diff options
author | peadar <peadar@FreeBSD.org> | 2004-04-11 13:30:20 +0000 |
---|---|---|
committer | peadar <peadar@FreeBSD.org> | 2004-04-11 13:30:20 +0000 |
commit | 9bb40b73ee38d581fd618dcc763cb6e9adcf607d (patch) | |
tree | a9fbdaa4c8e4800e0faf70c2b2c9b5b19300ad03 /sys/nfsclient | |
parent | 3341cc4adb28d03c2c544c42d2c3e10f3546606d (diff) | |
download | FreeBSD-src-9bb40b73ee38d581fd618dcc763cb6e9adcf607d.zip FreeBSD-src-9bb40b73ee38d581fd618dcc763cb6e9adcf607d.tar.gz |
Clean up properly when unloading NFS client module.
This includes a modified form of some code from Thomas Moestl (tmm@)
to properly clean up the UMA zone and the "nfsnodehashtbl" hash
table.
Reviewed By: iedowse
PR: 16299
Diffstat (limited to 'sys/nfsclient')
-rw-r--r-- | sys/nfsclient/nfs.h | 2 | ||||
-rw-r--r-- | sys/nfsclient/nfs_nfsiod.c | 6 | ||||
-rw-r--r-- | sys/nfsclient/nfs_node.c | 10 | ||||
-rw-r--r-- | sys/nfsclient/nfs_subs.c | 19 |
4 files changed, 35 insertions, 2 deletions
diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h index c9e9ac0..ab80ab8 100644 --- a/sys/nfsclient/nfs.h +++ b/sys/nfsclient/nfs.h @@ -136,6 +136,7 @@ extern struct callout nfs_callout; extern struct nfsstats nfsstats; extern int nfs_numasync; +extern unsigned int nfs_iodmax; extern int nfs_pbuf_freecnt; extern int nfs_ticks; @@ -295,6 +296,7 @@ int nfs_loadattrcache(struct vnode **, struct mbuf **, caddr_t *, struct vattr *, int); int nfsm_mbuftouio(struct mbuf **, struct uio *, int, caddr_t *); void nfs_nhinit(void); +void nfs_nhuninit(void); int nfs_nmcancelreqs(struct nfsmount *); void nfs_timer(void*); diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c index f36d19f..bf6175a 100644 --- a/sys/nfsclient/nfs_nfsiod.c +++ b/sys/nfsclient/nfs_nfsiod.c @@ -87,7 +87,7 @@ static unsigned int nfs_iodmaxidle = 120; SYSCTL_UINT(_vfs_nfs, OID_AUTO, iodmaxidle, CTLFLAG_RW, &nfs_iodmaxidle, 0, ""); /* Maximum number of nfsiod kthreads */ -static unsigned int nfs_iodmax = 20; +unsigned int nfs_iodmax = 20; /* Minimum number of nfsiod kthreads to keep as spares */ static unsigned int nfs_iodmin = 4; @@ -280,7 +280,9 @@ finish: nmp->nm_bufqiods--; nfs_iodwant[myiod] = NULL; nfs_iodmount[myiod] = NULL; - nfs_numasync--; + /* Someone may be waiting for the last nfsiod to terminate. */ + if (--nfs_numasync == 0) + wakeup(&nfs_numasync); if ((error == 0) || (error == EWOULDBLOCK)) kthread_exit(0); /* Abnormal termination */ diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c index e7643ce..e6b2d94 100644 --- a/sys/nfsclient/nfs_node.c +++ b/sys/nfsclient/nfs_node.c @@ -161,6 +161,16 @@ nfs_nhinit(void) } /* + * Release hash table resources + */ +void +nfs_nhuninit(void) +{ + hashdestroy(nfsnodehashtbl, M_NFSHASH, nfsnodehash); + uma_zdestroy(nfsnode_zone); +} + +/* * Look up a vnode/nfsnode by file handle. * Callers must check for mount points!! * In all cases, a pointer to a diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c index 975e112..8f8524c 100644 --- a/sys/nfsclient/nfs_subs.c +++ b/sys/nfsclient/nfs_subs.c @@ -429,10 +429,29 @@ nfs_init(struct vfsconf *vfsp) int nfs_uninit(struct vfsconf *vfsp) { + int i; callout_stop(&nfs_callout); sysent[SYS_nfsclnt].sy_narg = nfs_prev_nfsclnt_sy_narg; sysent[SYS_nfsclnt].sy_call = nfs_prev_nfsclnt_sy_call; + + KASSERT(TAILQ_ISEMPTY(&nfs_reqq), + ("nfs_uninit: request queue not empty")); + + /* + * Tell all nfsiod processes to exit. Clear nfs_iodmax, and wakeup + * any sleeping nfsiods so they check nfs_iodmax and exit. + */ + nfs_iodmax = 0; + for (i = 0; i < nfs_numasync; i++) + if (nfs_iodwant[i]) + wakeup(&nfs_iodwant[i]); + /* The last nfsiod to exit will wake us up when nfs_numasync hits 0 */ + while (nfs_numasync) + tsleep(&nfs_numasync, PWAIT, "ioddie", 0); + + nfs_nhuninit(); + uma_zdestroy(nfsmount_zone); return (0); } |