]> git.neil.brown.name Git - history.git/commitdiff
From: <martin@meltin.net>
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 13 Mar 2004 17:07:59 +0000 (12:07 -0500)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 13 Mar 2004 17:07:59 +0000 (12:07 -0500)
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
include/linux/nfs_fs.h
net/ipv4/ipconfig.c

index b14a7bf3d6bfc6691259f2b0564fbbd3825aac4f..0f348c2ab7220b454d7030a0f3630dfafb9c2f4c 100644 (file)
@@ -165,37 +165,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.
  */
@@ -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;
 }
 
index 6686e0a84323b69d2b3c2112ec427e68b8d44776..47123702fbd5d8f89fcf117fbf14be5a5884c83f 100644 (file)
@@ -276,6 +276,9 @@ extern void nfs_end_attr_update(struct inode *);
 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
  */
index 1289eb6a8c89984828658838103d325d634e828b..a5322adb2be8d82292b36bf4b5ea136c1027ff28 100644 (file)
@@ -1188,6 +1188,40 @@ static struct file_operations pnp_seq_fops = {
 };
 #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.
  */
@@ -1195,6 +1229,7 @@ static struct file_operations pnp_seq_fops = {
 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.
         */