diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2015-12-16 00:52:35 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2015-12-16 00:52:35 +0000 |
commit | e51b2b1eeaad474e4bc52deb0fd59b501c305a80 (patch) | |
tree | d19cc97dc803d4c0dfb91bc001a8eb98c84dfd2e /sys/fs/nfs | |
parent | 0696c87609cb06af71377db0d481f43e7bd039c2 (diff) | |
download | FreeBSD-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.
Diffstat (limited to 'sys/fs/nfs')
-rw-r--r-- | sys/fs/nfs/nfs_commonport.c | 2 | ||||
-rw-r--r-- | sys/fs/nfs/nfs_commonsubs.c | 49 | ||||
-rw-r--r-- | sys/fs/nfs/nfs_var.h | 1 |
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 *); |