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 */