Minor reorganization of nfs_mountroot code to simplify BOOTP support. trunk
authorgwr <gwr@NetBSD.org>
Tue, 27 May 1997 23:37:39 +0000
branchtrunk
changeset 28549 047b96f52b04
parent 28548 d4572a925fa5
child 28550 163d105f88da
Minor reorganization of nfs_mountroot code to simplify BOOTP support. The RPC/bootparamd calls to get the root and swap paths are now done in nfs_boot_init() instead of nfs_boot_getfh(), so the latter now just does the RPC/mountd call. Also changed some panics into error returns.
sys/nfs/nfs_boot.c
sys/nfs/nfs_vfsops.c
sys/nfs/nfsdiskless.h
--- a/sys/nfs/nfs_boot.c	Tue May 27 23:24:56 1997 +0000
+++ b/sys/nfs/nfs_boot.c	Tue May 27 23:37:39 1997 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_boot.c,v 1.32 1997/03/17 17:41:45 thorpej Exp $	*/
+/*	$NetBSD: nfs_boot.c,v 1.33 1997/05/27 23:37:39 gwr Exp $	*/
 
 /*
  * Copyright (c) 1995 Adam Glass, Gordon Ross
@@ -63,16 +63,15 @@
 	struct nfs_diskless *nd;
 	struct proc *procp;
 {
-	panic("nfs_boot_init: no ether");
+	printf("nfs_boot: NETHER == 0\n");
+	return (ENXIO);
 }
 
-void
-nfs_boot_getfh(bpsin, key, ndmntp)
-	struct sockaddr_in *bpsin;
-	char *key;
-	struct nfs_dlmount *ndmntp;
+int
+nfs_boot_getfh(ndm)
+	struct nfs_dlmount *ndm;
 {
-	/* can not get here */
+	return (ENXIO);
 }
 
 #else /* NETHER */
@@ -101,7 +100,7 @@
 static int bp_whoami __P((struct sockaddr_in *bpsin,
 	struct in_addr *my_ip, struct in_addr *gw_ip));
 static int bp_getfile __P((struct sockaddr_in *bpsin, char *key,
-	struct sockaddr_in *mdsin, char *servname, char *path));
+	struct nfs_dlmount *ndm));
 
 /* mountd RPC */
 static int md_mount __P((struct sockaddr_in *mdsin, char *path,
@@ -150,24 +149,35 @@
 	 * Get the old interface flags and or IFF_UP into them; if
 	 * IFF_UP set blindly, interface selection can be clobbered.
 	 */
-	if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)) != 0)
-		panic("nfs_boot: socreate, error=%d", error);
+	so = 0;
+	error = socreate(AF_INET, &so, SOCK_DGRAM, 0);
+	if (error) {
+		printf("nfs_boot: socreate, error=%d\n", error);
+		so = 0;
+		goto out;
+	}
 	error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)&ireq, procp);
-	if (error)
-		panic("nfs_boot: GIFFLAGS, error=%d", error);
+	if (error) {
+		printf("nfs_boot: GIFFLAGS, error=%d\n", error);
+		goto out;
+	}
 	ireq.ifr_flags |= IFF_UP;
 	error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)&ireq, procp);
-	if (error)
-		panic("nfs_boot: SIFFLAGS, error=%d", error);
+	if (error) {
+		printf("nfs_boot: SIFFLAGS, error=%d\n", error);
+		goto out;
+	}
 
 	/*
 	 * Do RARP for the interface address.
 	 */
 	if ((error = revarpwhoami(&my_ip, ifp)) != 0) {
 		printf("revarp failed, error=%d\n", error);
-		return (EIO);
+		error = EIO;	/* XXX */
+		goto out;
 	}
-	printf("nfs_boot: client_addr=0x%x\n", (u_int32_t)ntohl(my_ip.s_addr));
+	printf("nfs_boot: client_addr=0x%x\n",
+	       (u_int32_t)ntohl(my_ip.s_addr));
 
 	/*
 	 * Do enough of ifconfig(8) so that the chosen interface
@@ -179,10 +189,10 @@
 	sin->sin_family = AF_INET;
 	sin->sin_addr.s_addr = my_ip.s_addr;
 	error = ifioctl(so, SIOCSIFADDR, (caddr_t)&ireq, procp);
-	if (error)
-		panic("nfs_boot: set if addr, error=%d", error);
-
-	soclose(so);
+	if (error) {
+		printf("nfs_boot: set if addr, error=%d\n", error);
+		goto out;
+	}
 
 	/*
 	 * Get client name and gateway address.
@@ -198,11 +208,11 @@
 	bp_sin.sin_addr.s_addr = INADDR_BROADCAST;
 	hostnamelen = MAXHOSTNAMELEN;
 
-	/* this returns gateway IP address */
+	/* Do the RPC/bootparam/whoami. */
 	error = bp_whoami(&bp_sin, &my_ip, &gw_ip);
 	if (error) {
 		printf("nfs_boot: bootparam whoami, error=%d\n", error);
-		return (error);
+		goto out;
 	}
 	printf("nfs_boot: server_addr=0x%x\n",
 		   (u_int32_t)ntohl(bp_sin.sin_addr.s_addr));
@@ -248,34 +258,50 @@
 
 	bcopy(&bp_sin, &nd->nd_boot, sizeof(bp_sin));
 
-	return (0);
+	/*
+	 * Now fetch the server:pathname strings and server IP
+	 * for root and swap.  Missing swap is not fatal.
+	 */
+	error = bp_getfile(&nd->nd_boot, "root", &nd->nd_root);
+	if (error) {
+		printf("nfs_boot: bootparam get root: %d\n", error);
+		goto out;
+	}
+
+	error = bp_getfile(&nd->nd_boot, "swap", &nd->nd_swap);
+	if (error) {
+		printf("nfs_boot: bootparam get swap: %d", error);
+		error = 0;
+	}
+
+ out:
+	if (so) soclose(so);
+
+	return (error);
 }
 
-void
-nfs_boot_getfh(bpsin, key, ndmntp)
-	struct sockaddr_in *bpsin;	/* bootparam server */
-	char *key;			/* root or swap */
-	struct nfs_dlmount *ndmntp;	/* output */
+int
+nfs_boot_getfh(ndm)
+	struct nfs_dlmount *ndm;	/* output */
 {
 	struct nfs_args *args;
-	char pathname[MAXPATHLEN];
-	char *sp, *dp, *endp;
 	struct sockaddr_in *sin;
+	char *pathname;
 	int error;
 
-	args = &ndmntp->ndm_args;
+	args = &ndm->ndm_args;
 
 	/* Initialize mount args. */
 	bzero((caddr_t) args, sizeof(*args));
-	args->addr     = &ndmntp->ndm_saddr;
+	args->addr     = &ndm->ndm_saddr;
 	args->addrlen  = args->addr->sa_len;
 #ifdef NFS_BOOT_TCP
 	args->sotype   = SOCK_STREAM;
 #else
 	args->sotype   = SOCK_DGRAM;
 #endif
-	args->fh       = ndmntp->ndm_fh;
-	args->hostname = ndmntp->ndm_host;
+	args->fh       = ndm->ndm_fh;
+	args->hostname = ndm->ndm_host;
 	args->flags    = NFSMNT_RESVPORT | NFSMNT_NFSV3;
 
 #ifdef	NFS_BOOT_OPTIONS
@@ -292,23 +318,27 @@
 	args->rsize    = NFS_BOOT_RWSIZE;
 #endif
 
-	sin = (void*)&ndmntp->ndm_saddr;
+	/*
+	 * Find the pathname part of the "server:pathname"
+	 * string left in ndm->ndm_host by nfs_boot_init.
+	 */
+	pathname = strchr(ndm->ndm_host, ':');
+	if (pathname == 0) {
+		printf("nfs_boot: getfh - no pathname\n");
+		return (EIO);
+	}
+	pathname++;
 
 	/*
-	 * Get server:pathname for "key" (root or swap)
-	 * using RPC to bootparam/getfile
+	 * Get file handle using RPC to mountd/mount
 	 */
-	error = bp_getfile(bpsin, key, sin, ndmntp->ndm_host, pathname);
-	if (error)
-		panic("nfs_boot: bootparam get %s: %d", key, error);
-
-	/*
-	 * Get file handle for "key" (root or swap)
-	 * using RPC to mountd/mount
-	 */
+	sin = (struct sockaddr_in *)&ndm->ndm_saddr;
 	error = md_mount(sin, pathname, args);
-	if (error)
-		panic("nfs_boot: mountd %s, error=%d", key, error);
+	if (error) {
+		printf("nfs_boot: mountd `%s', error=%d\n",
+		    ndm->ndm_host, error);
+		return (error);
+	}
 
 	/* Set port number for NFS use. */
 	/* XXX: NFS port is always 2049, right? */
@@ -319,26 +349,19 @@
 		    (args->flags & NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
 		    (args->sotype == SOCK_STREAM) ? IPPROTO_TCP : IPPROTO_UDP,
 		    &sin->sin_port);
-
-	if (error || (sin->sin_port == htons(0))) {
+	if (sin->sin_port == htons(0))
+		error = EIO;
+	if (error) { 
 #ifdef NFS_BOOT_TCP
 		if (args->sotype == SOCK_STREAM) {
 			args->sotype = SOCK_DGRAM;
 			goto retry;
 		}
 #endif
-		panic("nfs_boot: portmap NFS, error=%d", error);
+		printf("nfs_boot: portmap NFS, error=%d\n", error);
 	}
 
-	/* Construct remote path (for getmntinfo(3)) */
-	dp = ndmntp->ndm_host;
-	endp = dp + MNAMELEN - 1;
-	dp += strlen(dp);
-	*dp++ = ':';
-	for (sp = pathname; *sp && dp < endp;)
-		*dp++ = *sp++;
-	*dp = '\0';
-
+	return (error);
 }
 
 
@@ -466,16 +489,16 @@
  *	server pathname
  */
 static int
-bp_getfile(bpsin, key, md_sin, serv_name, pathname)
+bp_getfile(bpsin, key, ndm)
 	struct sockaddr_in *bpsin;
 	char *key;
-	struct sockaddr_in *md_sin;
-	char *serv_name;
-	char *pathname;
+	struct nfs_dlmount *ndm;
 {
-	struct mbuf *m;
+	char pathname[MNAMELEN];
+	struct in_addr inaddr;
 	struct sockaddr_in *sin;
-	struct in_addr inaddr;
+	struct mbuf *m;
+	char *serv_name;
 	int error, sn_len, path_len;
 
 	/*
@@ -494,7 +517,7 @@
 
 	/* RPC: bootparam/getfile */
 	error = krpc_call(bpsin, BOOTPARAM_PROG, BOOTPARAM_VERS,
-			BOOTPARAM_GETFILE, &m, NULL);
+	                  BOOTPARAM_GETFILE, &m, NULL);
 	if (error)
 		return error;
 
@@ -503,7 +526,8 @@
 	 */
 
 	/* server name */
-	sn_len = MNAMELEN-1;
+	serv_name = &ndm->ndm_host[0];
+	sn_len = sizeof(ndm->ndm_host) - 1;
 	m = xdr_string_decode(m, serv_name, &sn_len);
 	if (m == NULL)
 		goto bad;
@@ -514,17 +538,27 @@
 		goto bad;
 
 	/* server pathname */
-	path_len = MAXPATHLEN-1;
+	path_len = sizeof(pathname) - 1;
 	m = xdr_string_decode(m, pathname, &path_len);
 	if (m == NULL)
 		goto bad;
 
-	/* setup server socket address */
-	sin = md_sin;
+	/*
+	 * Store the results in the nfs_dlmount.
+	 * The strings become "server:pathname"
+	 */
+	sin = (struct sockaddr_in *) &ndm->ndm_saddr;
 	bzero((caddr_t)sin, sizeof(*sin));
 	sin->sin_len = sizeof(*sin);
 	sin->sin_family = AF_INET;
 	sin->sin_addr = inaddr;
+	if ((sn_len + 1 + path_len + 1) > sizeof(ndm->ndm_host)) {
+		printf("nfs_boot: getfile name too long\n");
+		error = EIO;
+		goto out;
+	}
+	ndm->ndm_host[sn_len] = ':';
+	bcopy(pathname, ndm->ndm_host + sn_len + 1, path_len + 1);
 
 	/* success */
 	goto out;
--- a/sys/nfs/nfs_vfsops.c	Tue May 27 23:24:56 1997 +0000
+++ b/sys/nfs/nfs_vfsops.c	Tue May 27 23:37:39 1997 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_vfsops.c,v 1.58 1997/02/22 02:48:26 fvdl Exp $	*/
+/*	$NetBSD: nfs_vfsops.c,v 1.59 1997/05/27 23:37:41 gwr Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993, 1995
@@ -102,9 +102,9 @@
 extern u_int32_t nfs_procids[NFS_NPROCS];
 extern u_int32_t nfs_prog, nfs_vers;
 
-static struct mount *
-nfs_mount_diskless __P((struct nfs_dlmount *, const char *, int,
-    struct vnode **));
+static int
+nfs_mount_diskless __P((struct nfs_dlmount *, const char *,
+    struct mount **, struct vnode **));
 
 #define TRUE	1
 #define	FALSE	0
@@ -255,10 +255,9 @@
 /*
  * Mount a remote root fs via. NFS.  It goes like this:
  * - Call nfs_boot_init() to fill in the nfs_diskless struct
- *   (using RARP, bootparam RPC, mountd RPC)
+ * - build the rootfs mount point and call mountnfs() to do the rest.
  * - hand craft the swap nfs vnode hanging off a fake mount point
- *	if swdevt[0].sw_dev == NODEV
- * - build the rootfs mount point and call mountnfs() to do the rest.
+ *     (only if swdevt[0].sw_dev == NODEV)
  */
 int
 nfs_mountroot()
@@ -297,8 +296,12 @@
 	/*
 	 * Create the root mount point.
 	 */
-	nfs_boot_getfh(&nd.nd_boot, "root", &nd.nd_root);
-	mp = nfs_mount_diskless(&nd.nd_root, "/", 0, &vp);
+	error = nfs_boot_getfh(&nd.nd_root);
+	if (error)
+		return (error);
+	error = nfs_mount_diskless(&nd.nd_root, "/", &mp, &vp);
+	if (error)
+		return (error);
 	printf("root on %s\n", nd.nd_root.ndm_host);
 
 	/*
@@ -321,17 +324,22 @@
 
 	/* Get root attributes (for the time). */
 	error = VOP_GETATTR(vp, &attr, procp->p_ucred, procp);
-	if (error) panic("nfs_mountroot: getattr for root");
+	if (error)
+		panic("nfs_mountroot: getattr for root");
 	n = attr.va_mtime.tv_sec;
 #ifdef	DEBUG
 	printf("root time: 0x%lx\n", n);
 #endif
 	inittodr(n);
 
+#if 0
 	/* 
 	 * XXX splnet, so networks will receive...
+	 * XXX What system needed this hack?
+	 * XXX Should already be at spl0.
 	 */
 	splnet();
+#endif
 
 #ifdef notyet
 	/* Set up swap credentials. */
@@ -362,8 +370,15 @@
 	 * Create a fake mount point just for the swap vnode so that the
 	 * swap file can be on a different server from the rootfs.
 	 */
-	nfs_boot_getfh(&nd.nd_boot, "swap", &nd.nd_swap);
-	mp = nfs_mount_diskless(&nd.nd_swap, "/swap", 0, &vp);
+	if ((error = nfs_boot_getfh(&nd.nd_swap)) != 0) {
+		printf("nfs_boot: warning: getfh(swap), error=%d\n", error);
+		return (0);
+	}
+	error = nfs_mount_diskless(&nd.nd_swap, "/swap", &mp, &vp);
+	if (error) {
+		printf("nfs_boot: warning: mount(swap), error=%d\n", error);
+		return (0);
+	}
 #ifdef Lite2_integrated
 	vfs_unbusy(mp, procp);
 #endif
@@ -395,11 +410,11 @@
 /*
  * Internal version of mount system call for diskless setup.
  */
-static struct mount *
-nfs_mount_diskless(ndmntp, mntname, mntflag, vpp)
+static int
+nfs_mount_diskless(ndmntp, mntname, mpp, vpp)
 	struct nfs_dlmount *ndmntp;
-	const char *mntname;
-	int mntflag;
+	const char *mntname;	/* mount point name */
+	struct mount **mpp;
 	struct vnode **vpp;
 {
 	struct mount *mp;
@@ -415,7 +430,7 @@
 	bzero((char *)mp, (u_long)sizeof(struct mount));
 #endif
 	mp->mnt_op = &nfs_vfsops;
-	mp->mnt_flag = mntflag;
+	/* mp->mnt_flag = 0 */
 
 	/* Get mbuf for server sockaddr. */
 	m = m_get(M_WAIT, MT_SONAME);
@@ -426,10 +441,14 @@
 
 	error = mountnfs(&ndmntp->ndm_args, mp, m, mntname,
 			 ndmntp->ndm_args.hostname, vpp);
-	if (error)
-		panic("nfs_mountroot: mount %s failed: %d", mntname, error);
+	if (error) {
+		printf("nfs_mountroot: mount %s failed: %d\n",
+		       mntname, error);
+		free(mp, M_MOUNT);
+	} else
+		*mpp = mp;
 
-	return (mp);
+	return (error);
 }
 
 void
--- a/sys/nfs/nfsdiskless.h	Tue May 27 23:24:56 1997 +0000
+++ b/sys/nfs/nfsdiskless.h	Tue May 27 23:37:39 1997 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfsdiskless.h,v 1.10 1996/10/20 13:13:28 fvdl Exp $	*/
+/*	$NetBSD: nfsdiskless.h,v 1.11 1997/05/27 23:37:43 gwr Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993
@@ -50,18 +50,17 @@
  * client/server byte ordering differences.
  */
 struct nfs_dlmount {
-        struct nfs_args ndm_args;
+	struct nfs_args ndm_args;
 	struct sockaddr ndm_saddr;  		/* Address of file server */
-	char		ndm_host[MNAMELEN]; 	/* Host name for mount pt */
+	char		ndm_host[MNAMELEN]; 	/* server:pathname */
 	u_char		ndm_fh[NFSX_V3FHMAX]; 	/* The file's file handle */
 };
 struct nfs_diskless {
-	struct sockaddr_in nd_boot;	/* Address of boot server */
+	struct sockaddr_in nd_boot; 	/* Address of boot server */
 	struct nfs_dlmount nd_root; 	/* Mount info for root */
 	struct nfs_dlmount nd_swap; 	/* Mount info for swap */
 };
 
 int nfs_boot_init __P((struct nfs_diskless *nd, struct proc *procp));
-void nfs_boot_getfh __P((struct sockaddr_in *bpsin, char *key,
-		struct nfs_dlmount *ndmntp));
+int nfs_boot_getfh __P((struct nfs_dlmount *ndm));