2002-09-12 02:04:02

by Martin Schwenke

[permalink] [raw]
Subject: [PATCH] Pull NFS server address off root_server_path

The following patch pulls an NFS server IP address off
root_server_path, if it is present. This is useful, for example, when
root_server_path is obtained via the DHCP root-path option. 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 change is backwards compatible; if the IP address is not present
then the existing behaviour takes place. It is very well tested and
has been accepted into 2.4 and 2.5-dj. FreeBSD allows root-path to
include an IP address in the above format and the description of
root-path in RFC2132 (DHCP Options ...) is general enough to allow an
IP address to be present.

Regards,
Martin

diff -r -u linux-2.5.34/fs/nfs/nfsroot.c linux-2.5.34.work/fs/nfs/nfsroot.c
--- linux-2.5.34/fs/nfs/nfsroot.c 2002-06-17 13:28:46.000000000 +1000
+++ linux-2.5.34.work/fs/nfs/nfsroot.c 2002-09-12 11:34:08.000000000 +1000
@@ -164,37 +164,6 @@


/*
- * 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)
@@ -346,7 +315,7 @@
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 = ipconfig_parse_addr(nfs_root_name);
return 1;
}

diff -r -u linux-2.5.34/include/net/ipconfig.h linux-2.5.34.work/include/net/ipconfig.h
--- linux-2.5.34/include/net/ipconfig.h 2001-05-02 13:59:24.000000000 +1000
+++ linux-2.5.34.work/include/net/ipconfig.h 2002-09-12 11:34:08.000000000 +1000
@@ -6,6 +6,9 @@
* Automatic IP Layer Configuration
*/

+#ifndef _NET_IPCONFIG_H
+#define _NET_IPCONFIG_H
+
/* The following are initdata: */

extern int ic_enable; /* Enable or disable the whole shebang */
@@ -36,3 +39,10 @@
#define IC_BOOTP 0x01 /* BOOTP (or DHCP, see below) */
#define IC_RARP 0x02 /* RARP */
#define IC_USE_DHCP 0x100 /* If on, use DHCP instead of BOOTP */
+
+#ifdef __KERNEL__
+/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
+extern u32 ipconfig_parse_addr(char *name); /*__init*/
+#endif /* __KERNEL */
+
+#endif
diff -r -u linux-2.5.34/net/ipv4/ipconfig.c linux-2.5.34.work/net/ipv4/ipconfig.c
--- linux-2.5.34/net/ipv4/ipconfig.c 2002-08-28 06:12:28.000000000 +1000
+++ linux-2.5.34.work/net/ipv4/ipconfig.c 2002-09-12 11:34:08.000000000 +1000
@@ -1128,12 +1128,47 @@
#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 ipconfig_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_create("pnp", 0, pnp_get_info);
@@ -1222,6 +1257,10 @@
ic_dev = ic_first_dev->dev;
}

+ addr = ipconfig_parse_addr(root_server_path);
+ if (root_server_addr == INADDR_NONE)
+ root_server_addr = addr;
+
/*
* Use defaults whereever applicable.
*/


2002-09-12 08:04:41

by Alan

[permalink] [raw]
Subject: Re: [PATCH] Pull NFS server address off root_server_path

You are probably much better using the initrd based dhcp client from
things like the LTSP project (ltsp.org) than the kernel one

2002-09-13 00:28:15

by Martin Schwenke

[permalink] [raw]
Subject: Re: [PATCH] Pull NFS server address off root_server_path

>>>>> "Alan" == Alan Cox <[email protected]> writes:

Alan> You are probably much better using the initrd based dhcp
Alan> client from things like the LTSP project (ltsp.org) than the
Alan> kernel one

That's probably true in the long term. For the short term, is the
initrd-based stuff working right now? I didn't think it was quite
there yet...

If the patch goes in now, I won't be terribly disappointed if it comes
back out, along with (most of) the rest of the ipconfig stuff, if the
initrd-based stuff works acceptably before the feature freeze...

I would think that if there's a chance that the ipconfig stuff will
stay in for 2.6, and this patch improves it, then it should probably
be merged. The patch has been in use at OzLabs for about 6 months
(since I moved the DHCP server off the NFS server :-) to help boot the
embedded boxes that David Gibson is doing bring-up work on.

peace & happiness,
martin

2002-09-13 01:27:08

by David Gibson

[permalink] [raw]
Subject: Re: [PATCH] Pull NFS server address off root_server_path

On Fri, Sep 13, 2002 at 10:28:29AM +1000, Martin Schwenke wrote:
> >>>>> "Alan" == Alan Cox <[email protected]> writes:
>
> Alan> You are probably much better using the initrd based dhcp
> Alan> client from things like the LTSP project (ltsp.org) than the
> Alan> kernel one
>
> That's probably true in the long term. For the short term, is the
> initrd-based stuff working right now? I didn't think it was quite
> there yet...

Well, initrd works (as opposed to the still-in-progress initramfs),
but setting up an image to do the DHCP, NFS mount and pivot_root is a
pain in the bum. LTSP is all i386 (afaict), which helps me not at
all.

> If the patch goes in now, I won't be terribly disappointed if it comes
> back out, along with (most of) the rest of the ipconfig stuff, if the
> initrd-based stuff works acceptably before the feature freeze...
>
> I would think that if there's a chance that the ipconfig stuff will
> stay in for 2.6, and this patch improves it, then it should probably
> be merged. The patch has been in use at OzLabs for about 6 months
> (since I moved the DHCP server off the NFS server :-) to help boot the
> embedded boxes that David Gibson is doing bring-up work on.

--
David Gibson | For every complex problem there is a
[email protected] | solution which is simple, neat and
| wrong.
http://www.ozlabs.org/people/dgibson

2002-09-13 13:09:29

by Alan

[permalink] [raw]
Subject: Re: [PATCH] Pull NFS server address off root_server_path

On Fri, 2002-09-13 at 01:28, Martin Schwenke wrote:
> That's probably true in the long term. For the short term, is the
> initrd-based stuff working right now? I didn't think it was quite
> there yet...

They've been using it for a long time

> I would think that if there's a chance that the ipconfig stuff will

I hope not 8)


2002-09-16 13:27:59

by Rob Landley

[permalink] [raw]
Subject: Re: [PATCH] Pull NFS server address off root_server_path

On Thursday 12 September 2002 09:31 pm, David Gibson wrote:
> On Fri, Sep 13, 2002 at 10:28:29AM +1000, Martin Schwenke wrote:
> > >>>>> "Alan" == Alan Cox <[email protected]> writes:
> >
> > Alan> You are probably much better using the initrd based dhcp
> > Alan> client from things like the LTSP project (ltsp.org) than the
> > Alan> kernel one
> >
> > That's probably true in the long term. For the short term, is the
> > initrd-based stuff working right now? I didn't think it was quite
> > there yet...
>
> Well, initrd works (as opposed to the still-in-progress initramfs),
> but setting up an image to do the DHCP, NFS mount and pivot_root is a
> pain in the bum.

Is it? Maybe this template will save a little time. You'll need to supply a
new linuxrc script, add your new executables, and possibly new libraries (you
know the drill: whereis thingy, ldd /path/thingy, see if the list has
anything new. The strip technique I'm using follows symlinks nicely...), and
you may not need losetup, of course. :)


echo --- "Creating image for bootloader ramdisk (initrd)..." &&

dd if=/dev/zero of=ramdisk.img bs=1024 count=3072 &&
mke2fs -b 1024 -F -m 0 ramdisk.img &&
tune2fs -c 0 -i 0 ramdisk.img &&
mkdir ramdisktmp &&
mount -o loop ramdisk.img ramdisktmp &&
cd ramdisktmp &&
rmdir lost+found &&
mkdir dev lib bin var &&

echo --- Creating device nodes... &&

mknod dev/hda1 b 3 1 &&
mknod dev/hda2 b 3 2 &&
mknod dev/hda3 b 3 3 &&
mknod dev/hda4 b 3 4 &&
mknod dev/loop0 b 7 0 &&
mknod dev/console c 5 1 &&
mknod dev/zero c 1 5 &&

echo --- Copying stripped executable files... &&

strip /bin/bash -o bin/bash &&
strip /bin/mount -o bin/mount &&
strip /sbin/losetup -o bin/losetup &&

echo --- Copying stripped libraries... &&

strip /lib/libc.so.6 -o lib/libc.so.6 &&
strip /lib/libncurses.so.5 -o lib/libncurses.so.5 &&
strip /lib/libdl.so.2 -o lib/libdl.so.2 &&
strip /lib/ld-linux.so.2 -o lib/ld-linux.so.2 &&

chmod +x lib/* &&

echo --- Writing ramdisk boot script... &&

cat > linuxrc << EOF &&
#!/bin/bash

mount -n /dev/$VAR /var
losetup /dev/loop0 /var/local/firmware/$DATE/zisofs.img
EOF
chmod +x linuxrc &&

echo --- Compressing ramdisk image... &&

cd .. &&
umount ramdisktmp &&
rmdir ramdisktmp &&
gzip -9 ramdisk.img

if [ $? -ne 0 ]; then exit 1; fi