Module Name:    src
Committed By:   ad
Date:           Sat May 23 15:31:21 UTC 2009

Modified Files:
        src/sys/nfs: nfs_export.c nfs_serv.c nfs_var.h

Log Message:
- Fix a race between umount()/mount() and nfssvc().
- Toss netexport state on nfsserver module unload.


To generate a diff of this commit:
cvs rdiff -u -r1.44 -r1.45 src/sys/nfs/nfs_export.c
cvs rdiff -u -r1.145 -r1.146 src/sys/nfs/nfs_serv.c
cvs rdiff -u -r1.86 -r1.87 src/sys/nfs/nfs_var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/nfs/nfs_export.c
diff -u src/sys/nfs/nfs_export.c:1.44 src/sys/nfs/nfs_export.c:1.45
--- src/sys/nfs/nfs_export.c:1.44	Wed Dec 17 20:51:38 2008
+++ src/sys/nfs/nfs_export.c	Sat May 23 15:31:21 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_export.c,v 1.44 2008/12/17 20:51:38 cegger Exp $	*/
+/*	$NetBSD: nfs_export.c,v 1.45 2009/05/23 15:31:21 ad Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 2004, 2005, 2008 The NetBSD Foundation, Inc.
@@ -75,10 +75,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_export.c,v 1.44 2008/12/17 20:51:38 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_export.c,v 1.45 2009/05/23 15:31:21 ad Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/kernel.h>
 #include <sys/queue.h>
 #include <sys/proc.h>
 #include <sys/mount.h>
@@ -147,6 +148,7 @@
 static void netexport_wrunlock(void);
 static int nfs_export_update_30(struct mount *mp, const char *path, void *);
 
+static krwlock_t netexport_lock;
 
 /*
  * PUBLIC INTERFACE
@@ -155,11 +157,11 @@
 /*
  * Declare and initialize the file system export hooks.
  */
-static void nfs_export_unmount(struct mount *);
+static void netexport_unmount(struct mount *);
 
 struct vfs_hooks nfs_export_hooks = {
 	{ NULL, NULL },
-	.vh_unmount = nfs_export_unmount,
+	.vh_unmount = netexport_unmount,
 	.vh_reexport = nfs_export_update_30,
 };
 
@@ -171,7 +173,7 @@
  * information, although it theorically should.
  */
 static void
-nfs_export_unmount(struct mount *mp)
+netexport_unmount(struct mount *mp)
 {
 	struct netexport *ne;
 
@@ -189,6 +191,44 @@
 	kmem_free(ne, sizeof(*ne));
 }
 
+void
+netexport_init(void)
+{
+
+	rw_init(&netexport_lock);
+}
+
+void
+netexport_fini(void)
+{
+	struct netexport *ne;
+	struct mount *mp;
+	int error;
+
+	KASSERT(mp != NULL);
+
+	for (;;) {
+		if (CIRCLEQ_EMPTY(&netexport_list)) {
+			break;
+		}
+		netexport_wrlock();
+		ne = CIRCLEQ_FIRST(&netexport_list);
+		mp = ne->ne_mount;
+		error = vfs_busy(mp, NULL);
+		netexport_wrunlock();
+		if (error != 0) {
+			kpause("nfsfini", false, hz, NULL);
+			continue;
+		}
+		mutex_enter(&mp->mnt_updating);	/* mnt_flag */
+		netexport_unmount(mp);
+		mutex_exit(&mp->mnt_updating);	/* mnt_flag */
+		vfs_unbusy(mp, false, NULL);
+	}
+	rw_destroy(&netexport_lock);
+}
+
+
 /*
  * Atomically set the NFS exports list of the given file system, replacing
  * it with a new list of entries.
@@ -241,7 +281,7 @@
 	vput(vp);
 	if (error != 0)
 		return error;
-
+	mutex_enter(&mp->mnt_updating);	/* mnt_flag */
 	netexport_wrlock();
 	ne = netexport_lookup(mp);
 	if (ne == NULL) {
@@ -282,6 +322,7 @@
 
 out:
 	netexport_wrunlock();
+	mutex_exit(&mp->mnt_updating);	/* mnt_flag */
 	vfs_unbusy(mp, false, NULL);
 	return error;
 }
@@ -798,8 +839,6 @@
 	return np;
 }
 
-krwlock_t netexport_lock;
-
 void
 netexport_rdlock(void)
 {

Index: src/sys/nfs/nfs_serv.c
diff -u src/sys/nfs/nfs_serv.c:1.145 src/sys/nfs/nfs_serv.c:1.146
--- src/sys/nfs/nfs_serv.c:1.145	Sat May 23 14:45:18 2009
+++ src/sys/nfs/nfs_serv.c	Sat May 23 15:31:21 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_serv.c,v 1.145 2009/05/23 14:45:18 ad Exp $	*/
+/*	$NetBSD: nfs_serv.c,v 1.146 2009/05/23 15:31:21 ad Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -55,7 +55,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.145 2009/05/23 14:45:18 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.146 2009/05/23 15:31:21 ad Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -108,7 +108,6 @@
 static int
 nfsserver_modcmd(modcmd_t cmd, void *arg)
 {
-	extern krwlock_t netexport_lock;		/* XXX */
 	extern struct vfs_hooks nfs_export_hooks;	/* XXX */
 	int error;
 
@@ -119,7 +118,7 @@
 			return error;
 		}
 		nfs_init();	/* XXX for monolithic kernel */
-		rw_init(&netexport_lock);
+		netexport_init();
 		nfsrv_initcache();	/* Init the server request cache */
 		nfsrv_init(0);		/* Init server data structures */
 		vfs_hooks_attach(&nfs_export_hooks);
@@ -130,11 +129,19 @@
 		if (error != 0) {
 			return error;
 		}
-		nfs_timer_srvfini();
+		/*
+		 * Kill export list before detaching VFS hooks, so we
+		 * we don't leak state due to a concurrent umount().
+		 */
+		netexport_fini();
 		vfs_hooks_detach(&nfs_export_hooks);
+
+		/* Kill timer before server goes away. */
+		nfs_timer_srvfini();
 		nfsrv_fini();
+
+		/* Server uses server cache, so kill cache last. */
 		nfsrv_finicache();
-		rw_destroy(&netexport_lock);
 		return 0;
 	default:
 		return ENOTTY;

Index: src/sys/nfs/nfs_var.h
diff -u src/sys/nfs/nfs_var.h:1.86 src/sys/nfs/nfs_var.h:1.87
--- src/sys/nfs/nfs_var.h:1.86	Sat Mar 14 14:46:11 2009
+++ src/sys/nfs/nfs_var.h	Sat May 23 15:31:21 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_var.h,v 1.86 2009/03/14 14:46:11 dsl Exp $	*/
+/*	$NetBSD: nfs_var.h,v 1.87 2009/05/23 15:31:21 ad Exp $	*/
 
 /*-
  * Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -305,4 +305,6 @@
     kauth_cred_t *);
 void netexport_rdlock(void);
 void netexport_rdunlock(void);
+void netexport_init(void);
+void netexport_fini(void);
 #endif /* _KERNEL */

Reply via email to