summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2015-12-02 02:47:13 +0000
committerrmacklem <rmacklem@FreeBSD.org>2015-12-02 02:47:13 +0000
commit3b49f0eca8f952370d74b0798d7ce811e10429c4 (patch)
treef041ce51ad7cb6ea3bdcc76a8fa1a921006d6851 /sys/fs
parent449c785f1a7bca246c222cc63fbdbffaa0462c24 (diff)
downloadFreeBSD-src-3b49f0eca8f952370d74b0798d7ce811e10429c4.zip
FreeBSD-src-3b49f0eca8f952370d74b0798d7ce811e10429c4.tar.gz
Fix the memory leak that occurs when the nfscommon.ko module is unloaded.
This leak was introduced by r291527. Since the nfscommon.ko module is rarely unloaded, this leak would not have been much of an issue. MFC after: 2 weeks
Diffstat (limited to 'sys/fs')
-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 1ac376c..a22b38c 100644
--- a/sys/fs/nfs/nfs_commonport.c
+++ b/sys/fs/nfs/nfs_commonport.c
@@ -623,6 +623,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 11db5a5..16d91af 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -3546,6 +3546,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 e08835c..23475b2 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