* [PATCH 0/6] Update NFSROOT to use text-based mounts
@ 2010-05-11 17:15 Chuck Lever
[not found] ` <20100511170754.2167.72681.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
0 siblings, 1 reply; 8+ messages in thread
From: Chuck Lever @ 2010-05-11 17:15 UTC (permalink / raw)
To: linux-nfs
Here is a small patch set proposed for 2.6.35.
Now that the kernel NFS client does text-based mount option pro-
cessing and has its own MNT client, much of the code in nfsroot.c is
redundant. This series converts nfsroot.c to use mainline NFS client
mount option processing, and removes the redundant code.
Note that the default mount option settings for NFSROOT change with
this series. The defaults are now vers=3 and tcp. There is no
longer a default mntport setting of 627 (used if the server does not
have a running portmapper).
Some additional clean-ups are included, such as updating the in-kernel
documentation for NFSROOT, and adding a new kernel command-line
parameter that enables debugging messages during NFSROOT processing.
It would be good if others who use NFSROOT on a regular basis could
review and test these changes.
---
Chuck Lever (6):
SUNRPC: Remove rpcb_getport_sync()
NFS: Allow NFSROOT debugging messages to be enabled dynamically
NFS: Clean up nfsroot.c
NFS: Use super.c for NFSROOT mount option parsing
NFS: Clean up NFSROOT command line parsing
NFS: Remove \t from mount debugging message
Documentation/filesystems/nfs/nfsroot.txt | 22 +
Documentation/kernel-parameters.txt | 5
fs/nfs/mount_clnt.c | 2
fs/nfs/nfsroot.c | 566 +++++++++--------------------
include/linux/nfs_fs.h | 10 -
include/linux/sunrpc/clnt.h | 1
init/do_mounts.c | 12 -
net/sunrpc/rpcb_clnt.c | 51 ---
8 files changed, 209 insertions(+), 460 deletions(-)
--
Chuck Lever
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/6] NFS: Remove \t from mount debugging message
[not found] ` <20100511170754.2167.72681.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
@ 2010-05-11 17:16 ` Chuck Lever
2010-05-11 17:16 ` [PATCH 2/6] NFS: Clean up NFSROOT command line parsing Chuck Lever
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Chuck Lever @ 2010-05-11 17:16 UTC (permalink / raw)
To: linux-nfs
During boot, a random character is displayed instead of a tab.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/mount_clnt.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 59047f8..d610203 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -436,7 +436,7 @@ static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res)
for (i = 0; i < entries; i++) {
flavors[i] = ntohl(*p++);
- dprintk("NFS:\tflavor %u: %d\n", i, flavors[i]);
+ dprintk("NFS: auth flavor[%u]: %d\n", i, flavors[i]);
}
*count = i;
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/6] NFS: Clean up NFSROOT command line parsing
[not found] ` <20100511170754.2167.72681.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
2010-05-11 17:16 ` [PATCH 1/6] NFS: Remove \t from mount debugging message Chuck Lever
@ 2010-05-11 17:16 ` Chuck Lever
2010-05-11 17:16 ` [PATCH 3/6] NFS: Use super.c for NFSROOT mount option parsing Chuck Lever
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Chuck Lever @ 2010-05-11 17:16 UTC (permalink / raw)
To: linux-nfs
Clean up: To reduce confusion, rename nfs_root_name as nfs_root_parms,
as this buffer contains more than just the name of the remote server.
Introduce documenting comments around nfs_root_setup().
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/nfsroot.c | 32 +++++++++++++++++++++++---------
1 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 8c55b27..baed2aa 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -99,7 +99,7 @@
#define NFS_ROOT "/tftpboot/%s"
/* Parameters passed from the kernel command line */
-static char nfs_root_name[256] __initdata = "";
+static char nfs_root_parms[256] __initdata = "";
/* Address of NFS server */
static __be32 servaddr __initdata = 0;
@@ -369,7 +369,7 @@ static int __init root_nfs_init(void)
* be able to use the client IP address for the remote root
* directory (necessary for pure RARP booting).
*/
- if (root_nfs_name(nfs_root_name) < 0 ||
+ if (root_nfs_name(nfs_root_parms) < 0 ||
root_nfs_addr() < 0)
return -1;
@@ -380,23 +380,37 @@ static int __init root_nfs_init(void)
return 0;
}
-
/*
* Parse NFS server and directory information passed on the kernel
* command line.
+ *
+ * nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
+ *
+ * If there is a "%s" token in the <root-dir> string, it is replaced
+ * by the ASCII-representation of the client's IP address.
*/
static int __init nfs_root_setup(char *line)
{
ROOT_DEV = Root_NFS;
+
if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
- strlcpy(nfs_root_name, line, sizeof(nfs_root_name));
+ strlcpy(nfs_root_parms, line, sizeof(nfs_root_parms));
} else {
- int n = strlen(line) + sizeof(NFS_ROOT) - 1;
- if (n >= sizeof(nfs_root_name))
- line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0';
- sprintf(nfs_root_name, NFS_ROOT, line);
+ size_t n = strlen(line) + sizeof(NFS_ROOT) - 1;
+ if (n >= sizeof(nfs_root_parms))
+ line[sizeof(nfs_root_parms) - sizeof(NFS_ROOT) - 2] = '\0';
+ sprintf(nfs_root_parms, NFS_ROOT, line);
}
- root_server_addr = root_nfs_parse_addr(nfs_root_name);
+
+ /*
+ * Extract the IP address of the NFS server containing our
+ * root file system, if one was specified.
+ *
+ * Note: root_nfs_parse_addr() removes the server-ip from
+ * nfs_root_parms, if it exists.
+ */
+ root_server_addr = root_nfs_parse_addr(nfs_root_parms);
+
return 1;
}
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/6] NFS: Use super.c for NFSROOT mount option parsing
[not found] ` <20100511170754.2167.72681.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
2010-05-11 17:16 ` [PATCH 1/6] NFS: Remove \t from mount debugging message Chuck Lever
2010-05-11 17:16 ` [PATCH 2/6] NFS: Clean up NFSROOT command line parsing Chuck Lever
@ 2010-05-11 17:16 ` Chuck Lever
2010-05-11 17:16 ` [PATCH 4/6] NFS: Clean up nfsroot.c Chuck Lever
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Chuck Lever @ 2010-05-11 17:16 UTC (permalink / raw)
To: linux-nfs
Replace duplicate code in NFSROOT for mounting an NFS server on '/'
with logic that uses the existing mainline text-based logic in the NFS
client.
Add documenting comments where appropriate.
Note that this means NFSROOT mounts now use the same default settings
as v2/v3 mounts done via mount(2) from user space.
vers=3,tcp,rsize=<negotiated default>,wsize=<negotiated default>
As before, however, no version/protocol negotiation with the server is
done.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/nfsroot.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++--
include/linux/nfs_fs.h | 10 +--
init/do_mounts.c | 12 ++-
3 files changed, 187 insertions(+), 17 deletions(-)
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index baed2aa..fbc0f23 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -3,9 +3,10 @@
*
* Allow an NFS filesystem to be mounted as root. The way this works is:
* (1) Use the IP autoconfig mechanism to set local IP addresses and routes.
- * (2) Handle RPC negotiation with the system which replied to RARP or
- * was reported as a boot server by BOOTP or manually.
- * (3) The actual mounting is done later, when init() is running.
+ * (2) Construct the device string and the options string using DHCP
+ * option 17 and/or kernel command line options.
+ * (3) When mount_root() sets up the root file system, pass these strings
+ * to the NFS client's regular mount interface via sys_mount().
*
*
* Changes:
@@ -65,7 +66,8 @@
* Hua Qin : Support for mounting root file system via
* NFS over TCP.
* Fabian Frederick: Option parser rebuilt (using parser lib)
-*/
+ * Chuck Lever : Use super.c's text-based mount option parsing
+ */
#include <linux/types.h>
#include <linux/string.h>
@@ -101,11 +103,17 @@
/* Parameters passed from the kernel command line */
static char nfs_root_parms[256] __initdata = "";
+/* Text-based mount options passed to super.c */
+static char nfs_root_options[256] __initdata = "";
+
/* Address of NFS server */
static __be32 servaddr __initdata = 0;
/* Name of directory to mount */
-static char nfs_export_path[NFS_MAXPATHLEN] __initdata = { 0, };
+static char nfs_export_path[NFS_MAXPATHLEN] __initdata = "";
+
+/* server:export path string passed to super.c */
+static char nfs_root_device[NFS_MAXPATHLEN] __initdata = "";
/* NFS-related data */
static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */
@@ -535,7 +543,7 @@ static int __init root_nfs_get_handle(void)
* Get the NFS port numbers and file handle, and return the prepared 'data'
* argument for mount() if everything went OK. Return NULL otherwise.
*/
-void * __init nfs_root_data(void)
+void * __init old_nfs_root_data(void)
{
if (root_nfs_init() < 0
|| root_nfs_ports() < 0
@@ -544,3 +552,165 @@ void * __init nfs_root_data(void)
set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port));
return (void*)&nfs_data;
}
+
+static int __init root_nfs_copy(char *dest, const char *src,
+ const size_t destlen)
+{
+ if (strlcpy(dest, src, destlen) > destlen)
+ return -1;
+ return 0;
+}
+
+static int __init root_nfs_cat(char *dest, const char *src,
+ const size_t destlen)
+{
+ if (strlcat(dest, src, destlen) > destlen)
+ return -1;
+ return 0;
+}
+
+/*
+ * Parse out root export path and mount options from
+ * passed-in string @incoming.
+ *
+ * Copy the export path into @exppath.
+ */
+static int __init root_nfs_parse_options(char *incoming, char *exppath,
+ const size_t exppathlen)
+{
+ char *p;
+
+ /*
+ * Set the NFS remote path
+ */
+ p = strsep(&incoming, ",");
+ if (*p != '\0' && strcmp(p, "default") != 0)
+ if (root_nfs_copy(exppath, p, exppathlen))
+ return -1;
+
+ /*
+ * @incoming now points to the rest of the string; if it
+ * contains something, append it to our root options buffer
+ */
+ if (incoming != NULL && *incoming != '\0')
+ if (root_nfs_cat(nfs_root_options, incoming,
+ sizeof(nfs_root_options)))
+ return -1;
+
+ /*
+ * Possibly prepare for more options to be appended
+ */
+ if (nfs_root_options[0] != '\0' &&
+ nfs_root_options[strlen(nfs_root_options)] != ',')
+ if (root_nfs_cat(nfs_root_options, ",",
+ sizeof(nfs_root_options)))
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Decode the export directory path name and NFS options from
+ * the kernel command line. This has to be done late in order to
+ * use a dynamically acquired client IP address for the remote
+ * root directory path.
+ *
+ * Returns zero if successful; otherwise -1 is returned.
+ */
+static int __init root_nfs_data(char *cmdline)
+{
+ char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1];
+ int len, retval = -1;
+ char *tmp = NULL;
+ const size_t tmplen = sizeof(nfs_export_path);
+
+ tmp = kzalloc(tmplen, GFP_KERNEL);
+ if (tmp == NULL)
+ goto out_nomem;
+ strcpy(tmp, NFS_ROOT);
+
+ if (root_server_path[0] != '\0') {
+ dprintk("Root-NFS: DHCPv4 option 17: %s\n",
+ root_server_path);
+ if (root_nfs_parse_options(root_server_path, tmp, tmplen))
+ goto out_optionstoolong;
+ }
+
+ if (cmdline[0] != '\0') {
+ dprintk("Root-NFS: nfsroot=%s\n", cmdline);
+ if (root_nfs_parse_options(cmdline, tmp, tmplen))
+ goto out_optionstoolong;
+ }
+
+ /*
+ * Append mandatory options for nfsroot so they override
+ * what has come before
+ */
+ snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4",
+ &servaddr);
+ if (root_nfs_cat(nfs_root_options, addr_option,
+ sizeof(nfs_root_options)))
+ goto out_optionstoolong;
+
+ /*
+ * Set up nfs_root_device. For NFS mounts, this looks like
+ *
+ * server:/path
+ *
+ * At this point, utsname()->nodename contains our local
+ * IP address or hostname, set by ipconfig. If "%s" exists
+ * in tmp, substitute the nodename, then shovel the whole
+ * mess into nfs_root_device.
+ */
+ len = snprintf(nfs_export_path, sizeof(nfs_export_path),
+ tmp, utsname()->nodename);
+ if (len > (int)sizeof(nfs_export_path))
+ goto out_devnametoolong;
+ len = snprintf(nfs_root_device, sizeof(nfs_root_device),
+ "%pI4:%s", &servaddr, nfs_export_path);
+ if (len > (int)sizeof(nfs_root_device))
+ goto out_devnametoolong;
+
+ retval = 0;
+
+out:
+ kfree(tmp);
+ return retval;
+out_nomem:
+ printk(KERN_ERR "Root-NFS: could not allocate memory\n");
+ goto out;
+out_optionstoolong:
+ printk(KERN_ERR "Root-NFS: mount options string too long\n");
+ goto out;
+out_devnametoolong:
+ printk(KERN_ERR "Root-NFS: root device name too long.\n");
+ goto out;
+}
+
+/**
+ * nfs_root_data - Return prepared 'data' for NFSROOT mount
+ * @root_device: OUT: address of string containing NFSROOT device
+ * @root_data: OUT: address of string containing NFSROOT mount options
+ *
+ * Returns zero and sets @root_device and @root_data if successful,
+ * otherwise -1 is returned.
+ */
+int __init nfs_root_data(char **root_device, char **root_data)
+{
+#ifdef NFSROOT_DEBUG
+ nfs_debug |= NFSDBG_ROOT | NFSDBG_MOUNT;
+#endif /* NFSROOT_DEBUG */
+
+ servaddr = root_server_addr;
+ if (servaddr == htonl(INADDR_NONE)) {
+ printk(KERN_ERR "Root-NFS: no NFS server address\n");
+ return -1;
+ }
+
+ if (root_nfs_data(nfs_root_parms) < 0)
+ return -1;
+
+ *root_device = nfs_root_device;
+ *root_data = nfs_root_options;
+ return 0;
+}
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 07ce460..8d5e6cb 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -355,10 +355,14 @@ extern void put_nfs_open_context(struct nfs_open_context *ctx);
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
extern u64 nfs_compat_user_ino64(u64 fileid);
extern void nfs_fattr_init(struct nfs_fattr *fattr);
+extern unsigned long nfs_inc_attr_generation_counter(void);
+/*
+ * linux/fs/nfs/nfsroot.c
+ */
+extern int nfs_root_data(char **root_device, char **root_data); /*__init*/
/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
extern __be32 root_nfs_parse_addr(char *name); /*__init*/
-extern unsigned long nfs_inc_attr_generation_counter(void);
/*
* linux/fs/nfs/file.c
@@ -554,10 +558,6 @@ nfs_fileid_to_ino_t(u64 fileid)
return ino;
}
-/* NFS root */
-
-extern void * nfs_root_data(void);
-
#define nfs_wait_event(clnt, wq, condition) \
({ \
int __retval = wait_event_killable(wq, condition); \
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 02e3ca4..52387f1 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -291,13 +291,13 @@ out:
#ifdef CONFIG_ROOT_NFS
static int __init mount_nfs_root(void)
{
- void *data = nfs_root_data();
+ char *root_dev, *root_data;
- create_dev("/dev/root", ROOT_DEV);
- if (data &&
- do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0)
- return 1;
- return 0;
+ if (nfs_root_data(&root_dev, &root_data) != 0)
+ return 0;
+ if (do_mount_root(root_dev, "nfs", root_mountflags, root_data) != 0)
+ return 0;
+ return 1;
}
#endif
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/6] NFS: Clean up nfsroot.c
[not found] ` <20100511170754.2167.72681.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
` (2 preceding siblings ...)
2010-05-11 17:16 ` [PATCH 3/6] NFS: Use super.c for NFSROOT mount option parsing Chuck Lever
@ 2010-05-11 17:16 ` Chuck Lever
2010-05-11 17:17 ` [PATCH 5/6] NFS: Allow NFSROOT debugging messages to be enabled dynamically Chuck Lever
2010-05-11 17:17 ` [PATCH 6/6] SUNRPC: Remove rpcb_getport_sync() Chuck Lever
5 siblings, 0 replies; 8+ messages in thread
From: Chuck Lever @ 2010-05-11 17:16 UTC (permalink / raw)
To: linux-nfs
Clean up: now that mount option parsing for nfsroot is handled
in fs/nfs/super.c, remove code in fs/nfs/nfsroot.c that is no
longer used. This includes code that constructs the legacy
nfs_mount_data structure, and code that does a MNT call to the
server.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/nfsroot.c | 417 ------------------------------------------------------
1 files changed, 1 insertions(+), 416 deletions(-)
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index fbc0f23..51be225 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -71,22 +71,12 @@
#include <linux/types.h>
#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/fs.h>
#include <linux/init.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/xprtsock.h>
#include <linux/nfs.h>
#include <linux/nfs_fs.h>
-#include <linux/nfs_mount.h>
-#include <linux/in.h>
-#include <linux/major.h>
#include <linux/utsname.h>
-#include <linux/inet.h>
#include <linux/root_dev.h>
#include <net/ipconfig.h>
-#include <linux/parser.h>
#include "internal.h"
@@ -94,9 +84,6 @@
#undef NFSROOT_DEBUG
#define NFSDBG_FACILITY NFSDBG_ROOT
-/* Default port to use if server is not running a portmapper */
-#define NFS_MNT_PORT 627
-
/* Default path we try to mount. "%s" gets replaced by our IP address */
#define NFS_ROOT "/tftpboot/%s"
@@ -107,7 +94,7 @@ static char nfs_root_parms[256] __initdata = "";
static char nfs_root_options[256] __initdata = "";
/* Address of NFS server */
-static __be32 servaddr __initdata = 0;
+static __be32 servaddr __initdata = htonl(INADDR_NONE);
/* Name of directory to mount */
static char nfs_export_path[NFS_MAXPATHLEN] __initdata = "";
@@ -115,279 +102,6 @@ static char nfs_export_path[NFS_MAXPATHLEN] __initdata = "";
/* server:export path string passed to super.c */
static char nfs_root_device[NFS_MAXPATHLEN] __initdata = "";
-/* NFS-related data */
-static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */
-static int nfs_port __initdata = 0; /* Port to connect to for NFS */
-static int mount_port __initdata = 0; /* Mount daemon port number */
-
-
-/***************************************************************************
-
- Parsing of options
-
- ***************************************************************************/
-
-enum {
- /* Options that take integer arguments */
- Opt_port, Opt_rsize, Opt_wsize, Opt_timeo, Opt_retrans, Opt_acregmin,
- Opt_acregmax, Opt_acdirmin, Opt_acdirmax,
- /* Options that take no arguments */
- Opt_soft, Opt_hard, Opt_intr,
- Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac,
- Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
- Opt_acl, Opt_noacl,
- /* Error token */
- Opt_err
-};
-
-static const match_table_t tokens __initconst = {
- {Opt_port, "port=%u"},
- {Opt_rsize, "rsize=%u"},
- {Opt_wsize, "wsize=%u"},
- {Opt_timeo, "timeo=%u"},
- {Opt_retrans, "retrans=%u"},
- {Opt_acregmin, "acregmin=%u"},
- {Opt_acregmax, "acregmax=%u"},
- {Opt_acdirmin, "acdirmin=%u"},
- {Opt_acdirmax, "acdirmax=%u"},
- {Opt_soft, "soft"},
- {Opt_hard, "hard"},
- {Opt_intr, "intr"},
- {Opt_nointr, "nointr"},
- {Opt_posix, "posix"},
- {Opt_noposix, "noposix"},
- {Opt_cto, "cto"},
- {Opt_nocto, "nocto"},
- {Opt_ac, "ac"},
- {Opt_noac, "noac"},
- {Opt_lock, "lock"},
- {Opt_nolock, "nolock"},
- {Opt_v2, "nfsvers=2"},
- {Opt_v2, "v2"},
- {Opt_v3, "nfsvers=3"},
- {Opt_v3, "v3"},
- {Opt_udp, "proto=udp"},
- {Opt_udp, "udp"},
- {Opt_tcp, "proto=tcp"},
- {Opt_tcp, "tcp"},
- {Opt_acl, "acl"},
- {Opt_noacl, "noacl"},
- {Opt_err, NULL}
-
-};
-
-/*
- * Parse option string.
- */
-
-static int __init root_nfs_parse(char *name, char *buf)
-{
-
- char *p;
- substring_t args[MAX_OPT_ARGS];
- int option;
-
- if (!name)
- return 1;
-
- /* Set the NFS remote path */
- p = strsep(&name, ",");
- if (p[0] != '\0' && strcmp(p, "default") != 0)
- strlcpy(buf, p, NFS_MAXPATHLEN);
-
- while ((p = strsep (&name, ",")) != NULL) {
- int token;
- if (!*p)
- continue;
- token = match_token(p, tokens, args);
-
- /* %u tokens only. Beware if you add new tokens! */
- if (token < Opt_soft && match_int(&args[0], &option))
- return 0;
- switch (token) {
- case Opt_port:
- nfs_port = option;
- break;
- case Opt_rsize:
- nfs_data.rsize = option;
- break;
- case Opt_wsize:
- nfs_data.wsize = option;
- break;
- case Opt_timeo:
- nfs_data.timeo = option;
- break;
- case Opt_retrans:
- nfs_data.retrans = option;
- break;
- case Opt_acregmin:
- nfs_data.acregmin = option;
- break;
- case Opt_acregmax:
- nfs_data.acregmax = option;
- break;
- case Opt_acdirmin:
- nfs_data.acdirmin = option;
- break;
- case Opt_acdirmax:
- nfs_data.acdirmax = option;
- break;
- case Opt_soft:
- nfs_data.flags |= NFS_MOUNT_SOFT;
- break;
- case Opt_hard:
- nfs_data.flags &= ~NFS_MOUNT_SOFT;
- break;
- case Opt_intr:
- case Opt_nointr:
- break;
- case Opt_posix:
- nfs_data.flags |= NFS_MOUNT_POSIX;
- break;
- case Opt_noposix:
- nfs_data.flags &= ~NFS_MOUNT_POSIX;
- break;
- case Opt_cto:
- nfs_data.flags &= ~NFS_MOUNT_NOCTO;
- break;
- case Opt_nocto:
- nfs_data.flags |= NFS_MOUNT_NOCTO;
- break;
- case Opt_ac:
- nfs_data.flags &= ~NFS_MOUNT_NOAC;
- break;
- case Opt_noac:
- nfs_data.flags |= NFS_MOUNT_NOAC;
- break;
- case Opt_lock:
- nfs_data.flags &= ~NFS_MOUNT_NONLM;
- break;
- case Opt_nolock:
- nfs_data.flags |= NFS_MOUNT_NONLM;
- break;
- case Opt_v2:
- nfs_data.flags &= ~NFS_MOUNT_VER3;
- break;
- case Opt_v3:
- nfs_data.flags |= NFS_MOUNT_VER3;
- break;
- case Opt_udp:
- nfs_data.flags &= ~NFS_MOUNT_TCP;
- break;
- case Opt_tcp:
- nfs_data.flags |= NFS_MOUNT_TCP;
- break;
- case Opt_acl:
- nfs_data.flags &= ~NFS_MOUNT_NOACL;
- break;
- case Opt_noacl:
- nfs_data.flags |= NFS_MOUNT_NOACL;
- break;
- default:
- printk(KERN_WARNING "Root-NFS: unknown "
- "option: %s\n", p);
- return 0;
- }
- }
-
- return 1;
-}
-
-/*
- * Prepare the NFS data structure and parse all options.
- */
-static int __init root_nfs_name(char *name)
-{
- static char buf[NFS_MAXPATHLEN] __initdata;
- char *cp;
-
- /* Set some default values */
- memset(&nfs_data, 0, sizeof(nfs_data));
- nfs_port = -1;
- nfs_data.version = NFS_MOUNT_VERSION;
- nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */
- nfs_data.rsize = NFS_DEF_FILE_IO_SIZE;
- nfs_data.wsize = NFS_DEF_FILE_IO_SIZE;
- nfs_data.acregmin = NFS_DEF_ACREGMIN;
- nfs_data.acregmax = NFS_DEF_ACREGMAX;
- nfs_data.acdirmin = NFS_DEF_ACDIRMIN;
- nfs_data.acdirmax = NFS_DEF_ACDIRMAX;
- strcpy(buf, NFS_ROOT);
-
- /* Process options received from the remote server */
- root_nfs_parse(root_server_path, buf);
-
- /* Override them by options set on kernel command-line */
- root_nfs_parse(name, buf);
-
- cp = utsname()->nodename;
- if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
- printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
- return -1;
- }
- sprintf(nfs_export_path, buf, cp);
-
- return 1;
-}
-
-
-/*
- * Get NFS server address.
- */
-static int __init root_nfs_addr(void)
-{
- if ((servaddr = root_server_addr) == htonl(INADDR_NONE)) {
- printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n");
- return -1;
- }
-
- snprintf(nfs_data.hostname, sizeof(nfs_data.hostname),
- "%pI4", &servaddr);
- return 0;
-}
-
-/*
- * Tell the user what's going on.
- */
-#ifdef NFSROOT_DEBUG
-static void __init root_nfs_print(void)
-{
- printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n",
- nfs_export_path, nfs_data.hostname);
- printk(KERN_NOTICE "Root-NFS: rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
- nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans);
- printk(KERN_NOTICE "Root-NFS: acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n",
- nfs_data.acregmin, nfs_data.acregmax,
- nfs_data.acdirmin, nfs_data.acdirmax);
- printk(KERN_NOTICE "Root-NFS: nfsd port = %d, mountd port = %d, flags = %08x\n",
- nfs_port, mount_port, nfs_data.flags);
-}
-#endif
-
-
-static int __init root_nfs_init(void)
-{
-#ifdef NFSROOT_DEBUG
- nfs_debug |= NFSDBG_ROOT;
-#endif
-
- /*
- * Decode the root directory path name and NFS options from
- * the kernel command line. This has to go here in order to
- * be able to use the client IP address for the remote root
- * directory (necessary for pure RARP booting).
- */
- if (root_nfs_name(nfs_root_parms) < 0 ||
- root_nfs_addr() < 0)
- return -1;
-
-#ifdef NFSROOT_DEBUG
- root_nfs_print();
-#endif
-
- return 0;
-}
-
/*
* Parse NFS server and directory information passed on the kernel
* command line.
@@ -424,135 +138,6 @@ static int __init nfs_root_setup(char *line)
__setup("nfsroot=", nfs_root_setup);
-/***************************************************************************
-
- Routines to actually mount the root directory
-
- ***************************************************************************/
-
-/*
- * Construct sockaddr_in from address and port number.
- */
-static inline void
-set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
-{
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = addr;
- sin->sin_port = port;
-}
-
-/*
- * Query server portmapper for the port of a daemon program.
- */
-static int __init root_nfs_getport(int program, int version, int proto)
-{
- struct sockaddr_in sin;
-
- printk(KERN_NOTICE "Looking up port of RPC %d/%d on %pI4\n",
- program, version, &servaddr);
- set_sockaddr(&sin, servaddr, 0);
- return rpcb_getport_sync(&sin, program, version, proto);
-}
-
-
-/*
- * Use portmapper to find mountd and nfsd port numbers if not overriden
- * by the user. Use defaults if portmapper is not available.
- * XXX: Is there any nfs server with no portmapper?
- */
-static int __init root_nfs_ports(void)
-{
- int port;
- int nfsd_ver, mountd_ver;
- int nfsd_port, mountd_port;
- int proto;
-
- if (nfs_data.flags & NFS_MOUNT_VER3) {
- nfsd_ver = NFS3_VERSION;
- mountd_ver = NFS_MNT3_VERSION;
- nfsd_port = NFS_PORT;
- mountd_port = NFS_MNT_PORT;
- } else {
- nfsd_ver = NFS2_VERSION;
- mountd_ver = NFS_MNT_VERSION;
- nfsd_port = NFS_PORT;
- mountd_port = NFS_MNT_PORT;
- }
-
- proto = (nfs_data.flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
-
- if (nfs_port < 0) {
- if ((port = root_nfs_getport(NFS_PROGRAM, nfsd_ver, proto)) < 0) {
- printk(KERN_ERR "Root-NFS: Unable to get nfsd port "
- "number from server, using default\n");
- port = nfsd_port;
- }
- nfs_port = port;
- dprintk("Root-NFS: Portmapper on server returned %d "
- "as nfsd port\n", port);
- }
-
- if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) {
- printk(KERN_ERR "Root-NFS: Unable to get mountd port "
- "number from server, using default\n");
- port = mountd_port;
- }
- mount_port = port;
- dprintk("Root-NFS: mountd port is %d\n", port);
-
- return 0;
-}
-
-
-/*
- * Get a file handle from the server for the directory which is to be
- * mounted.
- */
-static int __init root_nfs_get_handle(void)
-{
- struct nfs_fh fh;
- struct sockaddr_in sin;
- unsigned int auth_flav_len = 0;
- struct nfs_mount_request request = {
- .sap = (struct sockaddr *)&sin,
- .salen = sizeof(sin),
- .dirpath = nfs_export_path,
- .version = (nfs_data.flags & NFS_MOUNT_VER3) ?
- NFS_MNT3_VERSION : NFS_MNT_VERSION,
- .protocol = (nfs_data.flags & NFS_MOUNT_TCP) ?
- XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
- .fh = &fh,
- .auth_flav_len = &auth_flav_len,
- };
- int status;
-
- set_sockaddr(&sin, servaddr, htons(mount_port));
- status = nfs_mount(&request);
- if (status < 0)
- printk(KERN_ERR "Root-NFS: Server returned error %d "
- "while mounting %s\n", status, nfs_export_path);
- else {
- nfs_data.root.size = fh.size;
- memcpy(nfs_data.root.data, fh.data, fh.size);
- }
-
- return status;
-}
-
-/*
- * Get the NFS port numbers and file handle, and return the prepared 'data'
- * argument for mount() if everything went OK. Return NULL otherwise.
- */
-void * __init old_nfs_root_data(void)
-{
- if (root_nfs_init() < 0
- || root_nfs_ports() < 0
- || root_nfs_get_handle() < 0)
- return NULL;
- set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port));
- return (void*)&nfs_data;
-}
-
static int __init root_nfs_copy(char *dest, const char *src,
const size_t destlen)
{
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/6] NFS: Allow NFSROOT debugging messages to be enabled dynamically
[not found] ` <20100511170754.2167.72681.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
` (3 preceding siblings ...)
2010-05-11 17:16 ` [PATCH 4/6] NFS: Clean up nfsroot.c Chuck Lever
@ 2010-05-11 17:17 ` Chuck Lever
2010-05-11 17:17 ` [PATCH 6/6] SUNRPC: Remove rpcb_getport_sync() Chuck Lever
5 siblings, 0 replies; 8+ messages in thread
From: Chuck Lever @ 2010-05-11 17:17 UTC (permalink / raw)
To: linux-nfs
As a convenience, introduce a kernel command line option to enable
NFSROOT debugging messages.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
Documentation/filesystems/nfs/nfsroot.txt | 22 ++++++++++++++++++++++
Documentation/kernel-parameters.txt | 5 ++++-
fs/nfs/nfsroot.c | 19 +++++++++++++------
3 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/Documentation/filesystems/nfs/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
index 3ba0b94..adc2248 100644
--- a/Documentation/filesystems/nfs/nfsroot.txt
+++ b/Documentation/filesystems/nfs/nfsroot.txt
@@ -157,6 +157,28 @@ ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
Default: any
+nfsrootdebug
+
+ This parameter enables debugging messages to appear in the kernel
+ log at boot time so that administrators can verify that the correct
+ NFS mount options, server address, and root path are passed to the
+ NFS client.
+
+
+rdinit=<executable file>
+
+ To specify which file contains the program that starts system
+ initialization, administrators can use this command line parameter.
+ The default value of this parameter is "/init". If the specified
+ file exists and the kernel can execute it, root filesystem related
+ kernel command line parameters, including `nfsroot=', are ignored.
+
+ A description of the process of mounting the root file system can be
+ found in:
+
+ Documentation/early-userspace/README
+
+
3.) Boot Loader
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 839b21b..26044a3 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1565,12 +1565,15 @@ and is between 256 and 4096 characters. It is defined in the file
Default value depends on CONFIG_NF_CT_ACCT that is
going to be removed in 2.6.29.
- nfsaddrs= [NFS]
+ nfsaddrs= [NFS] Deprecated. Use ip= instead.
See Documentation/filesystems/nfs/nfsroot.txt.
nfsroot= [NFS] nfs root filesystem for disk-less boxes.
See Documentation/filesystems/nfs/nfsroot.txt.
+ nfsrootdebug [NFS] enable nfsroot debugging messages.
+ See Documentation/filesystems/nfs/nfsroot.txt.
+
nfs.callback_tcpport=
[NFS] set the TCP port on which the NFSv4 callback
channel should listen.
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 51be225..b543122 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -67,6 +67,7 @@
* NFS over TCP.
* Fabian Frederick: Option parser rebuilt (using parser lib)
* Chuck Lever : Use super.c's text-based mount option parsing
+ * Chuck Lever : Add "nfsrootdebug".
*/
#include <linux/types.h>
@@ -80,8 +81,6 @@
#include "internal.h"
-/* Define this to allow debugging output */
-#undef NFSROOT_DEBUG
#define NFSDBG_FACILITY NFSDBG_ROOT
/* Default path we try to mount. "%s" gets replaced by our IP address */
@@ -103,6 +102,18 @@ static char nfs_export_path[NFS_MAXPATHLEN] __initdata = "";
static char nfs_root_device[NFS_MAXPATHLEN] __initdata = "";
/*
+ * When the "nfsrootdebug" kernel command line option is specified,
+ * enable debugging messages for NFSROOT.
+ */
+static int __init nfs_root_debug(char *__unused)
+{
+ nfs_debug |= NFSDBG_ROOT | NFSDBG_MOUNT;
+ return 1;
+}
+
+__setup("nfsrootdebug", nfs_root_debug);
+
+/*
* Parse NFS server and directory information passed on the kernel
* command line.
*
@@ -282,10 +293,6 @@ out_devnametoolong:
*/
int __init nfs_root_data(char **root_device, char **root_data)
{
-#ifdef NFSROOT_DEBUG
- nfs_debug |= NFSDBG_ROOT | NFSDBG_MOUNT;
-#endif /* NFSROOT_DEBUG */
-
servaddr = root_server_addr;
if (servaddr == htonl(INADDR_NONE)) {
printk(KERN_ERR "Root-NFS: no NFS server address\n");
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/6] SUNRPC: Remove rpcb_getport_sync()
[not found] ` <20100511170754.2167.72681.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
` (4 preceding siblings ...)
2010-05-11 17:17 ` [PATCH 5/6] NFS: Allow NFSROOT debugging messages to be enabled dynamically Chuck Lever
@ 2010-05-11 17:17 ` Chuck Lever
5 siblings, 0 replies; 8+ messages in thread
From: Chuck Lever @ 2010-05-11 17:17 UTC (permalink / raw)
To: linux-nfs
Clean up: rpcb_getport_sync() has no more users, so remove it.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
include/linux/sunrpc/clnt.h | 1 -
net/sunrpc/rpcb_clnt.c | 51 -------------------------------------------
2 files changed, 0 insertions(+), 52 deletions(-)
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 8ed9642..b9a2d4a 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -136,7 +136,6 @@ int rpcb_register(u32, u32, int, unsigned short);
int rpcb_v4_register(const u32 program, const u32 version,
const struct sockaddr *address,
const char *netid);
-int rpcb_getport_sync(struct sockaddr_in *, u32, u32, int);
void rpcb_getport_async(struct rpc_task *);
void rpc_call_start(struct rpc_task *);
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 1211053..4fd01f1 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -475,57 +475,6 @@ int rpcb_v4_register(const u32 program, const u32 version,
return -EAFNOSUPPORT;
}
-/**
- * rpcb_getport_sync - obtain the port for an RPC service on a given host
- * @sin: address of remote peer
- * @prog: RPC program number to bind
- * @vers: RPC version number to bind
- * @prot: transport protocol to use to make this request
- *
- * Return value is the requested advertised port number,
- * or a negative errno value.
- *
- * Called from outside the RPC client in a synchronous task context.
- * Uses default timeout parameters specified by underlying transport.
- *
- * XXX: Needs to support IPv6
- */
-int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
-{
- struct rpcbind_args map = {
- .r_prog = prog,
- .r_vers = vers,
- .r_prot = prot,
- .r_port = 0,
- };
- struct rpc_message msg = {
- .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT],
- .rpc_argp = &map,
- .rpc_resp = &map,
- };
- struct rpc_clnt *rpcb_clnt;
- int status;
-
- dprintk("RPC: %s(%pI4, %u, %u, %d)\n",
- __func__, &sin->sin_addr.s_addr, prog, vers, prot);
-
- rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
- sizeof(*sin), prot, RPCBVERS_2);
- if (IS_ERR(rpcb_clnt))
- return PTR_ERR(rpcb_clnt);
-
- status = rpc_call_sync(rpcb_clnt, &msg, 0);
- rpc_shutdown_client(rpcb_clnt);
-
- if (status >= 0) {
- if (map.r_port != 0)
- return map.r_port;
- status = -EACCES;
- }
- return status;
-}
-EXPORT_SYMBOL_GPL(rpcb_getport_sync);
-
static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
{
struct rpc_message msg = {
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/6] NFS: Use super.c for NFSROOT mount option parsing
2010-09-10 20:03 [PATCH 0/6] Replace NFSROOT mount option parsing Chuck Lever
@ 2010-09-10 20:03 ` Chuck Lever
0 siblings, 0 replies; 8+ messages in thread
From: Chuck Lever @ 2010-09-10 20:03 UTC (permalink / raw)
To: trond.myklebust; +Cc: linux-nfs
Replace duplicate code in NFSROOT for mounting an NFS server on '/'
with logic that uses the existing mainline text-based logic in the NFS
client.
Add documenting comments where appropriate.
Note that this means NFSROOT mounts now use the same default settings
as v2/v3 mounts done via mount(2) from user space.
vers=3,tcp,rsize=<negotiated default>,wsize=<negotiated default>
As before, however, no version/protocol negotiation with the server is
done.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/nfsroot.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++--
include/linux/nfs_fs.h | 10 +--
init/do_mounts.c | 12 ++-
3 files changed, 187 insertions(+), 17 deletions(-)
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 169b679..cb4a6bd 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -3,9 +3,10 @@
*
* Allow an NFS filesystem to be mounted as root. The way this works is:
* (1) Use the IP autoconfig mechanism to set local IP addresses and routes.
- * (2) Handle RPC negotiation with the system which replied to RARP or
- * was reported as a boot server by BOOTP or manually.
- * (3) The actual mounting is done later, when init() is running.
+ * (2) Construct the device string and the options string using DHCP
+ * option 17 and/or kernel command line options.
+ * (3) When mount_root() sets up the root file system, pass these strings
+ * to the NFS client's regular mount interface via sys_mount().
*
*
* Changes:
@@ -65,7 +66,8 @@
* Hua Qin : Support for mounting root file system via
* NFS over TCP.
* Fabian Frederick: Option parser rebuilt (using parser lib)
-*/
+ * Chuck Lever : Use super.c's text-based mount option parsing
+ */
#include <linux/types.h>
#include <linux/string.h>
@@ -101,11 +103,17 @@
/* Parameters passed from the kernel command line */
static char nfs_root_parms[256] __initdata = "";
+/* Text-based mount options passed to super.c */
+static char nfs_root_options[256] __initdata = "";
+
/* Address of NFS server */
static __be32 servaddr __initdata = 0;
/* Name of directory to mount */
-static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = { 0, };
+static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = "";
+
+/* server:export path string passed to super.c */
+static char nfs_root_device[NFS_MAXPATHLEN + 1] __initdata = "";
/* NFS-related data */
static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */
@@ -537,7 +545,7 @@ out:
* Get the NFS port numbers and file handle, and return the prepared 'data'
* argument for mount() if everything went OK. Return NULL otherwise.
*/
-void * __init nfs_root_data(void)
+void * __init old_nfs_root_data(void)
{
if (root_nfs_init() < 0
|| root_nfs_ports() < 0
@@ -546,3 +554,165 @@ void * __init nfs_root_data(void)
set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port));
return (void*)&nfs_data;
}
+
+static int __init root_nfs_copy(char *dest, const char *src,
+ const size_t destlen)
+{
+ if (strlcpy(dest, src, destlen) > destlen)
+ return -1;
+ return 0;
+}
+
+static int __init root_nfs_cat(char *dest, const char *src,
+ const size_t destlen)
+{
+ if (strlcat(dest, src, destlen) > destlen)
+ return -1;
+ return 0;
+}
+
+/*
+ * Parse out root export path and mount options from
+ * passed-in string @incoming.
+ *
+ * Copy the export path into @exppath.
+ */
+static int __init root_nfs_parse_options(char *incoming, char *exppath,
+ const size_t exppathlen)
+{
+ char *p;
+
+ /*
+ * Set the NFS remote path
+ */
+ p = strsep(&incoming, ",");
+ if (*p != '\0' && strcmp(p, "default") != 0)
+ if (root_nfs_copy(exppath, p, exppathlen))
+ return -1;
+
+ /*
+ * @incoming now points to the rest of the string; if it
+ * contains something, append it to our root options buffer
+ */
+ if (incoming != NULL && *incoming != '\0')
+ if (root_nfs_cat(nfs_root_options, incoming,
+ sizeof(nfs_root_options)))
+ return -1;
+
+ /*
+ * Possibly prepare for more options to be appended
+ */
+ if (nfs_root_options[0] != '\0' &&
+ nfs_root_options[strlen(nfs_root_options)] != ',')
+ if (root_nfs_cat(nfs_root_options, ",",
+ sizeof(nfs_root_options)))
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Decode the export directory path name and NFS options from
+ * the kernel command line. This has to be done late in order to
+ * use a dynamically acquired client IP address for the remote
+ * root directory path.
+ *
+ * Returns zero if successful; otherwise -1 is returned.
+ */
+static int __init root_nfs_data(char *cmdline)
+{
+ char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1];
+ int len, retval = -1;
+ char *tmp = NULL;
+ const size_t tmplen = sizeof(nfs_export_path);
+
+ tmp = kzalloc(tmplen, GFP_KERNEL);
+ if (tmp == NULL)
+ goto out_nomem;
+ strcpy(tmp, NFS_ROOT);
+
+ if (root_server_path[0] != '\0') {
+ dprintk("Root-NFS: DHCPv4 option 17: %s\n",
+ root_server_path);
+ if (root_nfs_parse_options(root_server_path, tmp, tmplen))
+ goto out_optionstoolong;
+ }
+
+ if (cmdline[0] != '\0') {
+ dprintk("Root-NFS: nfsroot=%s\n", cmdline);
+ if (root_nfs_parse_options(cmdline, tmp, tmplen))
+ goto out_optionstoolong;
+ }
+
+ /*
+ * Append mandatory options for nfsroot so they override
+ * what has come before
+ */
+ snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4",
+ &servaddr);
+ if (root_nfs_cat(nfs_root_options, addr_option,
+ sizeof(nfs_root_options)))
+ goto out_optionstoolong;
+
+ /*
+ * Set up nfs_root_device. For NFS mounts, this looks like
+ *
+ * server:/path
+ *
+ * At this point, utsname()->nodename contains our local
+ * IP address or hostname, set by ipconfig. If "%s" exists
+ * in tmp, substitute the nodename, then shovel the whole
+ * mess into nfs_root_device.
+ */
+ len = snprintf(nfs_export_path, sizeof(nfs_export_path),
+ tmp, utsname()->nodename);
+ if (len > (int)sizeof(nfs_export_path))
+ goto out_devnametoolong;
+ len = snprintf(nfs_root_device, sizeof(nfs_root_device),
+ "%pI4:%s", &servaddr, nfs_export_path);
+ if (len > (int)sizeof(nfs_root_device))
+ goto out_devnametoolong;
+
+ retval = 0;
+
+out:
+ kfree(tmp);
+ return retval;
+out_nomem:
+ printk(KERN_ERR "Root-NFS: could not allocate memory\n");
+ goto out;
+out_optionstoolong:
+ printk(KERN_ERR "Root-NFS: mount options string too long\n");
+ goto out;
+out_devnametoolong:
+ printk(KERN_ERR "Root-NFS: root device name too long.\n");
+ goto out;
+}
+
+/**
+ * nfs_root_data - Return prepared 'data' for NFSROOT mount
+ * @root_device: OUT: address of string containing NFSROOT device
+ * @root_data: OUT: address of string containing NFSROOT mount options
+ *
+ * Returns zero and sets @root_device and @root_data if successful,
+ * otherwise -1 is returned.
+ */
+int __init nfs_root_data(char **root_device, char **root_data)
+{
+#ifdef NFSROOT_DEBUG
+ nfs_debug |= NFSDBG_ROOT | NFSDBG_MOUNT;
+#endif /* NFSROOT_DEBUG */
+
+ servaddr = root_server_addr;
+ if (servaddr == htonl(INADDR_NONE)) {
+ printk(KERN_ERR "Root-NFS: no NFS server address\n");
+ return -1;
+ }
+
+ if (root_nfs_data(nfs_root_parms) < 0)
+ return -1;
+
+ *root_device = nfs_root_device;
+ *root_data = nfs_root_options;
+ return 0;
+}
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 508f8cf..2a18f15 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -364,6 +364,7 @@ extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ct
extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
extern u64 nfs_compat_user_ino64(u64 fileid);
extern void nfs_fattr_init(struct nfs_fattr *fattr);
+extern unsigned long nfs_inc_attr_generation_counter(void);
extern struct nfs_fattr *nfs_alloc_fattr(void);
@@ -379,9 +380,12 @@ static inline void nfs_free_fhandle(const struct nfs_fh *fh)
kfree(fh);
}
+/*
+ * linux/fs/nfs/nfsroot.c
+ */
+extern int nfs_root_data(char **root_device, char **root_data); /*__init*/
/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
extern __be32 root_nfs_parse_addr(char *name); /*__init*/
-extern unsigned long nfs_inc_attr_generation_counter(void);
/*
* linux/fs/nfs/file.c
@@ -584,10 +588,6 @@ nfs_fileid_to_ino_t(u64 fileid)
return ino;
}
-/* NFS root */
-
-extern void * nfs_root_data(void);
-
#define nfs_wait_event(clnt, wq, condition) \
({ \
int __retval = wait_event_killable(wq, condition); \
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 02e3ca4..52387f1 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -291,13 +291,13 @@ out:
#ifdef CONFIG_ROOT_NFS
static int __init mount_nfs_root(void)
{
- void *data = nfs_root_data();
+ char *root_dev, *root_data;
- create_dev("/dev/root", ROOT_DEV);
- if (data &&
- do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0)
- return 1;
- return 0;
+ if (nfs_root_data(&root_dev, &root_data) != 0)
+ return 0;
+ if (do_mount_root(root_dev, "nfs", root_mountflags, root_data) != 0)
+ return 0;
+ return 1;
}
#endif
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-09-10 20:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-11 17:15 [PATCH 0/6] Update NFSROOT to use text-based mounts Chuck Lever
[not found] ` <20100511170754.2167.72681.stgit-RytpoXr2tKZ9HhUboXbp9zCvJB+x5qRC@public.gmane.org>
2010-05-11 17:16 ` [PATCH 1/6] NFS: Remove \t from mount debugging message Chuck Lever
2010-05-11 17:16 ` [PATCH 2/6] NFS: Clean up NFSROOT command line parsing Chuck Lever
2010-05-11 17:16 ` [PATCH 3/6] NFS: Use super.c for NFSROOT mount option parsing Chuck Lever
2010-05-11 17:16 ` [PATCH 4/6] NFS: Clean up nfsroot.c Chuck Lever
2010-05-11 17:17 ` [PATCH 5/6] NFS: Allow NFSROOT debugging messages to be enabled dynamically Chuck Lever
2010-05-11 17:17 ` [PATCH 6/6] SUNRPC: Remove rpcb_getport_sync() Chuck Lever
-- strict thread matches above, loose matches on Subject: below --
2010-09-10 20:03 [PATCH 0/6] Replace NFSROOT mount option parsing Chuck Lever
2010-09-10 20:03 ` [PATCH 3/6] NFS: Use super.c for " Chuck Lever
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).