summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2015-12-16 00:52:35 +0000
committerrmacklem <rmacklem@FreeBSD.org>2015-12-16 00:52:35 +0000
commite51b2b1eeaad474e4bc52deb0fd59b501c305a80 (patch)
treed19cc97dc803d4c0dfb91bc001a8eb98c84dfd2e
parent0696c87609cb06af71377db0d481f43e7bd039c2 (diff)
downloadFreeBSD-src-e51b2b1eeaad474e4bc52deb0fd59b501c305a80.zip
FreeBSD-src-e51b2b1eeaad474e4bc52deb0fd59b501c305a80.tar.gz
MFC: r291638
Fix the memory leak that occurs when the nfscommon.ko module is unloaded. This leak was introduced by r291527 (r292223 in stable/10). Since the nfscommon.ko module is rarely unloaded, this leak would not have been much of an issue.
-rw-r--r--sys/fs/nfs/nfs_commonport.c2
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c49
-rw-r--r--sys/fs/nfs/nfs_var.h1
3 files changed, 52 insertions, 0 deletions
diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c
index 4910c61..85738af 100644
--- a/sys/fs/nfs/nfs_commonport.c
+++ b/sys/fs/nfs/nfs_commonport.c
@@ -624,6 +624,8 @@ nfscommon_modevent(module_t mod, int type, void *data)
nfsd_call_nfscommon = NULL;
callout_drain(&newnfsd_callout);
+ /* Clean out the name<-->id cache. */
+ nfsrv_cleanusergroup();
/* and get rid of the mutexes */
mtx_destroy(&nfs_nameid_mutex);
mtx_destroy(&newnfsd_mtx);
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 5b8bca3..ba38e0e 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -3539,6 +3539,55 @@ nfsrv_removeuser(struct nfsusrgrp *usrp, int isuser)
}
/*
+ * Free up all the allocations related to the name<-->id cache.
+ * This function should only be called when the nfsuserd daemon isn't
+ * running, since it doesn't do any locking.
+ * This function is meant to be used when the nfscommon module is unloaded.
+ */
+APPLESTATIC void
+nfsrv_cleanusergroup(void)
+{
+ struct nfsrv_lughash *hp, *hp2;
+ struct nfsusrgrp *nusrp, *usrp;
+ int i;
+
+ if (nfsuserhash == NULL)
+ return;
+
+ for (i = 0; i < nfsrv_lughashsize; i++) {
+ hp = &nfsuserhash[i];
+ TAILQ_FOREACH_SAFE(usrp, &hp->lughead, lug_numhash, nusrp) {
+ TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
+ hp2 = NFSUSERNAMEHASH(usrp->lug_name,
+ usrp->lug_namelen);
+ TAILQ_REMOVE(&hp2->lughead, usrp, lug_namehash);
+ if (usrp->lug_cred != NULL)
+ crfree(usrp->lug_cred);
+ free(usrp, M_NFSUSERGROUP);
+ }
+ hp = &nfsgrouphash[i];
+ TAILQ_FOREACH_SAFE(usrp, &hp->lughead, lug_numhash, nusrp) {
+ TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
+ hp2 = NFSGROUPNAMEHASH(usrp->lug_name,
+ usrp->lug_namelen);
+ TAILQ_REMOVE(&hp2->lughead, usrp, lug_namehash);
+ if (usrp->lug_cred != NULL)
+ crfree(usrp->lug_cred);
+ free(usrp, M_NFSUSERGROUP);
+ }
+ mtx_destroy(&nfsuserhash[i].mtx);
+ mtx_destroy(&nfsusernamehash[i].mtx);
+ mtx_destroy(&nfsgroupnamehash[i].mtx);
+ mtx_destroy(&nfsgrouphash[i].mtx);
+ }
+ free(nfsuserhash, M_NFSUSERGROUP);
+ free(nfsusernamehash, M_NFSUSERGROUP);
+ free(nfsgrouphash, M_NFSUSERGROUP);
+ free(nfsgroupnamehash, M_NFSUSERGROUP);
+ free(nfsrv_dnsname, M_NFSSTRING);
+}
+
+/*
* This function scans a byte string and checks for UTF-8 compliance.
* It returns 0 if it conforms and NFSERR_INVAL if not.
*/
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 49ac769..5739f6b 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -283,6 +283,7 @@ void nfsv4_getref(struct nfsv4lock *, int *, void *, struct mount *);
int nfsv4_getref_nonblock(struct nfsv4lock *);
int nfsv4_testlock(struct nfsv4lock *);
int nfsrv_mtostr(struct nfsrv_descript *, char *, int);
+void nfsrv_cleanusergroup(void);
int nfsrv_checkutf8(u_int8_t *, int);
int newnfs_sndlock(int *);
void newnfs_sndunlock(int *);
OpenPOWER on IntegriCloud