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