From 8eecd1c2e5bc73d33f3a544751305679dbf88eb4 Mon Sep 17 00:00:00 2001 From: "Paulo Alcantara (SUSE)" Date: Tue, 16 Jul 2019 19:04:50 -0300 Subject: cifs: Add support for root file systems Introduce a new CONFIG_CIFS_ROOT option to handle root file systems over a SMB share. In order to mount the root file system during the init process, make cifs.ko perform non-blocking socket operations while mounting and accessing it. Cc: Steve French Reviewed-by: Aurelien Aptel Signed-off-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/cifsroot.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 fs/cifs/cifsroot.c (limited to 'fs/cifs/cifsroot.c') diff --git a/fs/cifs/cifsroot.c b/fs/cifs/cifsroot.c new file mode 100644 index 000000000000..8760d9cbf25e --- /dev/null +++ b/fs/cifs/cifsroot.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SMB root file system support + * + * Copyright (c) 2019 Paulo Alcantara + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_MNT_OPTS \ + "vers=1.0,cifsacl,mfsymlinks,rsize=1048576,wsize=65536,uid=0,gid=0," \ + "hard,rootfs" + +static char root_dev[2048] __initdata = ""; +static char root_opts[1024] __initdata = DEFAULT_MNT_OPTS; + +static __be32 __init parse_srvaddr(char *start, char *end) +{ + char addr[sizeof("aaa.bbb.ccc.ddd")]; + int i = 0; + + while (start < end && i < sizeof(addr) - 1) { + if (isdigit(*start) || *start == '.') + addr[i++] = *start; + start++; + } + addr[i] = '\0'; + return in_aton(addr); +} + +/* cifsroot=///[,options] */ +static int __init cifs_root_setup(char *line) +{ + char *s; + int len; + __be32 srvaddr = htonl(INADDR_NONE); + + ROOT_DEV = Root_CIFS; + + if (strlen(line) > 3 && line[0] == '/' && line[1] == '/') { + s = strchr(&line[2], '/'); + if (!s || s[1] == '\0') + return 1; + + s = strchrnul(s, ','); + len = s - line + 1; + if (len <= sizeof(root_dev)) { + strlcpy(root_dev, line, len); + srvaddr = parse_srvaddr(&line[2], s); + if (*s) { + snprintf(root_opts, sizeof(root_opts), "%s,%s", + DEFAULT_MNT_OPTS, s + 1); + } + } + } + + root_server_addr = srvaddr; + + return 1; +} + +__setup("cifsroot=", cifs_root_setup); + +int __init cifs_root_data(char **dev, char **opts) +{ + if (!root_dev[0] || root_server_addr == htonl(INADDR_NONE)) { + printk(KERN_ERR "Root-CIFS: no SMB server address\n"); + return -1; + } + + *dev = root_dev; + *opts = root_opts; + + return 0; +} -- cgit v1.2.3