From: Forward-port from 2.4: The following patch pulls an NFS server IP address off root_server_path (handed out via the DHCP root-path option), if it is present. For example, you can do this sort of thing in dhcpd.conf: root-path = 192.168.1.33:/tftpboot/yip.zImage This lets you mount your root filesystem off a different machine than you booted from, without needing to use kernel command-line parameters. The patch appears to be backwards compatible. RFC2132 says this about the root-path option: This option specifies the path-name that contains the client's root disk. The path is formatted as a character string consisting of characters from the NVT ASCII character set. This is sufficiently vague to allow the path-name to include an IP-address. Also, I found some documentation for FreeBSD saying it does this too, so it must be right, because those FreeBSD guys are really smart... :-) The only downside of the patch is that the summary that ipconfig prints can be a little odd when the kernel command line overrides whatever ipconfig gets from (say) DHCP. The address from the kernel command line seems to get stripped off early, so ipconfig reports it, but it doesn't report the kernel command line NFS path, since that's handled a bit later... This small cosmetic problem looks difficult to "fix" without rewriting quite a bit of stuff... --- fs/nfs/nfsroot.c | 33 +-------------------------------- include/linux/nfs_fs.h | 3 +++ net/ipv4/ipconfig.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 32 deletions(-) diff -puN fs/nfs/nfsroot.c~nfs-server-in-root_server_path fs/nfs/nfsroot.c --- 25/fs/nfs/nfsroot.c~nfs-server-in-root_server_path 2004-02-28 18:11:44.000000000 -0800 +++ 25-akpm/fs/nfs/nfsroot.c 2004-02-28 18:11:44.000000000 -0800 @@ -166,37 +166,6 @@ static struct nfs_bool_opts { /* - * Extract IP address from the parameter string if needed. Note that we - * need to have root_server_addr set _before_ IPConfig gets called as it - * can override it. - */ -static void __init root_nfs_parse_addr(char *name) -{ - int octets = 0; - char *cp, *cq; - - cp = cq = name; - while (octets < 4) { - while (*cp >= '0' && *cp <= '9') - cp++; - if (cp == cq || cp - cq > 3) - break; - if (*cp == '.' || octets == 3) - octets++; - if (octets < 4) - cp++; - cq = cp; - } - if (octets == 4 && (*cp == ':' || *cp == '\0')) { - if (*cp == ':') - *cp++ = '\0'; - root_server_addr = in_aton(name); - strcpy(name, cp); - } -} - - -/* * Parse option string. */ static void __init root_nfs_parse(char *name, char *buf) @@ -345,7 +314,7 @@ int __init nfs_root_setup(char *line) line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0'; sprintf(nfs_root_name, NFS_ROOT, line); } - root_nfs_parse_addr(nfs_root_name); + root_server_addr = root_nfs_parse_addr(nfs_root_name); return 1; } diff -puN include/linux/nfs_fs.h~nfs-server-in-root_server_path include/linux/nfs_fs.h --- 25/include/linux/nfs_fs.h~nfs-server-in-root_server_path 2004-02-28 18:11:44.000000000 -0800 +++ 25-akpm/include/linux/nfs_fs.h 2004-02-28 18:11:44.000000000 -0800 @@ -276,6 +276,9 @@ extern void nfs_end_attr_update(struct i extern void nfs_begin_data_update(struct inode *); extern void nfs_end_data_update(struct inode *); +/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */ +extern u32 root_nfs_parse_addr(char *name); /*__init*/ + /* * linux/fs/nfs/file.c */ diff -puN net/ipv4/ipconfig.c~nfs-server-in-root_server_path net/ipv4/ipconfig.c --- 25/net/ipv4/ipconfig.c~nfs-server-in-root_server_path 2004-02-28 18:11:44.000000000 -0800 +++ 25-akpm/net/ipv4/ipconfig.c 2004-02-28 18:11:44.000000000 -0800 @@ -1189,12 +1189,47 @@ static struct file_operations pnp_seq_fo #endif /* CONFIG_PROC_FS */ /* + * Extract IP address from the parameter string if needed. Note that we + * need to have root_server_addr set _before_ IPConfig gets called as it + * can override it. + */ +u32 __init root_nfs_parse_addr(char *name) +{ + u32 addr; + int octets = 0; + char *cp, *cq; + + cp = cq = name; + while (octets < 4) { + while (*cp >= '0' && *cp <= '9') + cp++; + if (cp == cq || cp - cq > 3) + break; + if (*cp == '.' || octets == 3) + octets++; + if (octets < 4) + cp++; + cq = cp; + } + if (octets == 4 && (*cp == ':' || *cp == '\0')) { + if (*cp == ':') + *cp++ = '\0'; + addr = in_aton(name); + strcpy(name, cp); + } else + addr = INADDR_NONE; + + return addr; +} + +/* * IP Autoconfig dispatcher. */ static int __init ip_auto_config(void) { unsigned long jiff; + u32 addr; #ifdef CONFIG_PROC_FS proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops); @@ -1283,6 +1318,10 @@ static int __init ip_auto_config(void) ic_dev = ic_first_dev->dev; } + addr = root_nfs_parse_addr(root_server_path); + if (root_server_addr == INADDR_NONE) + root_server_addr = addr; + /* * Use defaults whereever applicable. */ _