summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpeadar <peadar@FreeBSD.org>2004-04-11 13:30:20 +0000
committerpeadar <peadar@FreeBSD.org>2004-04-11 13:30:20 +0000
commit9bb40b73ee38d581fd618dcc763cb6e9adcf607d (patch)
treea9fbdaa4c8e4800e0faf70c2b2c9b5b19300ad03 /sys
parent3341cc4adb28d03c2c544c42d2c3e10f3546606d (diff)
downloadFreeBSD-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')
-rw-r--r--sys/nfsclient/nfs.h2
-rw-r--r--sys/nfsclient/nfs_nfsiod.c6
-rw-r--r--sys/nfsclient/nfs_node.c10
-rw-r--r--sys/nfsclient/nfs_subs.c19
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);
}
OpenPOWER on IntegriCloud