Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Sep 2010 01:02:54 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r212716 - stable/8/sys/nfsclient
Message-ID:  <201009160102.o8G12sJT056347@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Thu Sep 16 01:02:53 2010
New Revision: 212716
URL: http://svn.freebsd.org/changeset/base/212716

Log:
  MFC: r212123
  Modify nfs_diskless.c to recognize the environment variable
  boot.nfsroot.nfshandlelen and set the diskless root fs to
  use NFSv3 and this file handle length when it is set. If
  this environment variable is not set, the diskless root fs
  will use NFSv2 and the same defaults as before. This fixes
  the problem where the diskless nfs root fs had to be on a
  FreeBSD server for NFSv3 to work, because it did not know
  the correct file handle length and assumed the size used
  by FreeBSD.

Modified:
  stable/8/sys/nfsclient/nfs_diskless.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/nfsclient/nfs_diskless.c
==============================================================================
--- stable/8/sys/nfsclient/nfs_diskless.c	Thu Sep 16 00:22:25 2010	(r212715)
+++ stable/8/sys/nfsclient/nfs_diskless.c	Thu Sep 16 01:02:53 2010	(r212716)
@@ -58,7 +58,7 @@ __FBSDID("$FreeBSD$");
 
 static int inaddr_to_sockaddr(char *ev, struct sockaddr_in *sa);
 static int hwaddr_to_sockaddr(char *ev, struct sockaddr_dl *sa);
-static int decode_nfshandle(char *ev, u_char *fh);
+static int decode_nfshandle(char *ev, u_char *fh, int maxfh);
 
 /*
  * Validate/sanity check a rsize/wsize parameter.
@@ -143,20 +143,37 @@ nfs_parse_options(const char *envopts, s
  * boot.nfsroot.server		IP address of root filesystem server
  * boot.nfsroot.path		path of the root filesystem on server
  * boot.nfsroot.nfshandle	NFS handle for root filesystem on server
+ * boot.nfsroot.nfshandlelen	and length of this handle (for NFSv3 only)
  * boot.nfsroot.options		NFS options for the root filesystem
  */
 void
 nfs_setup_diskless(void)
 {
 	struct nfs_diskless *nd = &nfs_diskless;
+	struct nfsv3_diskless *nd3 = &nfsv3_diskless;
 	struct ifnet *ifp;
 	struct ifaddr *ifa;
 	struct sockaddr_dl *sdl, ourdl;
 	struct sockaddr_in myaddr, netmask;
 	char *cp;
+	int cnt, fhlen, is_nfsv3;
+	uint32_t len;
 
-	if (nfs_diskless_valid)
+	if (nfs_diskless_valid != 0)
 		return;
+
+	/* get handle size. If this succeeds, it's an NFSv3 setup. */
+	if ((cp = getenv("boot.nfsroot.nfshandlelen")) != NULL) {
+		cnt = sscanf(cp, "%d", &len);
+		freeenv(cp);
+		if (cnt != 1 || len == 0 || len > NFSX_V3FHMAX) {
+			printf("nfs_diskless: bad NFS handle len\n");
+			return;
+		}
+		nd3->root_fhsize = len;
+		is_nfsv3 = 1;
+	} else
+		is_nfsv3 = 0;
 	/* set up interface */
 	if (inaddr_to_sockaddr("boot.netif.ip", &myaddr))
 		return;
@@ -164,11 +181,21 @@ nfs_setup_diskless(void)
 		printf("nfs_diskless: no netmask\n");
 		return;
 	}
-	bcopy(&myaddr, &nd->myif.ifra_addr, sizeof(myaddr));
-	bcopy(&myaddr, &nd->myif.ifra_broadaddr, sizeof(myaddr));
-	((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr =
-		myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr;
-	bcopy(&netmask, &nd->myif.ifra_mask, sizeof(netmask));
+	if (is_nfsv3 != 0) {
+		bcopy(&myaddr, &nd3->myif.ifra_addr, sizeof(myaddr));
+		bcopy(&myaddr, &nd3->myif.ifra_broadaddr, sizeof(myaddr));
+		((struct sockaddr_in *) 
+		   &nd3->myif.ifra_broadaddr)->sin_addr.s_addr =
+		    myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr;
+		bcopy(&netmask, &nd3->myif.ifra_mask, sizeof(netmask));
+	} else {
+		bcopy(&myaddr, &nd->myif.ifra_addr, sizeof(myaddr));
+		bcopy(&myaddr, &nd->myif.ifra_broadaddr, sizeof(myaddr));
+		((struct sockaddr_in *) 
+		   &nd->myif.ifra_broadaddr)->sin_addr.s_addr =
+		    myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr;
+		bcopy(&netmask, &nd->myif.ifra_mask, sizeof(netmask));
+	}
 
 	if (hwaddr_to_sockaddr("boot.netif.hwaddr", &ourdl)) {
 		printf("nfs_diskless: no hardware address\n");
@@ -196,46 +223,94 @@ nfs_setup_diskless(void)
 	return;	/* no matching interface */
 match_done:
 	setenv("boot.netif.name", ifp->if_xname);
-	strlcpy(nd->myif.ifra_name, ifp->if_xname, sizeof(nd->myif.ifra_name));
+	if (is_nfsv3 != 0) {
+		strlcpy(nd3->myif.ifra_name, ifp->if_xname,
+		    sizeof(nd3->myif.ifra_name));
 	
-	/* set up gateway */
-	inaddr_to_sockaddr("boot.netif.gateway", &nd->mygateway);
+		/* set up gateway */
+		inaddr_to_sockaddr("boot.netif.gateway", &nd3->mygateway);
 
-	/* set up root mount */
-	nd->root_args.rsize = 8192;		/* XXX tunable? */
-	nd->root_args.wsize = 8192;
-	nd->root_args.sotype = SOCK_STREAM;
-	nd->root_args.flags = (NFSMNT_NFSV3 | NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT);
-	if (inaddr_to_sockaddr("boot.nfsroot.server", &nd->root_saddr)) {
-		printf("nfs_diskless: no server\n");
-		return;
-	}
-	nd->root_saddr.sin_port = htons(NFS_PORT);
-	if (decode_nfshandle("boot.nfsroot.nfshandle", &nd->root_fh[0]) == 0) {
-		printf("nfs_diskless: no NFS handle\n");
-		return;
-	}
-	if ((cp = getenv("boot.nfsroot.path")) != NULL) {
-		strncpy(nd->root_hostnam, cp, MNAMELEN - 1);
-		freeenv(cp);
-	}
-	if ((cp = getenv("boot.nfsroot.options")) != NULL) {
-		struct nfs_args args;
+		/* set up root mount */
+		nd3->root_args.rsize = 32768;		/* XXX tunable? */
+		nd3->root_args.wsize = 32768;
+		nd3->root_args.sotype = SOCK_STREAM;
+		nd3->root_args.flags = (NFSMNT_NFSV3 | NFSMNT_WSIZE |
+		    NFSMNT_RSIZE | NFSMNT_RESVPORT);
+		if (inaddr_to_sockaddr("boot.nfsroot.server",
+		    &nd3->root_saddr)) {
+			printf("nfs_diskless: no server\n");
+			return;
+		}
+		nd3->root_saddr.sin_port = htons(NFS_PORT);
+		fhlen = decode_nfshandle("boot.nfsroot.nfshandle",
+		    &nd3->root_fh[0], NFSX_V3FHMAX);
+		if (fhlen == 0) {
+			printf("nfs_diskless: no NFS handle\n");
+			return;
+		}
+		if (fhlen != nd3->root_fhsize) {
+			printf("nfs_diskless: bad NFS handle len=%d\n", fhlen);
+			return;
+		}
+		if ((cp = getenv("boot.nfsroot.path")) != NULL) {
+			strncpy(nd3->root_hostnam, cp, MNAMELEN - 1);
+			freeenv(cp);
+		}
+		if ((cp = getenv("boot.nfsroot.options")) != NULL) {
+			nfs_parse_options(cp, &nd3->root_args);
+			freeenv(cp);
+		}
+	
+		nfs_diskless_valid = 3;
+	} else {
+		strlcpy(nd->myif.ifra_name, ifp->if_xname,
+		    sizeof(nd->myif.ifra_name));
+	
+		/* set up gateway */
+		inaddr_to_sockaddr("boot.netif.gateway", &nd->mygateway);
 
-		/* XXX yech, convert between old and current arg format */
-		args.flags = nd->root_args.flags;
-		args.sotype = nd->root_args.sotype;
-		args.rsize = nd->root_args.rsize;
-		args.wsize = nd->root_args.wsize;
-		nfs_parse_options(cp, &args);
-		nd->root_args.flags = args.flags;
-		nd->root_args.sotype = args.sotype;
-		nd->root_args.rsize = args.rsize;
-		nd->root_args.wsize = args.wsize;
-		freeenv(cp);
+		/* set up root mount */
+		nd->root_args.rsize = 8192;		/* XXX tunable? */
+		nd->root_args.wsize = 8192;
+		nd->root_args.sotype = SOCK_STREAM;
+		nd->root_args.flags = (NFSMNT_WSIZE |
+		    NFSMNT_RSIZE | NFSMNT_RESVPORT);
+		if (inaddr_to_sockaddr("boot.nfsroot.server",
+		    &nd->root_saddr)) {
+			printf("nfs_diskless: no server\n");
+			return;
+		}
+		nd->root_saddr.sin_port = htons(NFS_PORT);
+		if (decode_nfshandle("boot.nfsroot.nfshandle",
+		    &nd->root_fh[0], NFSX_V2FH) == 0) {
+			printf("nfs_diskless: no NFS handle\n");
+			return;
+		}
+		if ((cp = getenv("boot.nfsroot.path")) != NULL) {
+			strncpy(nd->root_hostnam, cp, MNAMELEN - 1);
+			freeenv(cp);
+		}
+		if ((cp = getenv("boot.nfsroot.options")) != NULL) {
+			struct nfs_args args;
+	
+			/*
+			 * XXX yech, convert between old and current
+			 * arg format
+			 */
+			args.flags = nd->root_args.flags;
+			args.sotype = nd->root_args.sotype;
+			args.rsize = nd->root_args.rsize;
+			args.wsize = nd->root_args.wsize;
+			nfs_parse_options(cp, &args);
+			nd->root_args.flags = args.flags;
+			nd->root_args.sotype = args.sotype;
+			nd->root_args.rsize = args.rsize;
+			nd->root_args.wsize = args.wsize;
+			freeenv(cp);
+		}
+	
+		nfs_diskless_valid = 1;
 	}
-
-	nfs_diskless_valid = 1;
 }
 
 static int
@@ -289,7 +364,7 @@ hwaddr_to_sockaddr(char *ev, struct sock
 }
 
 static int
-decode_nfshandle(char *ev, u_char *fh) 
+decode_nfshandle(char *ev, u_char *fh, int maxfh) 
 {
 	u_char *cp, *ep;
 	int len, val;
@@ -315,7 +390,7 @@ decode_nfshandle(char *ev, u_char *fh) 
 		*(fh++) = val;
 		len++;
 		cp += 2;
-		if (len > NFSX_V2FH) {
+		if (len > maxfh) {
 		    freeenv(ep);
 		    return (0);
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009160102.o8G12sJT056347>