diff --git a/sys/fs/nfs/nfs_commonport.c.vnet b/sys/fs/nfs/nfs_commonport.c --- a/sys/fs/nfs/nfs_commonport.c.vnet +++ b/sys/fs/nfs/nfs_commonport.c @@ -42,6 +42,7 @@ * to this BSD variant. */ #include +#include #include #include #include @@ -56,12 +57,9 @@ #include extern int nfscl_ticks; -extern nfsuserd_state nfsrv_nfsuserd; -extern struct nfssockreq nfsrv_nfsuserdsock; extern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *, struct thread *); extern int nfsrv_useacl; -struct mount nfsv4root_mnt; int newnfs_numnfsd = 0; struct nfsstatsv1 nfsstatsv1; int nfs_numnfscbd = 0; @@ -76,6 +74,16 @@ vop_reclaim_t *nfs_reclaim_p = NULL; uint32_t nfs_srvmaxio = NFS_SRVMAXIO; +NFSD_VNET_DECLARE(struct nfsrv_lughash *, nfsuserhash); +NFSD_VNET_DECLARE(struct nfsrv_lughash *, nfsusernamehash); +NFSD_VNET_DECLARE(struct nfsrv_lughash *, nfsgrouphash); +NFSD_VNET_DECLARE(struct nfsrv_lughash *, nfsgroupnamehash); +NFSD_VNET_DECLARE(u_char *, nfsrv_dnsname); +NFSD_VNET_DECLARE(struct nfssockreq, nfsrv_nfsuserdsock); +NFSD_VNET_DECLARE(nfsuserd_state, nfsrv_nfsuserd); + +NFSDSTATSDEFINE(nfsstatsv1); + int nfs_pnfsio(task_fn_t *, void *); static int nfs_realign_test; @@ -149,6 +157,7 @@ /* local functions */ static int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *); +static void nfsrv_cleanusergroup(struct prison *); #ifdef __NO_STRICT_ALIGNMENT /* @@ -433,7 +442,9 @@ { int error; + NFSD_CURVNET_SET(NFSD_TD_TO_VNET(td)); error = nfssvc_call(td, uap, td->td_ucred); + NFSD_CURVNET_RESTORE(); NFSEXITCODE(error); return (error); } @@ -447,6 +458,7 @@ struct { int vers; /* Just the first field of nfsstats. */ } nfsstatver; + struct nfsstatsv1 *outstats; if (uap->flag & NFSSVC_IDNAME) { if ((uap->flag & NFSSVC_NEWSTRUCT) != 0) @@ -470,90 +482,96 @@ error = nfssvc_idname(&nid); goto out; } else if (uap->flag & NFSSVC_GETSTATS) { +#ifdef VIMAGE + outstats = malloc(sizeof(*outstats), M_TEMP, M_WAITOK | M_ZERO); +#else + outstats = &nfsstatsv1; +#endif + nfsd_copy_vnetstats(); if ((uap->flag & NFSSVC_NEWSTRUCT) == 0) { /* Copy fields to the old ext_nfsstat structure. */ oldnfsstats.attrcache_hits = - nfsstatsv1.attrcache_hits; + outstats->attrcache_hits; oldnfsstats.attrcache_misses = - nfsstatsv1.attrcache_misses; + outstats->attrcache_misses; oldnfsstats.lookupcache_hits = - nfsstatsv1.lookupcache_hits; + outstats->lookupcache_hits; oldnfsstats.lookupcache_misses = - nfsstatsv1.lookupcache_misses; + outstats->lookupcache_misses; oldnfsstats.direofcache_hits = - nfsstatsv1.direofcache_hits; + outstats->direofcache_hits; oldnfsstats.direofcache_misses = - nfsstatsv1.direofcache_misses; + outstats->direofcache_misses; oldnfsstats.accesscache_hits = - nfsstatsv1.accesscache_hits; + outstats->accesscache_hits; oldnfsstats.accesscache_misses = - nfsstatsv1.accesscache_misses; + outstats->accesscache_misses; oldnfsstats.biocache_reads = - nfsstatsv1.biocache_reads; + outstats->biocache_reads; oldnfsstats.read_bios = - nfsstatsv1.read_bios; + outstats->read_bios; oldnfsstats.read_physios = - nfsstatsv1.read_physios; + outstats->read_physios; oldnfsstats.biocache_writes = - nfsstatsv1.biocache_writes; + outstats->biocache_writes; oldnfsstats.write_bios = - nfsstatsv1.write_bios; + outstats->write_bios; oldnfsstats.write_physios = - nfsstatsv1.write_physios; + outstats->write_physios; oldnfsstats.biocache_readlinks = - nfsstatsv1.biocache_readlinks; + outstats->biocache_readlinks; oldnfsstats.readlink_bios = - nfsstatsv1.readlink_bios; + outstats->readlink_bios; oldnfsstats.biocache_readdirs = - nfsstatsv1.biocache_readdirs; + outstats->biocache_readdirs; oldnfsstats.readdir_bios = - nfsstatsv1.readdir_bios; + outstats->readdir_bios; for (i = 0; i < NFSV4_NPROCS; i++) - oldnfsstats.rpccnt[i] = nfsstatsv1.rpccnt[i]; - oldnfsstats.rpcretries = nfsstatsv1.rpcretries; + oldnfsstats.rpccnt[i] = outstats->rpccnt[i]; + oldnfsstats.rpcretries = outstats->rpcretries; for (i = 0; i < NFSV4OP_NOPS; i++) oldnfsstats.srvrpccnt[i] = - nfsstatsv1.srvrpccnt[i]; + outstats->srvrpccnt[i]; for (i = NFSV42_NOPS, j = NFSV4OP_NOPS; i < NFSV42_NOPS + NFSV4OP_FAKENOPS; i++, j++) oldnfsstats.srvrpccnt[j] = - nfsstatsv1.srvrpccnt[i]; + outstats->srvrpccnt[i]; oldnfsstats.reserved_0 = 0; oldnfsstats.reserved_1 = 0; - oldnfsstats.rpcrequests = nfsstatsv1.rpcrequests; - oldnfsstats.rpctimeouts = nfsstatsv1.rpctimeouts; - oldnfsstats.rpcunexpected = nfsstatsv1.rpcunexpected; - oldnfsstats.rpcinvalid = nfsstatsv1.rpcinvalid; + oldnfsstats.rpcrequests = outstats->rpcrequests; + oldnfsstats.rpctimeouts = outstats->rpctimeouts; + oldnfsstats.rpcunexpected = outstats->rpcunexpected; + oldnfsstats.rpcinvalid = outstats->rpcinvalid; oldnfsstats.srvcache_inproghits = - nfsstatsv1.srvcache_inproghits; + outstats->srvcache_inproghits; oldnfsstats.reserved_2 = 0; oldnfsstats.srvcache_nonidemdonehits = - nfsstatsv1.srvcache_nonidemdonehits; + outstats->srvcache_nonidemdonehits; oldnfsstats.srvcache_misses = - nfsstatsv1.srvcache_misses; + outstats->srvcache_misses; oldnfsstats.srvcache_tcppeak = - nfsstatsv1.srvcache_tcppeak; - oldnfsstats.srvcache_size = nfsstatsv1.srvcache_size; - oldnfsstats.srvclients = nfsstatsv1.srvclients; - oldnfsstats.srvopenowners = nfsstatsv1.srvopenowners; - oldnfsstats.srvopens = nfsstatsv1.srvopens; - oldnfsstats.srvlockowners = nfsstatsv1.srvlockowners; - oldnfsstats.srvlocks = nfsstatsv1.srvlocks; - oldnfsstats.srvdelegates = nfsstatsv1.srvdelegates; + outstats->srvcache_tcppeak; + oldnfsstats.srvcache_size = outstats->srvcache_size; + oldnfsstats.srvclients = outstats->srvclients; + oldnfsstats.srvopenowners = outstats->srvopenowners; + oldnfsstats.srvopens = outstats->srvopens; + oldnfsstats.srvlockowners = outstats->srvlockowners; + oldnfsstats.srvlocks = outstats->srvlocks; + oldnfsstats.srvdelegates = outstats->srvdelegates; for (i = 0; i < NFSV4OP_CBNOPS; i++) oldnfsstats.cbrpccnt[i] = - nfsstatsv1.cbrpccnt[i]; - oldnfsstats.clopenowners = nfsstatsv1.clopenowners; - oldnfsstats.clopens = nfsstatsv1.clopens; - oldnfsstats.cllockowners = nfsstatsv1.cllockowners; - oldnfsstats.cllocks = nfsstatsv1.cllocks; - oldnfsstats.cldelegates = nfsstatsv1.cldelegates; + outstats->cbrpccnt[i]; + oldnfsstats.clopenowners = outstats->clopenowners; + oldnfsstats.clopens = outstats->clopens; + oldnfsstats.cllockowners = outstats->cllockowners; + oldnfsstats.cllocks = outstats->cllocks; + oldnfsstats.cldelegates = outstats->cldelegates; oldnfsstats.cllocalopenowners = - nfsstatsv1.cllocalopenowners; - oldnfsstats.cllocalopens = nfsstatsv1.cllocalopens; + outstats->cllocalopenowners; + oldnfsstats.cllocalopens = outstats->cllocalopens; oldnfsstats.cllocallockowners = - nfsstatsv1.cllocallockowners; - oldnfsstats.cllocallocks = nfsstatsv1.cllocallocks; + outstats->cllocallockowners; + oldnfsstats.cllocallocks = outstats->cllocallocks; error = copyout(&oldnfsstats, uap->argp, sizeof (oldnfsstats)); } else { @@ -561,136 +579,136 @@ sizeof(nfsstatver)); if (error == 0) { if (nfsstatver.vers == NFSSTATS_OV1) { - /* Copy nfsstatsv1 to nfsstatsov1. */ + /* Copy outstats to nfsstatsov1. */ nfsstatsov1.attrcache_hits = - nfsstatsv1.attrcache_hits; + outstats->attrcache_hits; nfsstatsov1.attrcache_misses = - nfsstatsv1.attrcache_misses; + outstats->attrcache_misses; nfsstatsov1.lookupcache_hits = - nfsstatsv1.lookupcache_hits; + outstats->lookupcache_hits; nfsstatsov1.lookupcache_misses = - nfsstatsv1.lookupcache_misses; + outstats->lookupcache_misses; nfsstatsov1.direofcache_hits = - nfsstatsv1.direofcache_hits; + outstats->direofcache_hits; nfsstatsov1.direofcache_misses = - nfsstatsv1.direofcache_misses; + outstats->direofcache_misses; nfsstatsov1.accesscache_hits = - nfsstatsv1.accesscache_hits; + outstats->accesscache_hits; nfsstatsov1.accesscache_misses = - nfsstatsv1.accesscache_misses; + outstats->accesscache_misses; nfsstatsov1.biocache_reads = - nfsstatsv1.biocache_reads; + outstats->biocache_reads; nfsstatsov1.read_bios = - nfsstatsv1.read_bios; + outstats->read_bios; nfsstatsov1.read_physios = - nfsstatsv1.read_physios; + outstats->read_physios; nfsstatsov1.biocache_writes = - nfsstatsv1.biocache_writes; + outstats->biocache_writes; nfsstatsov1.write_bios = - nfsstatsv1.write_bios; + outstats->write_bios; nfsstatsov1.write_physios = - nfsstatsv1.write_physios; + outstats->write_physios; nfsstatsov1.biocache_readlinks = - nfsstatsv1.biocache_readlinks; + outstats->biocache_readlinks; nfsstatsov1.readlink_bios = - nfsstatsv1.readlink_bios; + outstats->readlink_bios; nfsstatsov1.biocache_readdirs = - nfsstatsv1.biocache_readdirs; + outstats->biocache_readdirs; nfsstatsov1.readdir_bios = - nfsstatsv1.readdir_bios; + outstats->readdir_bios; for (i = 0; i < NFSV42_OLDNPROCS; i++) nfsstatsov1.rpccnt[i] = - nfsstatsv1.rpccnt[i]; + outstats->rpccnt[i]; nfsstatsov1.rpcretries = - nfsstatsv1.rpcretries; + outstats->rpcretries; for (i = 0; i < NFSV42_PURENOPS; i++) nfsstatsov1.srvrpccnt[i] = - nfsstatsv1.srvrpccnt[i]; + outstats->srvrpccnt[i]; for (i = NFSV42_NOPS, j = NFSV42_PURENOPS; i < NFSV42_NOPS + NFSV4OP_FAKENOPS; i++, j++) nfsstatsov1.srvrpccnt[j] = - nfsstatsv1.srvrpccnt[i]; + outstats->srvrpccnt[i]; nfsstatsov1.reserved_0 = 0; nfsstatsov1.reserved_1 = 0; nfsstatsov1.rpcrequests = - nfsstatsv1.rpcrequests; + outstats->rpcrequests; nfsstatsov1.rpctimeouts = - nfsstatsv1.rpctimeouts; + outstats->rpctimeouts; nfsstatsov1.rpcunexpected = - nfsstatsv1.rpcunexpected; + outstats->rpcunexpected; nfsstatsov1.rpcinvalid = - nfsstatsv1.rpcinvalid; + outstats->rpcinvalid; nfsstatsov1.srvcache_inproghits = - nfsstatsv1.srvcache_inproghits; + outstats->srvcache_inproghits; nfsstatsov1.reserved_2 = 0; nfsstatsov1.srvcache_nonidemdonehits = - nfsstatsv1.srvcache_nonidemdonehits; + outstats->srvcache_nonidemdonehits; nfsstatsov1.srvcache_misses = - nfsstatsv1.srvcache_misses; + outstats->srvcache_misses; nfsstatsov1.srvcache_tcppeak = - nfsstatsv1.srvcache_tcppeak; + outstats->srvcache_tcppeak; nfsstatsov1.srvcache_size = - nfsstatsv1.srvcache_size; + outstats->srvcache_size; nfsstatsov1.srvclients = - nfsstatsv1.srvclients; + outstats->srvclients; nfsstatsov1.srvopenowners = - nfsstatsv1.srvopenowners; + outstats->srvopenowners; nfsstatsov1.srvopens = - nfsstatsv1.srvopens; + outstats->srvopens; nfsstatsov1.srvlockowners = - nfsstatsv1.srvlockowners; + outstats->srvlockowners; nfsstatsov1.srvlocks = - nfsstatsv1.srvlocks; + outstats->srvlocks; nfsstatsov1.srvdelegates = - nfsstatsv1.srvdelegates; + outstats->srvdelegates; for (i = 0; i < NFSV42_CBNOPS; i++) nfsstatsov1.cbrpccnt[i] = - nfsstatsv1.cbrpccnt[i]; + outstats->cbrpccnt[i]; nfsstatsov1.clopenowners = - nfsstatsv1.clopenowners; + outstats->clopenowners; nfsstatsov1.clopens = - nfsstatsv1.clopens; + outstats->clopens; nfsstatsov1.cllockowners = - nfsstatsv1.cllockowners; + outstats->cllockowners; nfsstatsov1.cllocks = - nfsstatsv1.cllocks; + outstats->cllocks; nfsstatsov1.cldelegates = - nfsstatsv1.cldelegates; + outstats->cldelegates; nfsstatsov1.cllocalopenowners = - nfsstatsv1.cllocalopenowners; + outstats->cllocalopenowners; nfsstatsov1.cllocalopens = - nfsstatsv1.cllocalopens; + outstats->cllocalopens; nfsstatsov1.cllocallockowners = - nfsstatsv1.cllocallockowners; + outstats->cllocallockowners; nfsstatsov1.cllocallocks = - nfsstatsv1.cllocallocks; + outstats->cllocallocks; nfsstatsov1.srvstartcnt = - nfsstatsv1.srvstartcnt; + outstats->srvstartcnt; nfsstatsov1.srvdonecnt = - nfsstatsv1.srvdonecnt; + outstats->srvdonecnt; for (i = NFSV42_NOPS, j = NFSV42_PURENOPS; i < NFSV42_NOPS + NFSV4OP_FAKENOPS; i++, j++) { nfsstatsov1.srvbytes[j] = - nfsstatsv1.srvbytes[i]; + outstats->srvbytes[i]; nfsstatsov1.srvops[j] = - nfsstatsv1.srvops[i]; + outstats->srvops[i]; nfsstatsov1.srvduration[j] = - nfsstatsv1.srvduration[i]; + outstats->srvduration[i]; } nfsstatsov1.busyfrom = - nfsstatsv1.busyfrom; + outstats->busyfrom; nfsstatsov1.busyfrom = - nfsstatsv1.busyfrom; + outstats->busyfrom; error = copyout(&nfsstatsov1, uap->argp, sizeof(nfsstatsov1)); } else if (nfsstatver.vers != NFSSTATS_V1) error = EPERM; else - error = copyout(&nfsstatsv1, uap->argp, + error = copyout(outstats, uap->argp, sizeof(nfsstatsv1)); } } @@ -721,18 +739,22 @@ nfsstatsv1.rpcinvalid = 0; bzero(nfsstatsv1.rpccnt, sizeof(nfsstatsv1.rpccnt)); + bzero(nfsstatsv1.cbrpccnt, + sizeof(nfsstatsv1.cbrpccnt)); } if ((uap->flag & NFSSVC_ZEROSRVSTATS) != 0) { + nfsd_zero_vnetstats(); nfsstatsv1.srvcache_inproghits = 0; nfsstatsv1.srvcache_nonidemdonehits = 0; nfsstatsv1.srvcache_misses = 0; nfsstatsv1.srvcache_tcppeak = 0; bzero(nfsstatsv1.srvrpccnt, sizeof(nfsstatsv1.srvrpccnt)); - bzero(nfsstatsv1.cbrpccnt, - sizeof(nfsstatsv1.cbrpccnt)); } } +#ifdef VIMAGE + free(outstats, M_TEMP); +#endif goto out; } else if (uap->flag & NFSSVC_NFSUSERDPORT) { u_short sockport; @@ -848,6 +870,85 @@ return (ret); } +/* + * 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 called when a vnet jail is destroyed. + */ +static void +nfsrv_cleanusergroup(struct prison *pr) +{ + struct nfsrv_lughash *hp, *hp2; + struct nfsusrgrp *nusrp, *usrp; + int i; + + NFSD_CURVNET_SET(pr->pr_vnet); + mtx_destroy(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx); + if (NFSD_VNET(nfsuserhash) == NULL) { + NFSD_CURVNET_RESTORE(); + return; + } + + for (i = 0; i < nfsrv_lughashsize; i++) { + hp = &NFSD_VNET(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 = &NFSD_VNET(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(&NFSD_VNET(nfsuserhash)[i].mtx); + mtx_destroy(&NFSD_VNET(nfsusernamehash)[i].mtx); + mtx_destroy(&NFSD_VNET(nfsgroupnamehash)[i].mtx); + mtx_destroy(&NFSD_VNET(nfsgrouphash)[i].mtx); + } + free(NFSD_VNET(nfsuserhash), M_NFSUSERGROUP); + free(NFSD_VNET(nfsusernamehash), M_NFSUSERGROUP); + free(NFSD_VNET(nfsgrouphash), M_NFSUSERGROUP); + free(NFSD_VNET(nfsgroupnamehash), M_NFSUSERGROUP); + free(NFSD_VNET(nfsrv_dnsname), M_NFSSTRING); + NFSD_CURVNET_RESTORE(); +} + +/* + * Initialize everything that needs to be initialized for a vnet. + */ +static void +nfs_vnetinit(const void *unused __unused) +{ + + mtx_init(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx, "nfsuserd", + NULL, MTX_DEF); +} +VNET_SYSINIT(nfs_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY, + nfs_vnetinit, NULL); + +/* Osd entry for nfsrv_cleanup. */ +static int +nfs_prison_cleanup(void *obj, void *data __unused) +{ + struct prison *pr = obj; + + if ((pr->pr_flags & PR_VNET) == 0) + return (0); + nfsrv_cleanusergroup(pr); + return (0); +} + extern int (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *); /* @@ -857,6 +958,9 @@ nfscommon_modevent(module_t mod, int type, void *data) { int error = 0; + osd_method_t methods[PR_MAXMETHOD] = { + [PR_METHOD_REMOVE] = nfs_prison_cleanup, + }; static int loaded = 0; switch (type) { @@ -868,8 +972,8 @@ mtx_init(&nfs_sockl_mutex, "nfs_sockl_mutex", NULL, MTX_DEF); mtx_init(&nfs_slock_mutex, "nfs_slock_mutex", NULL, MTX_DEF); mtx_init(&nfs_req_mutex, "nfs_req_mutex", NULL, MTX_DEF); - mtx_init(&nfsrv_nfsuserdsock.nr_mtx, "nfsuserd", NULL, - MTX_DEF); + /* XXX-BZ OSD to VNET? */ + osd_jail_register(NULL, methods); mtx_init(&nfsrv_dslock_mtx, "nfs4ds", NULL, MTX_DEF); TAILQ_INIT(&nfsrv_devidhead); newnfs_init(); @@ -878,7 +982,8 @@ break; case MOD_UNLOAD: - if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != NOTRUNNING || + if (newnfs_numnfsd != 0 || + NFSD_VNET(nfsrv_nfsuserd) != NOTRUNNING || nfs_numnfscbd != 0) { error = EBUSY; break; @@ -886,7 +991,7 @@ nfsd_call_nfscommon = NULL; /* Clean out the name<-->id cache. */ - nfsrv_cleanusergroup(); + nfsrv_cleanusergroup(&prison0); /* and get rid of the mutexes */ mtx_destroy(&nfs_nameid_mutex); mtx_destroy(&newnfsd_mtx); @@ -895,7 +1000,6 @@ mtx_destroy(&nfs_sockl_mutex); mtx_destroy(&nfs_slock_mutex); mtx_destroy(&nfs_req_mutex); - mtx_destroy(&nfsrv_nfsuserdsock.nr_mtx); mtx_destroy(&nfsrv_dslock_mtx); loaded = 0; break; diff --git a/sys/fs/nfs/nfs_commonsubs.c.vnet b/sys/fs/nfs/nfs_commonsubs.c --- a/sys/fs/nfs/nfs_commonsubs.c.vnet +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -66,17 +66,10 @@ struct timeval nfsboottime; /* Copy boottime once, so it never changes */ int nfscl_ticks; int nfsrv_useacl = 1; -struct nfssockreq nfsrv_nfsuserdsock; -nfsuserd_state nfsrv_nfsuserd = NOTRUNNING; -static int nfsrv_userdupcalls = 0; struct nfsreqhead nfsd_reqq; -uid_t nfsrv_defaultuid = UID_NOBODY; -gid_t nfsrv_defaultgid = GID_NOGROUP; int nfsrv_lease = NFSRV_LEASE; int ncl_mbuf_mlen = MLEN; -int nfsd_enable_stringtouid = 0; int nfsrv_doflexfile = 0; -static int nfs_enable_uidtostring = 0; NFSNAMEIDMUTEX; NFSSOCKMUTEX; extern int nfsrv_lughashsize; @@ -87,10 +80,21 @@ extern struct nfsstatsv1 nfsstatsv1; extern uint32_t nfs_srvmaxio; +NFSD_VNET_DEFINE(int, nfsd_enable_stringtouid) = 0; +NFSD_VNET_DEFINE(struct nfssockreq, nfsrv_nfsuserdsock); +NFSD_VNET_DEFINE(nfsuserd_state, nfsrv_nfsuserd) = NOTRUNNING; +NFSD_VNET_DEFINE(uid_t, nfsrv_defaultuid) = UID_NOBODY; +NFSD_VNET_DEFINE(gid_t, nfsrv_defaultgid) = GID_NOGROUP; + +NFSD_VNET_DEFINE_STATIC(int, nfsrv_userdupcalls) = 0; + SYSCTL_DECL(_vfs_nfs); -SYSCTL_INT(_vfs_nfs, OID_AUTO, enable_uidtostring, CTLFLAG_RW, - &nfs_enable_uidtostring, 0, "Make nfs always send numeric owner_names"); +NFSD_VNET_DEFINE_STATIC(int, nfs_enable_uidtostring) = 0; +SYSCTL_INT(_vfs_nfs, OID_AUTO, enable_uidtostring, + CTLFLAG_NFSD_VNET | CTLFLAG_RW, &NFSD_VNET_NAME(nfs_enable_uidtostring), 0, + "Make nfs always send numeric owner_names"); + int nfsrv_maxpnfsmirror = 1; SYSCTL_INT(_vfs_nfs, OID_AUTO, pnfsmirror, CTLFLAG_RD, &nfsrv_maxpnfsmirror, 0, "Mirror level for pNFS service"); @@ -192,19 +196,16 @@ }; static int ncl_mbuf_mhlen = MHLEN; -static int nfsrv_usercnt = 0; -static int nfsrv_dnsnamelen; -static u_char *nfsrv_dnsname = NULL; -static int nfsrv_usermax = 999999999; -struct nfsrv_lughash { - struct mtx mtx; - struct nfsuserhashhead lughead; -}; -static struct nfsrv_lughash *nfsuserhash; -static struct nfsrv_lughash *nfsusernamehash; -static struct nfsrv_lughash *nfsgrouphash; -static struct nfsrv_lughash *nfsgroupnamehash; +NFSD_VNET_DEFINE_STATIC(int, nfsrv_usercnt) = 0; +NFSD_VNET_DEFINE_STATIC(int, nfsrv_dnsnamelen) = 0; +NFSD_VNET_DEFINE_STATIC(int, nfsrv_usermax) = 999999999; +NFSD_VNET_DEFINE(struct nfsrv_lughash *, nfsuserhash) = NULL; +NFSD_VNET_DEFINE(struct nfsrv_lughash *, nfsusernamehash) = NULL; +NFSD_VNET_DEFINE(struct nfsrv_lughash *, nfsgrouphash) = NULL; +NFSD_VNET_DEFINE(struct nfsrv_lughash *, nfsgroupnamehash) = NULL; +NFSD_VNET_DEFINE(u_char *, nfsrv_dnsname) = NULL; + /* * This static array indicates whether or not the RPC generates a large * reply. This is used by nfs_reply() to decide whether or not an mbuf @@ -1245,6 +1246,7 @@ #endif CTASSERT(sizeof(ino_t) == sizeof(uint64_t)); + NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread)); if (compare) { retnotsup = 0; error = nfsrv_getattrbits(nd, &attrbits, NULL, &retnotsup); @@ -1870,7 +1872,8 @@ } } else if (nap != NULL) { if (nfsv4_strtouid(nd, cp, j, &uid)) - nap->na_uid = nfsrv_defaultuid; + nap->na_uid = + NFSD_VNET(nfsrv_defaultuid); else nap->na_uid = uid; } @@ -1903,7 +1906,8 @@ } } else if (nap != NULL) { if (nfsv4_strtogid(nd, cp, j, &gid)) - nap->na_gid = nfsrv_defaultgid; + nap->na_gid = + NFSD_VNET(nfsrv_defaultgid); else nap->na_gid = gid; } @@ -2266,6 +2270,7 @@ error = nfsm_advance(nd, attrsize - attrsum, -1); } nfsmout: + NFSD_CURVNET_RESTORE(); NFSEXITCODE2(error, nd); return (error); } @@ -3142,14 +3147,16 @@ int cnt, hasampersand, len = NFSV4_SMALLSTR, ret; struct nfsrv_lughash *hp; + NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread)); cnt = 0; tryagain: - if (nfsrv_dnsnamelen > 0 && !nfs_enable_uidtostring) { + if (NFSD_VNET(nfsrv_dnsnamelen) > 0 && + !NFSD_VNET(nfs_enable_uidtostring)) { /* * Always map nfsrv_defaultuid to "nobody". */ - if (uid == nfsrv_defaultuid) { - i = nfsrv_dnsnamelen + 7; + if (uid == NFSD_VNET(nfsrv_defaultuid)) { + i = NFSD_VNET(nfsrv_dnsnamelen) + 7; if (i > len) { if (len > NFSV4_SMALLSTR) free(cp, M_NFSSTRING); @@ -3161,7 +3168,9 @@ *retlenp = i; NFSBCOPY("nobody@", cp, 7); cp += 7; - NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen); + NFSBCOPY(NFSD_VNET(nfsrv_dnsname), cp, + NFSD_VNET(nfsrv_dnsnamelen)); + NFSD_CURVNET_RESTORE(); return; } hasampersand = 0; @@ -3185,7 +3194,7 @@ i = usrp->lug_namelen; else i = usrp->lug_namelen + - nfsrv_dnsnamelen + 1; + NFSD_VNET(nfsrv_dnsnamelen) + 1; if (i > len) { mtx_unlock(&hp->mtx); if (len > NFSV4_SMALLSTR) @@ -3200,12 +3209,14 @@ if (!hasampersand) { cp += usrp->lug_namelen; *cp++ = '@'; - NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen); + NFSBCOPY(NFSD_VNET(nfsrv_dnsname), cp, + NFSD_VNET(nfsrv_dnsnamelen)); } TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash); TAILQ_INSERT_TAIL(&hp->lughead, usrp, lug_numhash); mtx_unlock(&hp->mtx); + NFSD_CURVNET_RESTORE(); return; } } @@ -3233,6 +3244,7 @@ *cp-- = '0' + (tmp % 10); tmp /= 10; } + NFSD_CURVNET_RESTORE(); return; } @@ -3253,7 +3265,7 @@ cnt = 0; uid = oldcred->cr_uid; tryagain: - if (nfsrv_dnsnamelen > 0) { + if (NFSD_VNET(nfsrv_dnsnamelen) > 0) { hp = NFSUSERHASH(uid); mtx_lock(&hp->mtx); TAILQ_FOREACH(usrp, &hp->lughead, lug_numhash) { @@ -3300,6 +3312,7 @@ uid_t tuid; struct nfsrv_lughash *hp, *hp2; + NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread)); if (len == 0) { error = NFSERR_BADOWNER; goto out; @@ -3311,7 +3324,7 @@ /* A numeric string. */ if ((nd->nd_flag & ND_KERBV) == 0 && ((nd->nd_flag & ND_NFSCL) != 0 || - nfsd_enable_stringtouid != 0)) + NFSD_VNET(nfsd_enable_stringtouid) != 0)) *uidp = tuid; else error = NFSERR_BADOWNER; @@ -3328,7 +3341,7 @@ cnt = 0; tryagain: - if (nfsrv_dnsnamelen > 0) { + if (NFSD_VNET(nfsrv_dnsnamelen) > 0) { /* * If an '@' is found and the domain name matches, search for * the name with dns stripped off. @@ -3336,9 +3349,10 @@ * all upper case will not. */ if (cnt == 0 && i < len && i > 0 && - (len - 1 - i) == nfsrv_dnsnamelen && - !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) { - len -= (nfsrv_dnsnamelen + 1); + (len - 1 - i) == NFSD_VNET(nfsrv_dnsnamelen) && + !nfsrv_cmpmixedcase(cp, + NFSD_VNET(nfsrv_dnsname), NFSD_VNET(nfsrv_dnsnamelen))) { + len -= (NFSD_VNET(nfsrv_dnsnamelen) + 1); *(cp - 1) = '\0'; } @@ -3346,7 +3360,7 @@ * Check for the special case of "nobody". */ if (len == 6 && !NFSBCMP(str, "nobody", 6)) { - *uidp = nfsrv_defaultuid; + *uidp = NFSD_VNET(nfsrv_defaultuid); error = 0; goto out; } @@ -3380,6 +3394,7 @@ error = NFSERR_BADOWNER; out: + NFSD_CURVNET_RESTORE(); NFSEXITCODE(error); return (error); } @@ -3401,14 +3416,16 @@ int cnt, hasampersand, len = NFSV4_SMALLSTR, ret; struct nfsrv_lughash *hp; + NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread)); cnt = 0; tryagain: - if (nfsrv_dnsnamelen > 0 && !nfs_enable_uidtostring) { + if (NFSD_VNET(nfsrv_dnsnamelen) > 0 && + !NFSD_VNET(nfs_enable_uidtostring)) { /* * Always map nfsrv_defaultgid to "nogroup". */ - if (gid == nfsrv_defaultgid) { - i = nfsrv_dnsnamelen + 8; + if (gid == NFSD_VNET(nfsrv_defaultgid)) { + i = NFSD_VNET(nfsrv_dnsnamelen) + 8; if (i > len) { if (len > NFSV4_SMALLSTR) free(cp, M_NFSSTRING); @@ -3420,7 +3437,9 @@ *retlenp = i; NFSBCOPY("nogroup@", cp, 8); cp += 8; - NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen); + NFSBCOPY(NFSD_VNET(nfsrv_dnsname), cp, + NFSD_VNET(nfsrv_dnsnamelen)); + NFSD_CURVNET_RESTORE(); return; } hasampersand = 0; @@ -3444,7 +3463,7 @@ i = usrp->lug_namelen; else i = usrp->lug_namelen + - nfsrv_dnsnamelen + 1; + NFSD_VNET(nfsrv_dnsnamelen) + 1; if (i > len) { mtx_unlock(&hp->mtx); if (len > NFSV4_SMALLSTR) @@ -3459,12 +3478,14 @@ if (!hasampersand) { cp += usrp->lug_namelen; *cp++ = '@'; - NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen); + NFSBCOPY(NFSD_VNET(nfsrv_dnsname), cp, + NFSD_VNET(nfsrv_dnsnamelen)); } TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash); TAILQ_INSERT_TAIL(&hp->lughead, usrp, lug_numhash); mtx_unlock(&hp->mtx); + NFSD_CURVNET_RESTORE(); return; } } @@ -3492,6 +3513,7 @@ *cp-- = '0' + (tmp % 10); tmp /= 10; } + NFSD_CURVNET_RESTORE(); return; } @@ -3514,6 +3536,7 @@ gid_t tgid; struct nfsrv_lughash *hp, *hp2; + NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread)); if (len == 0) { error = NFSERR_BADOWNER; goto out; @@ -3525,7 +3548,7 @@ /* A numeric string. */ if ((nd->nd_flag & ND_KERBV) == 0 && ((nd->nd_flag & ND_NFSCL) != 0 || - nfsd_enable_stringtouid != 0)) + NFSD_VNET(nfsd_enable_stringtouid) != 0)) *gidp = tgid; else error = NFSERR_BADOWNER; @@ -3542,15 +3565,16 @@ cnt = 0; tryagain: - if (nfsrv_dnsnamelen > 0) { + if (NFSD_VNET(nfsrv_dnsnamelen) > 0) { /* * If an '@' is found and the dns name matches, search for the * name with the dns stripped off. */ if (cnt == 0 && i < len && i > 0 && - (len - 1 - i) == nfsrv_dnsnamelen && - !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) { - len -= (nfsrv_dnsnamelen + 1); + (len - 1 - i) == NFSD_VNET(nfsrv_dnsnamelen) && + !nfsrv_cmpmixedcase(cp, + NFSD_VNET(nfsrv_dnsname), NFSD_VNET(nfsrv_dnsnamelen))) { + len -= (NFSD_VNET(nfsrv_dnsnamelen) + 1); *(cp - 1) = '\0'; } @@ -3558,7 +3582,7 @@ * Check for the special case of "nogroup". */ if (len == 7 && !NFSBCMP(str, "nogroup", 7)) { - *gidp = nfsrv_defaultgid; + *gidp = NFSD_VNET(nfsrv_defaultgid); error = 0; goto out; } @@ -3592,6 +3616,7 @@ error = NFSERR_BADOWNER; out: + NFSD_CURVNET_RESTORE(); NFSEXITCODE(error); return (error); } @@ -3642,12 +3667,12 @@ int error; NFSLOCKNAMEID(); - if (nfsrv_nfsuserd != NOTRUNNING) { + if (NFSD_VNET(nfsrv_nfsuserd) != NOTRUNNING) { NFSUNLOCKNAMEID(); error = EPERM; goto out; } - nfsrv_nfsuserd = STARTSTOP; + NFSD_VNET(nfsrv_nfsuserd) = STARTSTOP; /* * Set up the socket record and connect. * Set nr_client NULL before unlocking, just to ensure that no other @@ -3655,7 +3680,7 @@ * occur if the use of the nameid lock to protect nfsrv_nfsuserd is * broken. */ - rp = &nfsrv_nfsuserdsock; + rp = &NFSD_VNET(nfsrv_nfsuserdsock); rp->nr_client = NULL; NFSUNLOCKNAMEID(); rp->nr_sotype = SOCK_DGRAM; @@ -3696,12 +3721,12 @@ &rp->nr_client); if (error == 0) { NFSLOCKNAMEID(); - nfsrv_nfsuserd = RUNNING; + NFSD_VNET(nfsrv_nfsuserd) = RUNNING; NFSUNLOCKNAMEID(); } else { free(rp->nr_nam, M_SONAME); NFSLOCKNAMEID(); - nfsrv_nfsuserd = NOTRUNNING; + NFSD_VNET(nfsrv_nfsuserd) = NOTRUNNING; NFSUNLOCKNAMEID(); } out: @@ -3717,20 +3742,20 @@ { NFSLOCKNAMEID(); - if (nfsrv_nfsuserd != RUNNING) { + if (NFSD_VNET(nfsrv_nfsuserd) != RUNNING) { NFSUNLOCKNAMEID(); return; } - nfsrv_nfsuserd = STARTSTOP; + NFSD_VNET(nfsrv_nfsuserd) = STARTSTOP; /* Wait for all upcalls to complete. */ - while (nfsrv_userdupcalls > 0) - msleep(&nfsrv_userdupcalls, NFSNAMEIDMUTEXPTR, PVFS, + while (NFSD_VNET(nfsrv_userdupcalls) > 0) + msleep(&NFSD_VNET(nfsrv_userdupcalls), NFSNAMEIDMUTEXPTR, PVFS, "nfsupcalls", 0); NFSUNLOCKNAMEID(); - newnfs_disconnect(NULL, &nfsrv_nfsuserdsock); - free(nfsrv_nfsuserdsock.nr_nam, M_SONAME); + newnfs_disconnect(NULL, &NFSD_VNET(nfsrv_nfsuserdsock)); + free(NFSD_VNET(nfsrv_nfsuserdsock).nr_nam, M_SONAME); NFSLOCKNAMEID(); - nfsrv_nfsuserd = NOTRUNNING; + NFSD_VNET(nfsrv_nfsuserd) = NOTRUNNING; NFSUNLOCKNAMEID(); } @@ -3750,7 +3775,7 @@ int error; NFSLOCKNAMEID(); - if (nfsrv_nfsuserd != RUNNING) { + if (NFSD_VNET(nfsrv_nfsuserd) != RUNNING) { NFSUNLOCKNAMEID(); error = EPERM; goto out; @@ -3759,9 +3784,9 @@ * Maintain a count of upcalls in progress, so that nfsrv_X() * can wait until no upcalls are in progress. */ - nfsrv_userdupcalls++; + NFSD_VNET(nfsrv_userdupcalls)++; NFSUNLOCKNAMEID(); - KASSERT(nfsrv_userdupcalls > 0, + KASSERT(NFSD_VNET(nfsrv_userdupcalls) > 0, ("nfsrv_getuser: non-positive upcalls")); nd = &nfsd; cred = newnfs_getcred(); @@ -3779,11 +3804,13 @@ len = strlen(name); (void) nfsm_strtom(nd, name, len); } - error = newnfs_request(nd, NULL, NULL, &nfsrv_nfsuserdsock, NULL, NULL, - cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL, NULL); + error = newnfs_request(nd, NULL, NULL, &NFSD_VNET(nfsrv_nfsuserdsock), + NULL, NULL, cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, + NULL, NULL); NFSLOCKNAMEID(); - if (--nfsrv_userdupcalls == 0 && nfsrv_nfsuserd == STARTSTOP) - wakeup(&nfsrv_userdupcalls); + if (--NFSD_VNET(nfsrv_userdupcalls) == 0 && + NFSD_VNET(nfsrv_nfsuserd) == STARTSTOP) + wakeup(&NFSD_VNET(nfsrv_userdupcalls)); NFSUNLOCKNAMEID(); NFSFREECRED(cred); if (!error) { @@ -3823,7 +3850,8 @@ free(cp, M_NFSSTRING); goto out; } - if (atomic_cmpset_acq_int(&nfsrv_dnsnamelen, 0, 0) == 0) { + if (atomic_cmpset_acq_int(&NFSD_VNET(nfsrv_dnsnamelen), 0, 0) == + 0) { /* * Free up all the old stuff and reinitialize hash * lists. All mutexes for both lists must be locked, @@ -3831,80 +3859,81 @@ * ones, to avoid a LOR. */ for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsusernamehash[i].mtx); + mtx_lock(&NFSD_VNET(nfsusernamehash)[i].mtx); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsuserhash[i].mtx); + mtx_lock(&NFSD_VNET(nfsuserhash)[i].mtx); for (i = 0; i < nfsrv_lughashsize; i++) TAILQ_FOREACH_SAFE(usrp, - &nfsuserhash[i].lughead, lug_numhash, nusrp) + &NFSD_VNET(nfsuserhash)[i].lughead, lug_numhash, nusrp) nfsrv_removeuser(usrp, 1); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_unlock(&nfsuserhash[i].mtx); + mtx_unlock(&NFSD_VNET(nfsuserhash)[i].mtx); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_unlock(&nfsusernamehash[i].mtx); + mtx_unlock(&NFSD_VNET(nfsusernamehash)[i].mtx); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsgroupnamehash[i].mtx); + mtx_lock(&NFSD_VNET(nfsgroupnamehash)[i].mtx); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsgrouphash[i].mtx); + mtx_lock(&NFSD_VNET(nfsgrouphash)[i].mtx); for (i = 0; i < nfsrv_lughashsize; i++) TAILQ_FOREACH_SAFE(usrp, - &nfsgrouphash[i].lughead, lug_numhash, + &NFSD_VNET(nfsgrouphash)[i].lughead, lug_numhash, nusrp) nfsrv_removeuser(usrp, 0); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_unlock(&nfsgrouphash[i].mtx); + mtx_unlock(&NFSD_VNET(nfsgrouphash)[i].mtx); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_unlock(&nfsgroupnamehash[i].mtx); - free(nfsrv_dnsname, M_NFSSTRING); - nfsrv_dnsname = NULL; + mtx_unlock(&NFSD_VNET(nfsgroupnamehash)[i].mtx); + free(NFSD_VNET(nfsrv_dnsname), M_NFSSTRING); + NFSD_VNET(nfsrv_dnsname) = NULL; } - if (nfsuserhash == NULL) { + if (NFSD_VNET(nfsuserhash) == NULL) { /* Allocate the hash tables. */ - nfsuserhash = malloc(sizeof(struct nfsrv_lughash) * + NFSD_VNET(nfsuserhash) = malloc(sizeof(struct nfsrv_lughash) * nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK | M_ZERO); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_init(&nfsuserhash[i].mtx, "nfsuidhash", + mtx_init(&NFSD_VNET(nfsuserhash)[i].mtx, "nfsuidhash", NULL, MTX_DEF | MTX_DUPOK); - nfsusernamehash = malloc(sizeof(struct nfsrv_lughash) * + NFSD_VNET(nfsusernamehash) = malloc(sizeof(struct nfsrv_lughash) * nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK | M_ZERO); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_init(&nfsusernamehash[i].mtx, + mtx_init(&NFSD_VNET(nfsusernamehash)[i].mtx, "nfsusrhash", NULL, MTX_DEF | MTX_DUPOK); - nfsgrouphash = malloc(sizeof(struct nfsrv_lughash) * + NFSD_VNET(nfsgrouphash) = malloc(sizeof(struct nfsrv_lughash) * nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK | M_ZERO); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_init(&nfsgrouphash[i].mtx, "nfsgidhash", + mtx_init(&NFSD_VNET(nfsgrouphash)[i].mtx, "nfsgidhash", NULL, MTX_DEF | MTX_DUPOK); - nfsgroupnamehash = malloc(sizeof(struct nfsrv_lughash) * + NFSD_VNET(nfsgroupnamehash) = malloc(sizeof(struct nfsrv_lughash) * nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK | M_ZERO); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_init(&nfsgroupnamehash[i].mtx, + mtx_init(&NFSD_VNET(nfsgroupnamehash)[i].mtx, "nfsgrphash", NULL, MTX_DEF | MTX_DUPOK); } /* (Re)initialize the list heads. */ for (i = 0; i < nfsrv_lughashsize; i++) - TAILQ_INIT(&nfsuserhash[i].lughead); + TAILQ_INIT(&NFSD_VNET(nfsuserhash)[i].lughead); for (i = 0; i < nfsrv_lughashsize; i++) - TAILQ_INIT(&nfsusernamehash[i].lughead); + TAILQ_INIT(&NFSD_VNET(nfsusernamehash)[i].lughead); for (i = 0; i < nfsrv_lughashsize; i++) - TAILQ_INIT(&nfsgrouphash[i].lughead); + TAILQ_INIT(&NFSD_VNET(nfsgrouphash)[i].lughead); for (i = 0; i < nfsrv_lughashsize; i++) - TAILQ_INIT(&nfsgroupnamehash[i].lughead); + TAILQ_INIT(&NFSD_VNET(nfsgroupnamehash)[i].lughead); /* * Put name in "DNS" string. */ - nfsrv_dnsname = cp; - nfsrv_defaultuid = nidp->nid_uid; - nfsrv_defaultgid = nidp->nid_gid; - nfsrv_usercnt = 0; - nfsrv_usermax = nidp->nid_usermax; - atomic_store_rel_int(&nfsrv_dnsnamelen, nidp->nid_namelen); + NFSD_VNET(nfsrv_dnsname) = cp; + NFSD_VNET(nfsrv_defaultuid) = nidp->nid_uid; + NFSD_VNET(nfsrv_defaultgid) = nidp->nid_gid; + NFSD_VNET(nfsrv_usercnt) = 0; + NFSD_VNET(nfsrv_usermax) = nidp->nid_usermax; + atomic_store_rel_int(&NFSD_VNET(nfsrv_dnsnamelen), + nidp->nid_namelen); goto out; } @@ -3931,7 +3960,10 @@ cr->cr_uid = cr->cr_ruid = cr->cr_svuid = nidp->nid_uid; crsetgroups(cr, nidp->nid_ngroup, grps); cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0]; - cr->cr_prison = &prison0; + if (jailed(curthread->td_ucred)) + cr->cr_prison = curthread->td_ucred->cr_prison; + else + cr->cr_prison = &prison0; prison_hold(cr->cr_prison); #ifdef MAC mac_cred_associate_nfsd(cr); @@ -3963,7 +3995,7 @@ if (nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID)) { /* Must lock all username hash lists first, to avoid a LOR. */ for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsusernamehash[i].mtx); + mtx_lock(&NFSD_VNET(nfsusernamehash)[i].mtx); username_locked = 1; hp_idnum = NFSUSERHASH(nidp->nid_uid); mtx_lock(&hp_idnum->mtx); @@ -3992,7 +4024,7 @@ } else if (nidp->nid_flag & (NFSID_DELGID | NFSID_ADDGID)) { /* Must lock all groupname hash lists first, to avoid a LOR. */ for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsgroupnamehash[i].mtx); + mtx_lock(&NFSD_VNET(nfsgroupnamehash)[i].mtx); groupname_locked = 1; hp_idnum = NFSGROUPHASH(nidp->nid_gid); mtx_lock(&hp_idnum->mtx); @@ -4035,7 +4067,7 @@ thp = NFSUSERNAMEHASH(newusrp->lug_name, newusrp->lug_namelen); mtx_assert(&thp->mtx, MA_OWNED); TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_namehash); - atomic_add_int(&nfsrv_usercnt, 1); + atomic_add_int(&NFSD_VNET(nfsrv_usercnt), 1); } else if (nidp->nid_flag & (NFSID_ADDGID | NFSID_ADDGROUPNAME)) { newusrp->lug_gid = nidp->nid_gid; thp = NFSGROUPHASH(newusrp->lug_gid); @@ -4044,7 +4076,7 @@ thp = NFSGROUPNAMEHASH(newusrp->lug_name, newusrp->lug_namelen); mtx_assert(&thp->mtx, MA_OWNED); TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_namehash); - atomic_add_int(&nfsrv_usercnt, 1); + atomic_add_int(&NFSD_VNET(nfsrv_usercnt), 1); } else { if (newusrp->lug_cred != NULL) crfree(newusrp->lug_cred); @@ -4073,17 +4105,17 @@ NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) != 0) { if (username_locked == 0) { for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsusernamehash[i].mtx); + mtx_lock(&NFSD_VNET(nfsusernamehash)[i].mtx); username_locked = 1; } KASSERT(user_locked == 0, ("nfssvc_idname: user_locked")); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsuserhash[i].mtx); + mtx_lock(&NFSD_VNET(nfsuserhash)[i].mtx); user_locked = 1; for (i = 0; i < nfsrv_lughashsize; i++) { TAILQ_FOREACH_SAFE(usrp, - &nfsuserhash[i].lughead, lug_numhash, + &NFSD_VNET(nfsuserhash)[i].lughead, lug_numhash, nusrp) if (usrp->lug_expiry < NFSD_MONOSEC) nfsrv_removeuser(usrp, 1); @@ -4094,26 +4126,26 @@ * algorithm. This code deletes the least * recently used entry on each hash list. */ - if (nfsrv_usercnt <= nfsrv_usermax) + if (NFSD_VNET(nfsrv_usercnt) <= NFSD_VNET(nfsrv_usermax)) break; - usrp = TAILQ_FIRST(&nfsuserhash[i].lughead); + usrp = TAILQ_FIRST(&NFSD_VNET(nfsuserhash)[i].lughead); if (usrp != NULL) nfsrv_removeuser(usrp, 1); } } else { if (groupname_locked == 0) { for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsgroupnamehash[i].mtx); + mtx_lock(&NFSD_VNET(nfsgroupnamehash)[i].mtx); groupname_locked = 1; } KASSERT(group_locked == 0, ("nfssvc_idname: group_locked")); for (i = 0; i < nfsrv_lughashsize; i++) - mtx_lock(&nfsgrouphash[i].mtx); + mtx_lock(&NFSD_VNET(nfsgrouphash)[i].mtx); group_locked = 1; for (i = 0; i < nfsrv_lughashsize; i++) { TAILQ_FOREACH_SAFE(usrp, - &nfsgrouphash[i].lughead, lug_numhash, + &NFSD_VNET(nfsgrouphash)[i].lughead, lug_numhash, nusrp) if (usrp->lug_expiry < NFSD_MONOSEC) nfsrv_removeuser(usrp, 0); @@ -4124,9 +4156,9 @@ * algorithm. This code deletes the least * recently user entry on each hash list. */ - if (nfsrv_usercnt <= nfsrv_usermax) + if (NFSD_VNET(nfsrv_usercnt) <= NFSD_VNET(nfsrv_usermax)) break; - usrp = TAILQ_FIRST(&nfsgrouphash[i].lughead); + usrp = TAILQ_FIRST(&NFSD_VNET(nfsgrouphash)[i].lughead); if (usrp != NULL) nfsrv_removeuser(usrp, 0); } @@ -4142,16 +4174,16 @@ mtx_unlock(&hp_name->mtx); if (user_locked != 0) for (i = 0; i < nfsrv_lughashsize; i++) - mtx_unlock(&nfsuserhash[i].mtx); + mtx_unlock(&NFSD_VNET(nfsuserhash)[i].mtx); if (username_locked != 0) for (i = 0; i < nfsrv_lughashsize; i++) - mtx_unlock(&nfsusernamehash[i].mtx); + mtx_unlock(&NFSD_VNET(nfsusernamehash)[i].mtx); if (group_locked != 0) for (i = 0; i < nfsrv_lughashsize; i++) - mtx_unlock(&nfsgrouphash[i].mtx); + mtx_unlock(&NFSD_VNET(nfsgrouphash)[i].mtx); if (groupname_locked != 0) for (i = 0; i < nfsrv_lughashsize; i++) - mtx_unlock(&nfsgroupnamehash[i].mtx); + mtx_unlock(&NFSD_VNET(nfsgroupnamehash)[i].mtx); out: NFSEXITCODE(error); return (error); @@ -4180,59 +4212,10 @@ mtx_assert(&hp->mtx, MA_OWNED); TAILQ_REMOVE(&hp->lughead, usrp, lug_namehash); } - atomic_add_int(&nfsrv_usercnt, -1); + atomic_add_int(&NFSD_VNET(nfsrv_usercnt), -1); if (usrp->lug_cred != NULL) crfree(usrp->lug_cred); free(usrp, M_NFSUSERGROUP); -} - -/* - * 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. - */ -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); } /* diff --git a/sys/fs/nfs/nfs_var.h.vnetnfsuserd b/sys/fs/nfs/nfs_var.h --- a/sys/fs/nfs/nfs_var.h.vnetnfsuserd +++ b/sys/fs/nfs/nfs_var.h @@ -122,7 +122,7 @@ int nfsrv_releaselckown(struct nfsstate *, nfsquad_t, NFSPROC_T *); void nfsrv_zapclient(struct nfsclient *, NFSPROC_T *); int nfssvc_idname(struct nfsd_idargs *); -void nfsrv_servertimer(void); +void nfsrv_servertimer(void *); int nfsrv_getclientipaddr(struct nfsrv_descript *, struct nfsclient *); void nfsrv_setupstable(NFSPROC_T *); void nfsrv_updatestable(NFSPROC_T *); @@ -348,7 +348,6 @@ 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 *); diff --git a/sys/fs/nfs/nfsdport.h.vnet b/sys/fs/nfs/nfsdport.h --- a/sys/fs/nfs/nfsdport.h.vnet +++ b/sys/fs/nfs/nfsdport.h @@ -92,7 +92,7 @@ bcmp(&(f1)->fh_fid, &(f2)->fh_fid, sizeof(struct fid)) == 0) #define NFSLOCKHASH(f) \ - (&nfslockhash[nfsrv_hashfh(f) % nfsrv_lockhashsize]) + (&NFSD_VNET(nfslockhash)[nfsrv_hashfh(f) % nfsrv_lockhashsize]) #define NFSFPVNODE(f) ((f)->f_vnode) #define NFSFPCRED(f) ((f)->f_cred) diff --git a/sys/fs/nfs/nfsport.h.vnet b/sys/fs/nfs/nfsport.h --- a/sys/fs/nfs/nfsport.h.vnet +++ b/sys/fs/nfs/nfsport.h @@ -181,6 +181,77 @@ */ #define NFSMUTEX_T struct mtx +/* Macros for VIMAGE. */ +/* Just define the NFSD_VNETxxx() macros as VNETxxx() macros. */ +#define NFSD_VNET_NAME(n) VNET_NAME(n) +#define NFSD_VNET_DECLARE(t, n) VNET_DECLARE(t, n) +#define NFSD_VNET_DEFINE(t, n) VNET_DEFINE(t, n) +#define NFSD_VNET_DEFINE_STATIC(t, n) VNET_DEFINE_STATIC(t, n) +#define NFSD_VNET(n) VNET(n) + +#define CTLFLAG_NFSD_VNET CTLFLAG_VNET + +#define NFSD_CURVNET_SET(n) CURVNET_SET(n) +#define NFSD_CURVNET_SET_QUIET(n) CURVNET_SET_QUIET(n) +#define NFSD_CURVNET_RESTORE() CURVNET_RESTORE() +#define NFSD_TD_TO_VNET(n) TD_TO_VNET(n) + +#ifdef VIMAGE +#define NFSDSTATS() VNET(nfsstatsv1_vnet) +#define NFSDSTATSDECLARE(s) \ + VNET_DECLARE(struct nfsstatsv1_vnet *, nfsstatsv1_vnet) +#define NFSDSTATSDEFINE(s) \ + VNET_DEFINE(struct nfsstatsv1_vnet *, nfsstatsv1_vnet) +#define nfsd_copy_vnetstats() do { \ + int iii; \ + NFSBCOPY(&nfsstatsv1, outstats, sizeof(nfsstatsv1)); \ + for (iii = 0; iii < NFSV42_NOPS + NFSV4OP_FAKENOPS; iii++) { \ + outstats->srvrpccnt[iii] = \ + VNET(nfsstatsv1_vnet)->srvrpccnt[iii]; \ + outstats->srvbytes[iii] = \ + VNET(nfsstatsv1_vnet)->srvbytes[iii]; \ + outstats->srvops[iii] = \ + VNET(nfsstatsv1_vnet)->srvops[iii]; \ + outstats->srvduration[iii] = \ + VNET(nfsstatsv1_vnet)->srvduration[iii]; \ + } \ + outstats->srvlayouts = VNET(nfsstatsv1_vnet)->srvlayouts; \ + outstats->srvcache_inproghits = \ + VNET(nfsstatsv1_vnet)->srvcache_inproghits; \ + outstats->srvcache_nonidemdonehits = \ + VNET(nfsstatsv1_vnet)->srvcache_nonidemdonehits; \ + outstats->srvcache_misses = \ + VNET(nfsstatsv1_vnet)->srvcache_misses; \ + outstats->srvcache_tcppeak = \ + VNET(nfsstatsv1_vnet)->srvcache_tcppeak; \ + outstats->srvcache_size = VNET(nfsstatsv1_vnet)->srvcache_size; \ + outstats->srvclients = VNET(nfsstatsv1_vnet)->srvclients; \ + outstats->srvopenowners = VNET(nfsstatsv1_vnet)->srvopenowners; \ + outstats->srvopens = VNET(nfsstatsv1_vnet)->srvopens; \ + outstats->srvlockowners = VNET(nfsstatsv1_vnet)->srvlockowners; \ + outstats->srvlocks = VNET(nfsstatsv1_vnet)->srvlocks; \ + outstats->srvdelegates = VNET(nfsstatsv1_vnet)->srvdelegates; \ + outstats->srvstartcnt = VNET(nfsstatsv1_vnet)->srvstartcnt; \ + outstats->srvdonecnt = VNET(nfsstatsv1_vnet)->srvdonecnt; \ + outstats->busyfrom = VNET(nfsstatsv1_vnet)->busyfrom; \ + outstats->busytime = VNET(nfsstatsv1_vnet)->busytime; \ + } while (0) +#define nfsd_zero_vnetstats() do { \ + VNET(nfsstatsv1_vnet)->srvcache_inproghits = 0; \ + VNET(nfsstatsv1_vnet)->srvcache_nonidemdonehits = 0; \ + VNET(nfsstatsv1_vnet)->srvcache_misses = 0; \ + VNET(nfsstatsv1_vnet)->srvcache_tcppeak = 0; \ + bzero(VNET(nfsstatsv1_vnet)->srvrpccnt, \ + sizeof(nfsstatsv1.srvrpccnt)); \ + } while (0) +#else /* !VIMAGE */ +#define NFSDSTATS() (&nfsstatsv1) +#define NFSDSTATSDECLARE(s) extern struct s s +#define NFSDSTATSDEFINE(s) +#define nfsd_copy_vnetstats() +#define nfsd_zero_vnetstats() +#endif /* VIMAGE */ + #endif /* _KERNEL */ /* @@ -503,6 +574,33 @@ }; /* + * Subset of above structure that needs to be vnet'd for the case + * of VIMAGE. + */ +struct nfsstatsv1_vnet { + uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; + uint64_t srvlayouts; + uint64_t srvcache_inproghits; + uint64_t srvcache_nonidemdonehits; + uint64_t srvcache_misses; + uint64_t srvcache_tcppeak; + int srvcache_size; /* Updated by atomic_xx_int(). */ + uint64_t srvclients; + uint64_t srvopenowners; + uint64_t srvopens; + uint64_t srvlockowners; + uint64_t srvlocks; + uint64_t srvdelegates; + uint64_t srvstartcnt; + uint64_t srvdonecnt; + uint64_t srvbytes[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; + uint64_t srvops[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; + struct bintime srvduration[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15]; + struct bintime busyfrom; + struct bintime busytime; +}; + +/* * Newer stats structure. * The vers field will be set to NFSSTATS_OV1 by the caller. */ @@ -1162,6 +1260,12 @@ #ifndef NFS_MAXBSIZE #define NFS_MAXBSIZE (maxbcachebuf) #endif + +/* User/group hash structure for nfsuserhash and friends. */ +struct nfsrv_lughash { + struct mtx mtx; + struct nfsuserhashhead lughead; +}; /* * This macro checks to see if issuing of delegations is allowed for this diff --git a/sys/fs/nfs/nfsrvstate.h.vnet b/sys/fs/nfs/nfsrvstate.h --- a/sys/fs/nfs/nfsrvstate.h.vnet +++ b/sys/fs/nfs/nfsrvstate.h @@ -58,18 +58,18 @@ TAILQ_HEAD(nfsuserhashhead, nfsusrgrp); #define NFSCLIENTHASH(id) \ - (&nfsclienthash[(id).lval[1] % nfsrv_clienthashsize]) + (&NFSD_VNET(nfsclienthash)[(id).lval[1] % nfsrv_clienthashsize]) #define NFSSTATEHASH(clp, id) \ (&((clp)->lc_stateid[(id).other[2] % nfsrv_statehashsize])) #define NFSUSERHASH(id) \ - (&nfsuserhash[(id) % nfsrv_lughashsize]) + (&NFSD_VNET(nfsuserhash)[(id) % nfsrv_lughashsize]) #define NFSUSERNAMEHASH(p, l) \ - (&nfsusernamehash[((l)>=4?(*(p)+*((p)+1)+*((p)+2)+*((p)+3)):*(p)) \ + (&NFSD_VNET(nfsusernamehash)[((l)>=4?(*(p)+*((p)+1)+*((p)+2)+*((p)+3)):*(p)) \ % nfsrv_lughashsize]) #define NFSGROUPHASH(id) \ - (&nfsgrouphash[(id) % nfsrv_lughashsize]) + (&NFSD_VNET(nfsgrouphash)[(id) % nfsrv_lughashsize]) #define NFSGROUPNAMEHASH(p, l) \ - (&nfsgroupnamehash[((l)>=4?(*(p)+*((p)+1)+*((p)+2)+*((p)+3)):*(p)) \ + (&NFSD_VNET(nfsgroupnamehash)[((l)>=4?(*(p)+*((p)+1)+*((p)+2)+*((p)+3)):*(p)) \ % nfsrv_lughashsize]) struct nfssessionhash { @@ -77,7 +77,8 @@ struct nfssessionhashhead list; }; #define NFSSESSIONHASH(f) \ - (&nfssessionhash[nfsrv_hashsessionid(f) % nfsrv_sessionhashsize]) + (&NFSD_VNET(nfssessionhash)[nfsrv_hashsessionid(f) % \ + nfsrv_sessionhashsize]) struct nfslayouthash { struct mtx mtx; diff --git a/sys/fs/nfsserver/nfs_fha_new.c.vnet b/sys/fs/nfsserver/nfs_fha_new.c --- a/sys/fs/nfsserver/nfs_fha_new.c.vnet +++ b/sys/fs/nfsserver/nfs_fha_new.c @@ -61,8 +61,9 @@ SYSCTL_DECL(_vfs_nfsd); extern int newnfs_nfsv3_procid[]; -extern SVCPOOL *nfsrvd_pool; +NFSD_VNET_DECLARE(SVCPOOL *, nfsrvd_pool); + SYSINIT(nfs_fhanew, SI_SUB_ROOT_CONF, SI_ORDER_ANY, fhanew_init, NULL); SYSUNINIT(nfs_fhanew, SI_SUB_ROOT_CONF, SI_ORDER_ANY, fhanew_uninit, NULL); @@ -79,7 +80,7 @@ snprintf(softc->server_name, sizeof(softc->server_name), FHANEW_SERVER_NAME); - softc->pool = &nfsrvd_pool; + softc->pool = &NFSD_VNET(nfsrvd_pool); /* * Initialize the sysctl context list for the fha module. diff --git a/sys/fs/nfsserver/nfs_nfsdcache.c.vnet b/sys/fs/nfsserver/nfs_nfsdcache.c --- a/sys/fs/nfsserver/nfs_nfsdcache.c.vnet +++ b/sys/fs/nfsserver/nfs_nfsdcache.c @@ -160,12 +160,17 @@ */ #include -extern struct nfsstatsv1 nfsstatsv1; extern struct mtx nfsrc_udpmtx; -extern struct nfsrchash_bucket nfsrchash_table[NFSRVCACHE_HASHSIZE]; -extern struct nfsrchash_bucket nfsrcahash_table[NFSRVCACHE_HASHSIZE]; -int nfsrc_floodlevel = NFSRVCACHE_FLOODLEVEL, nfsrc_tcpsavedreplies = 0; +NFSDSTATSDECLARE(nfsstatsv1); + +NFSD_VNET_DECLARE(struct nfsrvhashhead *, nfsrvudphashtbl); +NFSD_VNET_DECLARE(struct nfsrchash_bucket *, nfsrchash_table); +NFSD_VNET_DECLARE(struct nfsrchash_bucket *, nfsrcahash_table); + +NFSD_VNET_DEFINE(int, nfsrc_floodlevel) = NFSRVCACHE_FLOODLEVEL; +NFSD_VNET_DEFINE(int, nfsrc_tcpsavedreplies) = 0; + SYSCTL_DECL(_vfs_nfsd); static u_int nfsrc_tcphighwater = 0; @@ -180,8 +185,8 @@ return (error); if (newhighwater < 0) return (EINVAL); - if (newhighwater >= nfsrc_floodlevel) - nfsrc_floodlevel = newhighwater + newhighwater / 5; + if (newhighwater >= NFSD_VNET(nfsrc_floodlevel)) + NFSD_VNET(nfsrc_floodlevel) = newhighwater + newhighwater / 5; nfsrc_tcphighwater = newhighwater; return (0); } @@ -202,9 +207,8 @@ &nfsrc_tcpnonidempotent, 0, "Enable the DRC for NFS over TCP"); -static int nfsrc_udpcachesize = 0; -static TAILQ_HEAD(, nfsrvcache) nfsrvudplru; -static struct nfsrvhashhead nfsrvudphashtbl[NFSRVCACHE_HASHSIZE]; +NFSD_VNET_DEFINE_STATIC(int, nfsrc_udpcachesize) = 0; +NFSD_VNET_DEFINE_STATIC(TAILQ_HEAD(, nfsrvcache), nfsrvudplru); /* * and the reverse mapping from generic to Version 2 procedure numbers @@ -236,10 +240,10 @@ #define nfsrc_hash(xid) (((xid) + ((xid) >> 24)) % NFSRVCACHE_HASHSIZE) #define NFSRCUDPHASH(xid) \ - (&nfsrvudphashtbl[nfsrc_hash(xid)]) + (&NFSD_VNET(nfsrvudphashtbl)[nfsrc_hash(xid)]) #define NFSRCHASH(xid) \ - (&nfsrchash_table[nfsrc_hash(xid)].tbl) -#define NFSRCAHASH(xid) (&nfsrcahash_table[nfsrc_hash(xid)]) + (&NFSD_VNET(nfsrchash_table)[nfsrc_hash(xid)].tbl) +#define NFSRCAHASH(xid) (&NFSD_VNET(nfsrcahash_table)[nfsrc_hash(xid)]) #define TRUE 1 #define FALSE 0 #define NFSRVCACHE_CHECKLEN 100 @@ -295,7 +299,7 @@ if ((rp->rc_flag & RC_UDP) != 0) return (&nfsrc_udpmtx); - return (&nfsrchash_table[nfsrc_hash(rp->rc_xid)].mtx); + return (&NFSD_VNET(nfsrchash_table)[nfsrc_hash(rp->rc_xid)].mtx); } /* @@ -305,21 +309,27 @@ nfsrvd_initcache(void) { int i; - static int inited = 0; - if (inited) - return; - inited = 1; + NFSD_VNET(nfsrvudphashtbl) = malloc(sizeof(struct nfsrvhashhead) * + NFSRVCACHE_HASHSIZE, M_NFSRVCACHE, M_WAITOK | M_ZERO); + NFSD_VNET(nfsrchash_table) = malloc(sizeof(struct nfsrchash_bucket) * + NFSRVCACHE_HASHSIZE, M_NFSRVCACHE, M_WAITOK | M_ZERO); + NFSD_VNET(nfsrcahash_table) = malloc(sizeof(struct nfsrchash_bucket) * + NFSRVCACHE_HASHSIZE, M_NFSRVCACHE, M_WAITOK | M_ZERO); for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { - LIST_INIT(&nfsrvudphashtbl[i]); - LIST_INIT(&nfsrchash_table[i].tbl); - LIST_INIT(&nfsrcahash_table[i].tbl); + mtx_init(&NFSD_VNET(nfsrchash_table)[i].mtx, "nfsrtc", NULL, + MTX_DEF); + mtx_init(&NFSD_VNET(nfsrcahash_table)[i].mtx, "nfsrtca", NULL, + MTX_DEF); } - TAILQ_INIT(&nfsrvudplru); - nfsrc_tcpsavedreplies = 0; - nfsrc_udpcachesize = 0; - nfsstatsv1.srvcache_tcppeak = 0; - nfsstatsv1.srvcache_size = 0; + for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { + LIST_INIT(&NFSD_VNET(nfsrvudphashtbl)[i]); + LIST_INIT(&NFSD_VNET(nfsrchash_table)[i].tbl); + LIST_INIT(&NFSD_VNET(nfsrcahash_table)[i].tbl); + } + TAILQ_INIT(&NFSD_VNET(nfsrvudplru)); + NFSD_VNET(nfsrc_tcpsavedreplies) = 0; + NFSD_VNET(nfsrc_udpcachesize) = 0; } /* @@ -392,17 +402,17 @@ if (rp->rc_flag == 0) panic("nfs udp cache0"); rp->rc_flag |= RC_LOCKED; - TAILQ_REMOVE(&nfsrvudplru, rp, rc_lru); - TAILQ_INSERT_TAIL(&nfsrvudplru, rp, rc_lru); + TAILQ_REMOVE(&NFSD_VNET(nfsrvudplru), rp, rc_lru); + TAILQ_INSERT_TAIL(&NFSD_VNET(nfsrvudplru), rp, rc_lru); if (rp->rc_flag & RC_INPROG) { - nfsstatsv1.srvcache_inproghits++; + NFSDSTATS()->srvcache_inproghits++; mtx_unlock(mutex); ret = RC_DROPIT; } else if (rp->rc_flag & RC_REPSTATUS) { /* * V2 only. */ - nfsstatsv1.srvcache_nonidemdonehits++; + NFSDSTATS()->srvcache_nonidemdonehits++; mtx_unlock(mutex); nfsrvd_rephead(nd); *(nd->nd_errp) = rp->rc_status; @@ -410,7 +420,7 @@ rp->rc_timestamp = NFSD_MONOSEC + NFSRVCACHE_UDPTIMEOUT; } else if (rp->rc_flag & RC_REPMBUF) { - nfsstatsv1.srvcache_nonidemdonehits++; + NFSDSTATS()->srvcache_nonidemdonehits++; mtx_unlock(mutex); nd->nd_mreq = m_copym(rp->rc_reply, 0, M_COPYALL, M_WAITOK); @@ -425,9 +435,9 @@ goto out; } } - nfsstatsv1.srvcache_misses++; - atomic_add_int(&nfsstatsv1.srvcache_size, 1); - nfsrc_udpcachesize++; + NFSDSTATS()->srvcache_misses++; + atomic_add_int(&NFSDSTATS()->srvcache_size, 1); + NFSD_VNET(nfsrc_udpcachesize)++; newrp->rc_flag |= RC_INPROG; saddr = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); @@ -440,7 +450,7 @@ newrp->rc_flag |= RC_INETIPV6; } LIST_INSERT_HEAD(hp, newrp, rc_hash); - TAILQ_INSERT_TAIL(&nfsrvudplru, newrp, rc_lru); + TAILQ_INSERT_TAIL(&NFSD_VNET(nfsrvudplru), newrp, rc_lru); mtx_unlock(mutex); nd->nd_rp = newrp; ret = RC_DOIT; @@ -472,15 +482,15 @@ panic("nfsrvd_updatecache not inprog"); rp->rc_flag &= ~RC_INPROG; if (rp->rc_flag & RC_UDP) { - TAILQ_REMOVE(&nfsrvudplru, rp, rc_lru); - TAILQ_INSERT_TAIL(&nfsrvudplru, rp, rc_lru); + TAILQ_REMOVE(&NFSD_VNET(nfsrvudplru), rp, rc_lru); + TAILQ_INSERT_TAIL(&NFSD_VNET(nfsrvudplru), rp, rc_lru); } /* * Reply from cache is a special case returned by nfsrv_checkseqid(). */ if (nd->nd_repstat == NFSERR_REPLYFROMCACHE) { - nfsstatsv1.srvcache_nonidemdonehits++; + NFSDSTATS()->srvcache_nonidemdonehits++; mtx_unlock(mutex); nd->nd_repstat = 0; if (nd->nd_mreq) @@ -503,7 +513,7 @@ (rp->rc_refcnt > 0 || ((nd->nd_flag & ND_SAVEREPLY) && (rp->rc_flag & RC_UDP)) || ((nd->nd_flag & ND_SAVEREPLY) && !(rp->rc_flag & RC_UDP) && - nfsrc_tcpsavedreplies <= nfsrc_floodlevel && + NFSD_VNET(nfsrc_tcpsavedreplies) <= NFSD_VNET(nfsrc_floodlevel) && nfsrc_tcpnonidempotent))) { if (rp->rc_refcnt > 0) { if (!(rp->rc_flag & RC_NFSV4)) @@ -517,11 +527,12 @@ mtx_unlock(mutex); } else { if (!(rp->rc_flag & RC_UDP)) { - atomic_add_int(&nfsrc_tcpsavedreplies, 1); - if (nfsrc_tcpsavedreplies > - nfsstatsv1.srvcache_tcppeak) - nfsstatsv1.srvcache_tcppeak = - nfsrc_tcpsavedreplies; + atomic_add_int(&NFSD_VNET(nfsrc_tcpsavedreplies), + 1); + if (NFSD_VNET(nfsrc_tcpsavedreplies) > + NFSDSTATS()->srvcache_tcppeak) + NFSDSTATS()->srvcache_tcppeak = + NFSD_VNET(nfsrc_tcpsavedreplies); } mtx_unlock(mutex); m = m_copym(nd->nd_mreq, 0, M_COPYALL, M_WAITOK); @@ -678,7 +689,7 @@ panic("nfs tcp cache0"); rp->rc_flag |= RC_LOCKED; if (rp->rc_flag & RC_INPROG) { - nfsstatsv1.srvcache_inproghits++; + NFSDSTATS()->srvcache_inproghits++; mtx_unlock(mutex); if (newrp->rc_sockref == rp->rc_sockref) nfsrc_marksametcpconn(rp->rc_sockref); @@ -687,7 +698,7 @@ /* * V2 only. */ - nfsstatsv1.srvcache_nonidemdonehits++; + NFSDSTATS()->srvcache_nonidemdonehits++; mtx_unlock(mutex); if (newrp->rc_sockref == rp->rc_sockref) nfsrc_marksametcpconn(rp->rc_sockref); @@ -696,7 +707,7 @@ *(nd->nd_errp) = rp->rc_status; rp->rc_timestamp = NFSD_MONOSEC + nfsrc_tcptimeout; } else if (rp->rc_flag & RC_REPMBUF) { - nfsstatsv1.srvcache_nonidemdonehits++; + NFSDSTATS()->srvcache_nonidemdonehits++; mtx_unlock(mutex); if (newrp->rc_sockref == rp->rc_sockref) nfsrc_marksametcpconn(rp->rc_sockref); @@ -711,8 +722,8 @@ free(newrp, M_NFSRVCACHE); goto out; } - nfsstatsv1.srvcache_misses++; - atomic_add_int(&nfsstatsv1.srvcache_size, 1); + NFSDSTATS()->srvcache_misses++; + atomic_add_int(&NFSDSTATS()->srvcache_size, 1); /* * For TCP, multiple entries for a key are allowed, so don't @@ -785,8 +796,8 @@ LIST_REMOVE(rp, rc_hash); if (rp->rc_flag & RC_UDP) { - TAILQ_REMOVE(&nfsrvudplru, rp, rc_lru); - nfsrc_udpcachesize--; + TAILQ_REMOVE(&NFSD_VNET(nfsrvudplru), rp, rc_lru); + NFSD_VNET(nfsrc_udpcachesize)--; } else if (rp->rc_acked != RC_NO_SEQ) { hbp = NFSRCAHASH(rp->rc_sockref); mtx_lock(&hbp->mtx); @@ -798,10 +809,10 @@ if (rp->rc_flag & RC_REPMBUF) { m_freem(rp->rc_reply); if (!(rp->rc_flag & RC_UDP)) - atomic_add_int(&nfsrc_tcpsavedreplies, -1); + atomic_add_int(&NFSD_VNET(nfsrc_tcpsavedreplies), -1); } free(rp, M_NFSRVCACHE); - atomic_add_int(&nfsstatsv1.srvcache_size, -1); + atomic_add_int(&NFSDSTATS()->srvcache_size, -1); } /* @@ -814,20 +825,22 @@ int i; for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { - mtx_lock(&nfsrchash_table[i].mtx); - LIST_FOREACH_SAFE(rp, &nfsrchash_table[i].tbl, rc_hash, nextrp) + mtx_lock(&NFSD_VNET(nfsrchash_table)[i].mtx); + LIST_FOREACH_SAFE(rp, &NFSD_VNET(nfsrchash_table)[i].tbl, + rc_hash, nextrp) nfsrc_freecache(rp); - mtx_unlock(&nfsrchash_table[i].mtx); + mtx_unlock(&NFSD_VNET(nfsrchash_table)[i].mtx); } mtx_lock(&nfsrc_udpmtx); for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { - LIST_FOREACH_SAFE(rp, &nfsrvudphashtbl[i], rc_hash, nextrp) { + LIST_FOREACH_SAFE(rp, &NFSD_VNET(nfsrvudphashtbl)[i], rc_hash, + nextrp) { nfsrc_freecache(rp); } } - nfsstatsv1.srvcache_size = 0; + NFSDSTATS()->srvcache_size = 0; mtx_unlock(&nfsrc_udpmtx); - nfsrc_tcpsavedreplies = 0; + NFSD_VNET(nfsrc_tcpsavedreplies) = 0; } #define HISTSIZE 16 @@ -864,25 +877,28 @@ if (atomic_cmpset_acq_int(&onethread, 0, 1) == 0) return; if (NFSD_MONOSEC != udp_lasttrim || - nfsrc_udpcachesize >= (nfsrc_udphighwater + + NFSD_VNET(nfsrc_udpcachesize) >= (nfsrc_udphighwater + nfsrc_udphighwater / 2)) { mtx_lock(&nfsrc_udpmtx); udp_lasttrim = NFSD_MONOSEC; - TAILQ_FOREACH_SAFE(rp, &nfsrvudplru, rc_lru, nextrp) { + TAILQ_FOREACH_SAFE(rp, &NFSD_VNET(nfsrvudplru), rc_lru, + nextrp) { if (!(rp->rc_flag & (RC_INPROG|RC_LOCKED|RC_WANTED)) && rp->rc_refcnt == 0 && ((rp->rc_flag & RC_REFCNT) || udp_lasttrim > rp->rc_timestamp || - nfsrc_udpcachesize > nfsrc_udphighwater)) + NFSD_VNET(nfsrc_udpcachesize) > + nfsrc_udphighwater)) nfsrc_freecache(rp); } mtx_unlock(&nfsrc_udpmtx); } if (NFSD_MONOSEC != tcp_lasttrim || - nfsrc_tcpsavedreplies >= nfsrc_tcphighwater) { + NFSD_VNET(nfsrc_tcpsavedreplies) >= nfsrc_tcphighwater) { force = nfsrc_tcphighwater / 4; if (force > 0 && - nfsrc_tcpsavedreplies + force >= nfsrc_tcphighwater) { + NFSD_VNET(nfsrc_tcpsavedreplies) + force >= + nfsrc_tcphighwater) { for (i = 0; i < HISTSIZE; i++) time_histo[i] = 0; i = 0; @@ -901,8 +917,9 @@ tto = nfsrc_tcptimeout; tcp_lasttrim = NFSD_MONOSEC; for (; i <= lastslot; i++) { - mtx_lock(&nfsrchash_table[i].mtx); - LIST_FOREACH_SAFE(rp, &nfsrchash_table[i].tbl, rc_hash, + mtx_lock(&NFSD_VNET(nfsrchash_table)[i].mtx); + LIST_FOREACH_SAFE(rp, + &NFSD_VNET(nfsrchash_table)[i].tbl, rc_hash, nextrp) { if (!(rp->rc_flag & (RC_INPROG|RC_LOCKED|RC_WANTED)) @@ -932,7 +949,7 @@ time_histo[j]++; } } - mtx_unlock(&nfsrchash_table[i].mtx); + mtx_unlock(&NFSD_VNET(nfsrchash_table)[i].mtx); } if (force) { /* @@ -951,8 +968,9 @@ k = 1; thisstamp = tcp_lasttrim + k; for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { - mtx_lock(&nfsrchash_table[i].mtx); - LIST_FOREACH_SAFE(rp, &nfsrchash_table[i].tbl, + mtx_lock(&NFSD_VNET(nfsrchash_table)[i].mtx); + LIST_FOREACH_SAFE(rp, + &NFSD_VNET(nfsrchash_table)[i].tbl, rc_hash, nextrp) { if (!(rp->rc_flag & (RC_INPROG|RC_LOCKED|RC_WANTED)) @@ -962,7 +980,7 @@ rp->rc_acked == RC_ACK)) nfsrc_freecache(rp); } - mtx_unlock(&nfsrchash_table[i].mtx); + mtx_unlock(&NFSD_VNET(nfsrchash_table)[i].mtx); } } } diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c.vnet b/sys/fs/nfsserver/nfs_nfsdkrpc.c --- a/sys/fs/nfsserver/nfs_nfsdkrpc.c.vnet +++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c @@ -52,7 +52,6 @@ NFSDLOCKMUTEX; NFSV4ROOTLOCKMUTEX; -struct nfsv4lock nfsd_suspend_lock; char *nfsrv_zeropnfsdat = NULL; /* @@ -85,32 +84,39 @@ SYSCTL_DECL(_vfs_nfsd); -SVCPOOL *nfsrvd_pool; - -static int nfs_privport = 0; -SYSCTL_INT(_vfs_nfsd, OID_AUTO, nfs_privport, CTLFLAG_RWTUN, - &nfs_privport, 0, +NFSD_VNET_DEFINE_STATIC(int, nfs_privport) = 0; +SYSCTL_INT(_vfs_nfsd, OID_AUTO, nfs_privport, CTLFLAG_NFSD_VNET | CTLFLAG_RWTUN, + &NFSD_VNET_NAME(nfs_privport), 0, "Only allow clients using a privileged port for NFSv2, 3 and 4"); -static int nfs_minvers = NFS_VER2; -SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_nfsvers, CTLFLAG_RWTUN, - &nfs_minvers, 0, "The lowest version of NFS handled by the server"); +NFSD_VNET_DEFINE_STATIC(int, nfs_minvers) = NFS_VER2; +SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_nfsvers, + CTLFLAG_NFSD_VNET | CTLFLAG_RWTUN, &NFSD_VNET_NAME(nfs_minvers), 0, + "The lowest version of NFS handled by the server"); -static int nfs_maxvers = NFS_VER4; -SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_nfsvers, CTLFLAG_RWTUN, - &nfs_maxvers, 0, "The highest version of NFS handled by the server"); +NFSD_VNET_DEFINE_STATIC(int, nfs_maxvers) = NFS_VER4; +SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_nfsvers, + CTLFLAG_NFSD_VNET | CTLFLAG_RWTUN, &NFSD_VNET_NAME(nfs_maxvers), 0, + "The highest version of NFS handled by the server"); static int nfs_proc(struct nfsrv_descript *, u_int32_t, SVCXPRT *xprt, struct nfsrvcache **); extern u_long sb_max_adj; extern int newnfs_numnfsd; -extern struct proc *nfsd_master_proc; extern time_t nfsdev_time; extern int nfsrv_writerpc[NFS_NPROCS]; extern volatile int nfsrv_devidcnt; extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS]; +NFSD_VNET_DECLARE(struct proc *, nfsd_master_proc); + +NFSD_VNET_DEFINE(SVCPOOL *, nfsrvd_pool); +NFSD_VNET_DEFINE(int, nfsrv_numnfsd) = 0; +NFSD_VNET_DEFINE(struct nfsv4lock, nfsd_suspend_lock); + +NFSD_VNET_DEFINE_STATIC(bool, nfsrvd_inited) = false; + /* * NFS server system calls */ @@ -125,6 +131,7 @@ u_int maxlen; #endif + NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread)); memset(&nd, 0, sizeof(nd)); if (rqst->rq_vers == NFS_VER2) { if (rqst->rq_proc > NFSV2PROC_STATFS || @@ -169,7 +176,7 @@ nd.nd_mreq = NULL; nd.nd_cred = NULL; - if (nfs_privport != 0) { + if (NFSD_VNET(nfs_privport) != 0) { /* Check if source port is privileged */ u_short port; struct sockaddr *nam = nd.nd_nam; @@ -261,17 +268,17 @@ * nfsv4root exports by nfsvno_v4rootexport(). */ NFSLOCKV4ROOTMUTEX(); - nfsv4_lock(&nfsd_suspend_lock, 0, NULL, NFSV4ROOTLOCKMUTEXPTR, - NULL); - nfsv4_getref(&nfsd_suspend_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, - NULL); + nfsv4_lock(&NFSD_VNET(nfsd_suspend_lock), 0, NULL, + NFSV4ROOTLOCKMUTEXPTR, NULL); + nfsv4_getref(&NFSD_VNET(nfsd_suspend_lock), NULL, + NFSV4ROOTLOCKMUTEXPTR, NULL); NFSUNLOCKV4ROOTMUTEX(); if ((nd.nd_flag & ND_NFSV4) != 0) { nd.nd_repstat = nfsvno_v4rootexport(&nd); if (nd.nd_repstat != 0) { NFSLOCKV4ROOTMUTEX(); - nfsv4_relref(&nfsd_suspend_lock); + nfsv4_relref(&NFSD_VNET(nfsd_suspend_lock)); NFSUNLOCKV4ROOTMUTEX(); svcerr_weakauth(rqst); svc_freereq(rqst); @@ -287,7 +294,7 @@ #endif cacherep = nfs_proc(&nd, rqst->rq_xid, xprt, &rp); NFSLOCKV4ROOTMUTEX(); - nfsv4_relref(&nfsd_suspend_lock); + nfsv4_relref(&NFSD_VNET(nfsd_suspend_lock)); NFSUNLOCKV4ROOTMUTEX(); } else { NFSMGET(nd.nd_mreq); @@ -327,6 +334,7 @@ svc_freereq(rqst); out: + NFSD_CURVNET_RESTORE(); ast_kclear(curthread); NFSEXITCODE(0); } @@ -440,7 +448,9 @@ ack = 0; SVC_ACK(xprt, &ack); + NFSD_CURVNET_SET(NFSD_TD_TO_VNET(curthread)); nfsrc_trimcache(xprt->xp_sockref, ack, 1); + NFSD_CURVNET_RESTORE(); } /* @@ -467,26 +477,28 @@ * unexpectedly. */ if (so->so_type == SOCK_DGRAM) - xprt = svc_dg_create(nfsrvd_pool, so, 0, 0); + xprt = svc_dg_create(NFSD_VNET(nfsrvd_pool), so, 0, 0); else - xprt = svc_vc_create(nfsrvd_pool, so, 0, 0); + xprt = svc_vc_create(NFSD_VNET(nfsrvd_pool), so, 0, 0); if (xprt) { fp->f_ops = &badfileops; fp->f_data = NULL; xprt->xp_sockref = ++sockref; - if (nfs_minvers == NFS_VER2) + if (NFSD_VNET(nfs_minvers) == NFS_VER2) svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, NULL); - if (nfs_minvers <= NFS_VER3 && nfs_maxvers >= NFS_VER3) + if (NFSD_VNET(nfs_minvers) <= NFS_VER3 && + NFSD_VNET(nfs_maxvers) >= NFS_VER3) svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, NULL); - if (nfs_maxvers >= NFS_VER4) + if (NFSD_VNET(nfs_maxvers) >= NFS_VER4) svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, NULL); if (so->so_type == SOCK_STREAM) svc_loss_reg(xprt, nfssvc_loss); SVC_RELEASE(xprt); - } + } else + error = EPERM; out: NFSEXITCODE(error); @@ -518,13 +530,15 @@ * use. */ NFSD_LOCK(); - if (newnfs_numnfsd == 0) { + if (NFSD_VNET(nfsrv_numnfsd) == 0) { + nfsrvd_init(0); nfsdev_time = time_second; p = td->td_proc; PROC_LOCK(p); p->p_flag2 |= P2_AST_SU; PROC_UNLOCK(p); - newnfs_numnfsd++; + newnfs_numnfsd++; /* Total num for all vnets. */ + NFSD_VNET(nfsrv_numnfsd)++; /* Num for this vnet. */ NFSD_UNLOCK(); error = nfsrv_createdevids(args, td); @@ -542,12 +556,15 @@ NFS_VER4); if (!ret2 || !ret3 || !ret4) - printf( - "nfsd: can't register svc name\n"); + printf("nfsd: can't register svc " + "name %s jid:%d\n", principal, + td->td_ucred->cr_prison->pr_id); } - nfsrvd_pool->sp_minthreads = args->minthreads; - nfsrvd_pool->sp_maxthreads = args->maxthreads; + NFSD_VNET(nfsrvd_pool)->sp_minthreads = + args->minthreads; + NFSD_VNET(nfsrvd_pool)->sp_maxthreads = + args->maxthreads; /* * If this is a pNFS service, make Getattr do a @@ -558,7 +575,7 @@ nfsv4_opflag[NFSV4OP_GETATTR].modifyfs = 1; } - svc_run(nfsrvd_pool); + svc_run(NFSD_VNET(nfsrvd_pool)); /* Reset Getattr to not do a vn_start_write(). */ nfsrv_writerpc[NFSPROC_GETATTR] = 0; @@ -572,6 +589,7 @@ } NFSD_LOCK(); newnfs_numnfsd--; + NFSD_VNET(nfsrv_numnfsd)--; nfsrvd_init(1); PROC_LOCK(p); p->p_flag2 &= ~P2_AST_SU; @@ -596,21 +614,25 @@ NFSD_LOCK_ASSERT(); if (terminating) { - nfsd_master_proc = NULL; + NFSD_VNET(nfsd_master_proc) = NULL; NFSD_UNLOCK(); nfsrv_freealllayoutsanddevids(); nfsrv_freeallbackchannel_xprts(); - svcpool_close(nfsrvd_pool); + svcpool_close(NFSD_VNET(nfsrvd_pool)); free(nfsrv_zeropnfsdat, M_TEMP); nfsrv_zeropnfsdat = NULL; NFSD_LOCK(); } else { + /* Initialize per-vnet globals once per vnet. */ + if (NFSD_VNET(nfsrvd_inited)) + return; + NFSD_VNET(nfsrvd_inited) = true; NFSD_UNLOCK(); - nfsrvd_pool = svcpool_create("nfsd", + NFSD_VNET(nfsrvd_pool) = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_nfsd)); - nfsrvd_pool->sp_rcache = NULL; - nfsrvd_pool->sp_assign = fhanew_assign; - nfsrvd_pool->sp_done = fhanew_nd_complete; + NFSD_VNET(nfsrvd_pool)->sp_rcache = NULL; + NFSD_VNET(nfsrvd_pool)->sp_assign = fhanew_assign; + NFSD_VNET(nfsrvd_pool)->sp_done = fhanew_nd_complete; NFSD_LOCK(); } } diff --git a/sys/fs/nfsserver/nfs_nfsdport.c.vnet b/sys/fs/nfsserver/nfs_nfsdport.c --- a/sys/fs/nfsserver/nfs_nfsdport.c.vnet +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -59,46 +60,59 @@ extern u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1; extern int nfsrv_useacl; extern int newnfs_numnfsd; -extern struct mount nfsv4root_mnt; -extern struct nfsrv_stablefirst nfsrv_stablefirst; -extern SVCPOOL *nfsrvd_pool; -extern struct nfsv4lock nfsd_suspend_lock; -extern struct nfsclienthashhead *nfsclienthash; -extern struct nfslockhashhead *nfslockhash; -extern struct nfssessionhash *nfssessionhash; extern int nfsrv_sessionhashsize; -extern struct nfsstatsv1 nfsstatsv1; extern struct nfslayouthash *nfslayouthash; extern int nfsrv_layouthashsize; extern struct mtx nfsrv_dslock_mtx; extern int nfs_pnfsiothreads; -extern struct nfsdontlisthead nfsrv_dontlisthead; -extern volatile int nfsrv_dontlistlen; extern volatile int nfsrv_devidcnt; extern int nfsrv_maxpnfsmirror; extern uint32_t nfs_srvmaxio; extern int nfs_bufpackets; extern u_long sb_max_adj; -struct vfsoptlist nfsv4root_opt, nfsv4root_newopt; + +NFSDSTATSDECLARE(nfsstatsv1); + +NFSD_VNET_DECLARE(int, nfsrv_numnfsd); +NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst); +NFSD_VNET_DECLARE(SVCPOOL *, nfsrvd_pool); +NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash); +NFSD_VNET_DECLARE(struct nfslockhashhead *, nfslockhash); +NFSD_VNET_DECLARE(struct nfssessionhash *, nfssessionhash); +NFSD_VNET_DECLARE(struct nfsv4lock, nfsd_suspend_lock); + NFSDLOCKMUTEX; NFSSTATESPINLOCK; -struct nfsrchash_bucket nfsrchash_table[NFSRVCACHE_HASHSIZE]; -struct nfsrchash_bucket nfsrcahash_table[NFSRVCACHE_HASHSIZE]; struct mtx nfsrc_udpmtx; struct mtx nfs_v4root_mutex; struct mtx nfsrv_dontlistlock_mtx; struct mtx nfsrv_recalllock_mtx; -struct nfsrvfh nfs_rootfh, nfs_pubfh; -int nfs_pubfhset = 0, nfs_rootfhset = 0; -struct proc *nfsd_master_proc = NULL; +struct nfsrvfh nfs_pubfh; +int nfs_pubfhset = 0; int nfsd_debuglevel = 0; static pid_t nfsd_master_pid = (pid_t)-1; static char nfsd_master_comm[MAXCOMLEN + 1]; static struct timeval nfsd_master_start; static uint32_t nfsv4_sysid = 0; static fhandle_t zerofh; -struct callout nfsd_callout; +static int nfsrv_osd_jail_slot; +NFSD_VNET_DEFINE(struct proc *, nfsd_master_proc) = NULL; +NFSD_VNET_DEFINE(struct nfsrvhashhead *, nfsrvudphashtbl); +NFSD_VNET_DEFINE(struct nfsrchash_bucket *, nfsrchash_table); +NFSD_VNET_DEFINE(struct nfsrchash_bucket *, nfsrcahash_table); +NFSD_VNET_DEFINE(struct nfsrvfh, nfs_rootfh); +NFSD_VNET_DEFINE(int, nfs_rootfhset) = 0; +NFSD_VNET_DEFINE(struct callout, nfsd_callout); + +NFSD_VNET_DEFINE_STATIC(struct mount *, nfsv4root_mnt); +NFSD_VNET_DEFINE_STATIC(struct vfsoptlist, nfsv4root_opt); +NFSD_VNET_DEFINE_STATIC(struct vfsoptlist, nfsv4root_newopt); +NFSD_VNET_DEFINE_STATIC(bool, nfsrv_suspend_nfsd) = false; +NFSD_VNET_DEFINE_STATIC(bool, nfsrv_mntinited) = false; + +static void nfsrv_cleanup(struct prison *); + static int nfssvc_srvcall(struct thread *, struct nfssvc_args *, struct ucred *); static void nfsvno_updateds(struct vnode *, struct ucred *, struct thread *); @@ -108,7 +122,6 @@ static int nfs_commit_miss; extern int nfsrv_issuedelegs; extern int nfsrv_dolocallocks; -extern int nfsd_enable_stringtouid; extern struct nfsdevicehead nfsrv_devidhead; static int nfsrv_createiovec(int, struct mbuf **, struct mbuf **, @@ -170,8 +183,10 @@ &nfsrv_dolocallocks, 0, "Enable nfsd to acquire local locks on files"); SYSCTL_INT(_vfs_nfsd, OID_AUTO, debuglevel, CTLFLAG_RW, &nfsd_debuglevel, 0, "Debug level for NFS server"); -SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_stringtouid, CTLFLAG_RW, - &nfsd_enable_stringtouid, 0, "Enable nfsd to accept numeric owner_names"); +NFSD_VNET_DECLARE(int, nfsd_enable_stringtouid); +SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_stringtouid, + CTLFLAG_NFSD_VNET | CTLFLAG_RW, &NFSD_VNET_NAME(nfsd_enable_stringtouid), + 0, "Enable nfsd to accept numeric owner_names"); static int nfsrv_pnfsgetdsattr = 1; SYSCTL_INT(_vfs_nfsd, OID_AUTO, pnfsgetdsattr, CTLFLAG_RW, &nfsrv_pnfsgetdsattr, 0, "When set getattr gets DS attributes via RPC"); @@ -1022,7 +1037,7 @@ nh = nfsrv_sequential_heuristic(uiop, vp); ioflag |= nh->nh_seqcount << IO_SEQSHIFT; /* XXX KDM make this more systematic? */ - nfsstatsv1.srvbytes[NFSV4OP_READ] += uiop->uio_resid; + NFSDSTATS()->srvbytes[NFSV4OP_READ] += uiop->uio_resid; error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred); free(iv, M_TEMP); if (error) { @@ -1147,7 +1162,7 @@ nh = nfsrv_sequential_heuristic(uiop, vp); ioflags |= nh->nh_seqcount << IO_SEQSHIFT; /* XXX KDM make this more systematic? */ - nfsstatsv1.srvbytes[NFSV4OP_WRITE] += uiop->uio_resid; + NFSDSTATS()->srvbytes[NFSV4OP_WRITE] += uiop->uio_resid; error = VOP_WRITE(vp, uiop, ioflags, cred); if (error == 0) nh->nh_nextoff = uiop->uio_offset; @@ -3237,7 +3252,7 @@ error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, &exp->nes_numsecflavor, exp->nes_secflavors); if (error) { - if (nfs_rootfhset) { + if (NFSD_VNET(nfs_rootfhset)) { exp->nes_exflag = 0; exp->nes_numsecflavor = 0; error = 0; @@ -3272,7 +3287,7 @@ error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp, &exp->nes_numsecflavor, exp->nes_secflavors); if (error) { - if (nfs_rootfhset) { + if (NFSD_VNET(nfs_rootfhset)) { exp->nes_exflag = 0; exp->nes_numsecflavor = 0; error = 0; @@ -3440,9 +3455,9 @@ struct nameidata nd; fhandle_t fh; - error = vfs_export(&nfsv4root_mnt, &nfsexargp->export); + error = vfs_export(NFSD_VNET(nfsv4root_mnt), &nfsexargp->export); if ((nfsexargp->export.ex_flags & MNT_DELEXPORT) != 0) - nfs_rootfhset = 0; + NFSD_VNET(nfs_rootfhset) = 0; else if (error == 0) { if (nfsexargp->fspec == NULL) { error = EPERM; @@ -3457,11 +3472,11 @@ error = nfsvno_getfh(nd.ni_vp, &fh, p); vrele(nd.ni_vp); if (!error) { - nfs_rootfh.nfsrvfh_len = NFSX_MYFH; + NFSD_VNET(nfs_rootfh).nfsrvfh_len = NFSX_MYFH; NFSBCOPY((caddr_t)&fh, - nfs_rootfh.nfsrvfh_data, + NFSD_VNET(nfs_rootfh).nfsrvfh_data, sizeof (fhandle_t)); - nfs_rootfhset = 1; + NFSD_VNET(nfs_rootfhset) = 1; } } @@ -3497,29 +3512,52 @@ void nfsd_mntinit(void) { - static int inited = 0; - if (inited) + NFSD_LOCK(); + if (NFSD_VNET(nfsrv_mntinited)) { + NFSD_UNLOCK(); return; - inited = 1; - nfsv4root_mnt.mnt_flag = (MNT_RDONLY | MNT_EXPORTED); - TAILQ_INIT(&nfsv4root_mnt.mnt_nvnodelist); - TAILQ_INIT(&nfsv4root_mnt.mnt_lazyvnodelist); - nfsv4root_mnt.mnt_export = NULL; - TAILQ_INIT(&nfsv4root_opt); - TAILQ_INIT(&nfsv4root_newopt); - nfsv4root_mnt.mnt_opt = &nfsv4root_opt; - nfsv4root_mnt.mnt_optnew = &nfsv4root_newopt; - nfsv4root_mnt.mnt_nvnodelistsize = 0; - nfsv4root_mnt.mnt_lazyvnodelistsize = 0; + } + NFSD_VNET(nfsrv_mntinited) = true; + NFSD_UNLOCK(); + +#ifdef VIMAGE + NFSD_VNET(nfsstatsv1_vnet) = malloc(sizeof(struct nfsstatsv1_vnet), + M_TEMP, M_WAITOK | M_ZERO); +#endif + NFSDSTATS()->srvcache_tcppeak = 0; + NFSDSTATS()->srvcache_size = 0; + NFSD_VNET(nfsv4root_mnt) = malloc(sizeof(struct mount), M_TEMP, + M_WAITOK | M_ZERO); + NFSD_VNET(nfsv4root_mnt)->mnt_flag = (MNT_RDONLY | MNT_EXPORTED); + mtx_init(&NFSD_VNET(nfsv4root_mnt)->mnt_mtx, "nfs4mnt", NULL, MTX_DEF); + lockinit(&NFSD_VNET(nfsv4root_mnt)->mnt_explock, PVFS, "explock", 0, 0); + TAILQ_INIT(&NFSD_VNET(nfsv4root_mnt)->mnt_nvnodelist); + TAILQ_INIT(&NFSD_VNET(nfsv4root_mnt)->mnt_lazyvnodelist); + NFSD_VNET(nfsv4root_mnt)->mnt_export = NULL; + TAILQ_INIT(&NFSD_VNET(nfsv4root_opt)); + TAILQ_INIT(&NFSD_VNET(nfsv4root_newopt)); + NFSD_VNET(nfsv4root_mnt)->mnt_opt = &NFSD_VNET(nfsv4root_opt); + NFSD_VNET(nfsv4root_mnt)->mnt_optnew = &NFSD_VNET(nfsv4root_newopt); + NFSD_VNET(nfsv4root_mnt)->mnt_nvnodelistsize = 0; + NFSD_VNET(nfsv4root_mnt)->mnt_lazyvnodelistsize = 0; + callout_init(&NFSD_VNET(nfsd_callout), 1); + + nfsrvd_initcache(); + nfsd_init(); } static void nfsd_timer(void *arg) { + struct vnet *vnetp; - nfsrv_servertimer(); - callout_reset_sbt(&nfsd_callout, SBT_1S, SBT_1S, nfsd_timer, NULL, 0); + vnetp = (struct vnet *)arg; + NFSD_CURVNET_SET_QUIET(vnetp); + nfsrv_servertimer(vnetp); + callout_reset_sbt(&NFSD_VNET(nfsd_callout), SBT_1S, SBT_1S, nfsd_timer, + arg, 0); + NFSD_CURVNET_RESTORE(); } /* @@ -3601,7 +3639,7 @@ int error = 0, numsecflavor, secflavors[MAXSECFLAVORS], i; uint64_t exflags; - error = vfs_stdcheckexp(&nfsv4root_mnt, nd->nd_nam, &exflags, + error = vfs_stdcheckexp(NFSD_VNET(nfsv4root_mnt), nd->nd_nam, &exflags, &credanon, &numsecflavor, secflavors); if (error) { error = NFSERR_PROGUNAVAIL; @@ -3634,6 +3672,18 @@ return (error); } +/* Osd entry for nfsrv_cleanup. */ +static int +nfsrv_prison_cleanup(void *obj, void *data __unused) +{ + struct prison *pr = obj; + + if ((pr->pr_flags & PR_VNET) == 0) + return (0); + nfsrv_cleanup(pr); + return (0); +} + /* * Nfs server pseudo system call for the nfsd's */ @@ -3656,6 +3706,7 @@ char *buf, *cp, *cp2, *cp3; char fname[PNFS_FILENAME_LEN + 1]; + NFSD_CURVNET_SET(NFSD_TD_TO_VNET(td)); if (uap->flag & NFSSVC_NFSDADDSOCK) { error = copyin(uap->argp, (caddr_t)&sockarg, sizeof (sockarg)); if (error) @@ -3763,8 +3814,9 @@ nfsdarg.mdspathlen = 0; nfsdarg.mirrorcnt = 1; } - nfsd_timer(NULL); + nfsd_timer(NFSD_TD_TO_VNET(td)); error = nfsrvd_nfsd(td, &nfsdarg); + callout_drain(&NFSD_VNET(nfsd_callout)); free(nfsdarg.addr, M_TEMP); free(nfsdarg.dnshost, M_TEMP); free(nfsdarg.dspath, M_TEMP); @@ -3842,6 +3894,7 @@ } out: + NFSD_CURVNET_RESTORE(); NFSEXITCODE(error); return (error); } @@ -3863,7 +3916,6 @@ int error = EINVAL, igotlock; struct proc *procp; gid_t *grps; - static int suspend_nfsd = 0; if (uap->flag & NFSSVC_PUBLICFH) { NFSBZERO((caddr_t)&nfs_pubfh.nfsrvfh_data, @@ -3947,10 +3999,10 @@ error = fp_getfvp(p, stablefd, &fp, &vp); if (!error && (NFSFPFLAG(fp) & (FREAD | FWRITE)) != (FREAD | FWRITE)) error = EBADF; - if (!error && newnfs_numnfsd != 0) + if (!error && NFSD_VNET(nfsrv_numnfsd) != 0) error = EPERM; if (!error) { - nfsrv_stablefirst.nsf_fp = fp; + NFSD_VNET(nfsrv_stablefirst).nsf_fp = fp; nfsrv_setupstable(p); } } else if (uap->flag & NFSSVC_ADMINREVOKE) { @@ -3997,25 +4049,27 @@ nfsd_master_pid = procp->p_pid; bcopy(procp->p_comm, nfsd_master_comm, MAXCOMLEN + 1); nfsd_master_start = procp->p_stats->p_start; - nfsd_master_proc = procp; + NFSD_VNET(nfsd_master_proc) = procp; PROC_UNLOCK(procp); } else if ((uap->flag & NFSSVC_SUSPENDNFSD) != 0) { NFSLOCKV4ROOTMUTEX(); - if (suspend_nfsd == 0) { + if (!NFSD_VNET(nfsrv_suspend_nfsd)) { /* Lock out all nfsd threads */ do { - igotlock = nfsv4_lock(&nfsd_suspend_lock, 1, - NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); - } while (igotlock == 0 && suspend_nfsd == 0); - suspend_nfsd = 1; + igotlock = nfsv4_lock( + &NFSD_VNET(nfsd_suspend_lock), 1, NULL, + NFSV4ROOTLOCKMUTEXPTR, NULL); + } while (igotlock == 0 && + !NFSD_VNET(nfsrv_suspend_nfsd)); + NFSD_VNET(nfsrv_suspend_nfsd) = true; } NFSUNLOCKV4ROOTMUTEX(); error = 0; } else if ((uap->flag & NFSSVC_RESUMENFSD) != 0) { NFSLOCKV4ROOTMUTEX(); - if (suspend_nfsd != 0) { - nfsv4_unlock(&nfsd_suspend_lock, 0); - suspend_nfsd = 0; + if (NFSD_VNET(nfsrv_suspend_nfsd)) { + nfsv4_unlock(&NFSD_VNET(nfsd_suspend_lock), 0); + NFSD_VNET(nfsrv_suspend_nfsd) = false; } NFSUNLOCKV4ROOTMUTEX(); error = 0; @@ -4123,10 +4177,10 @@ { struct proc *procp; - if (nfsd_master_proc != NULL) { + if (NFSD_VNET(nfsd_master_proc) != NULL) { procp = pfind(nfsd_master_pid); /* Try to make sure it is the correct process. */ - if (procp == nfsd_master_proc && + if (procp == NFSD_VNET(nfsd_master_proc) && procp->p_stats->p_start.tv_sec == nfsd_master_start.tv_sec && procp->p_stats->p_start.tv_usec == @@ -4134,7 +4188,7 @@ strcmp(procp->p_comm, nfsd_master_comm) == 0) kern_psignal(procp, SIGUSR2); else - nfsd_master_proc = NULL; + NFSD_VNET(nfsd_master_proc) = NULL; if (procp != NULL) PROC_UNLOCK(procp); @@ -7045,6 +7099,71 @@ free(devid, M_TEMP); } +/* + * Initialize everything that needs to be initialized for a vnet. + */ +static void +nfsrv_vnetinit(const void *unused __unused) +{ + + nfsd_mntinit(); +} +VNET_SYSINIT(nfsrv_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY, + nfsrv_vnetinit, NULL); + +/* + * Clean up everything that is in a vnet and needs to be + * done when the jail is destroyed or the module unloaded. + */ +static void +nfsrv_cleanup(struct prison *pr) +{ + int i; + + NFSD_CURVNET_SET(pr->pr_vnet); + NFSD_LOCK(); + if (!NFSD_VNET(nfsrv_mntinited)) { + NFSD_UNLOCK(); + NFSD_CURVNET_RESTORE(); + return; + } + NFSD_VNET(nfsrv_mntinited) = false; + NFSD_UNLOCK(); + + /* Clean out all NFSv4 state. */ + nfsrv_throwawayallstate(curthread); + + /* Clean the NFS server reply cache */ + nfsrvd_cleancache(); + + /* Free up the krpc server pool. */ + if (NFSD_VNET(nfsrvd_pool) != NULL) + svcpool_destroy(NFSD_VNET(nfsrvd_pool)); + + /* and get rid of the locks */ + for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { + mtx_destroy(&NFSD_VNET(nfsrchash_table)[i].mtx); + mtx_destroy(&NFSD_VNET(nfsrcahash_table)[i].mtx); + } + mtx_destroy(&NFSD_VNET(nfsv4root_mnt)->mnt_mtx); + for (i = 0; i < nfsrv_sessionhashsize; i++) + mtx_destroy(&NFSD_VNET(nfssessionhash)[i].mtx); + lockdestroy(&NFSD_VNET(nfsv4root_mnt)->mnt_explock); + free(NFSD_VNET(nfsrvudphashtbl), M_NFSRVCACHE); + free(NFSD_VNET(nfsrchash_table), M_NFSRVCACHE); + free(NFSD_VNET(nfsrcahash_table), M_NFSRVCACHE); + free(NFSD_VNET(nfsclienthash), M_NFSDCLIENT); + free(NFSD_VNET(nfslockhash), M_NFSDLOCKFILE); + free(NFSD_VNET(nfssessionhash), M_NFSDSESSION); + free(NFSD_VNET(nfsv4root_mnt), M_TEMP); + NFSD_VNET(nfsv4root_mnt) = NULL; +#ifdef VIMAGE + free(NFSD_VNET(nfsstatsv1_vnet), M_TEMP); + NFSD_VNET(nfsstatsv1_vnet) = NULL; +#endif + NFSD_CURVNET_RESTORE(); +} + extern int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *); /* @@ -7054,6 +7173,9 @@ nfsd_modevent(module_t mod, int type, void *data) { int error = 0, i; + osd_method_t methods[PR_MAXMETHOD] = { + [PR_METHOD_REMOVE] = nfsrv_prison_cleanup, + }; static int loaded = 0; switch (type) { @@ -7061,30 +7183,17 @@ if (loaded) goto out; newnfs_portinit(); - for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { - mtx_init(&nfsrchash_table[i].mtx, "nfsrtc", NULL, - MTX_DEF); - mtx_init(&nfsrcahash_table[i].mtx, "nfsrtca", NULL, - MTX_DEF); - } mtx_init(&nfsrc_udpmtx, "nfsuc", NULL, MTX_DEF); mtx_init(&nfs_v4root_mutex, "nfs4rt", NULL, MTX_DEF); - mtx_init(&nfsv4root_mnt.mnt_mtx, "nfs4mnt", NULL, MTX_DEF); mtx_init(&nfsrv_dontlistlock_mtx, "nfs4dnl", NULL, MTX_DEF); mtx_init(&nfsrv_recalllock_mtx, "nfs4rec", NULL, MTX_DEF); - lockinit(&nfsv4root_mnt.mnt_explock, PVFS, "explock", 0, 0); - callout_init(&nfsd_callout, 1); - nfsrvd_initcache(); - nfsd_init(); - NFSD_LOCK(); - nfsrvd_init(0); - NFSD_UNLOCK(); - nfsd_mntinit(); #ifdef VV_DISABLEDELEG vn_deleg_ops.vndeleg_recall = nfsd_recalldelegation; vn_deleg_ops.vndeleg_disable = nfsd_disabledelegation; #endif nfsd_call_nfsd = nfssvc_nfsd; + /* XXX-BZ OSD to VNET? */ + nfsrv_osd_jail_slot = osd_jail_register(NULL, methods); loaded = 1; break; @@ -7099,39 +7208,17 @@ vn_deleg_ops.vndeleg_disable = NULL; #endif nfsd_call_nfsd = NULL; - callout_drain(&nfsd_callout); - - /* Clean out all NFSv4 state. */ - nfsrv_throwawayallstate(curthread); - - /* Clean the NFS server reply cache */ - nfsrvd_cleancache(); - - /* Free up the krpc server pool. */ - if (nfsrvd_pool != NULL) - svcpool_destroy(nfsrvd_pool); - - /* and get rid of the locks */ - for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) { - mtx_destroy(&nfsrchash_table[i].mtx); - mtx_destroy(&nfsrcahash_table[i].mtx); - } + osd_jail_deregister(nfsrv_osd_jail_slot); + nfsrv_cleanup(&prison0); mtx_destroy(&nfsrc_udpmtx); mtx_destroy(&nfs_v4root_mutex); - mtx_destroy(&nfsv4root_mnt.mnt_mtx); mtx_destroy(&nfsrv_dontlistlock_mtx); mtx_destroy(&nfsrv_recalllock_mtx); - for (i = 0; i < nfsrv_sessionhashsize; i++) - mtx_destroy(&nfssessionhash[i].mtx); if (nfslayouthash != NULL) { for (i = 0; i < nfsrv_layouthashsize; i++) mtx_destroy(&nfslayouthash[i].mtx); free(nfslayouthash, M_NFSDSESSION); } - lockdestroy(&nfsv4root_mnt.mnt_explock); - free(nfsclienthash, M_NFSDCLIENT); - free(nfslockhash, M_NFSDLOCKFILE); - free(nfssessionhash, M_NFSDSESSION); loaded = 0; break; default: diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c.vnet b/sys/fs/nfsserver/nfs_nfsdsocket.c --- a/sys/fs/nfsserver/nfs_nfsdsocket.c.vnet +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -42,20 +42,25 @@ #include -extern struct nfsstatsv1 nfsstatsv1; -extern struct nfsrvfh nfs_pubfh, nfs_rootfh; -extern int nfs_pubfhset, nfs_rootfhset; +extern struct nfsrvfh nfs_pubfh; +extern int nfs_pubfhset; extern struct nfsv4lock nfsv4rootfs_lock; -extern struct nfsrv_stablefirst nfsrv_stablefirst; -extern struct nfsclienthashhead *nfsclienthash; extern int nfsrv_clienthashsize; -extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies; extern int nfsd_debuglevel; extern int nfsrv_layouthighwater; extern volatile int nfsrv_layoutcnt; NFSV4ROOTLOCKMUTEX; NFSSTATESPINLOCK; +NFSDSTATSDECLARE(nfsstatsv1); + +NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst); +NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash); +NFSD_VNET_DECLARE(int, nfsrc_floodlevel); +NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies); +NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh); +NFSD_VNET_DECLARE(int, nfs_rootfhset); + int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *) = { (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0, @@ -471,15 +476,15 @@ } mtx_lock(&nfsrvd_statmtx); - if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) { + if (NFSDSTATS()->srvstartcnt == NFSDSTATS()->srvdonecnt) { if (now != NULL) - nfsstatsv1.busyfrom = *now; + NFSDSTATS()->busyfrom = *now; else - binuptime(&nfsstatsv1.busyfrom); + binuptime(&NFSDSTATS()->busyfrom); } - nfsstatsv1.srvrpccnt[op]++; - nfsstatsv1.srvstartcnt++; + NFSDSTATS()->srvrpccnt[op]++; + NFSDSTATS()->srvstartcnt++; mtx_unlock(&nfsrvd_statmtx); } @@ -502,21 +507,21 @@ mtx_lock(&nfsrvd_statmtx); - nfsstatsv1.srvbytes[op] += bytes; - nfsstatsv1.srvops[op]++; + NFSDSTATS()->srvbytes[op] += bytes; + NFSDSTATS()->srvops[op]++; if (then != NULL) { dt = *now; bintime_sub(&dt, then); - bintime_add(&nfsstatsv1.srvduration[op], &dt); + bintime_add(&NFSDSTATS()->srvduration[op], &dt); } dt = *now; - bintime_sub(&dt, &nfsstatsv1.busyfrom); - bintime_add(&nfsstatsv1.busytime, &dt); - nfsstatsv1.busyfrom = *now; + bintime_sub(&dt, &NFSDSTATS()->busyfrom); + bintime_add(&NFSDSTATS()->busytime, &dt); + NFSDSTATS()->busyfrom = *now; - nfsstatsv1.srvdonecnt++; + NFSDSTATS()->srvdonecnt++; mtx_unlock(&nfsrvd_statmtx); } @@ -753,7 +758,7 @@ */ igotlock = 0; NFSLOCKV4ROOTMUTEX(); - if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK) + if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NEEDLOCK) igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); else @@ -766,8 +771,8 @@ * Done when the grace period is over or a client has long * since expired. */ - nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK; - if ((nfsrv_stablefirst.nsf_flags & + NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK; + if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags & (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER) nfsrv_updatestable(p); @@ -777,11 +782,13 @@ * stable storage file and then remove them from the client * list. */ - if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) { - nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT; + if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & + NFSNSF_EXPIREDCLIENT) { + NFSD_VNET(nfsrv_stablefirst).nsf_flags &= + ~NFSNSF_EXPIREDCLIENT; for (i = 0; i < nfsrv_clienthashsize; i++) { - LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, - nclp) { + LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i], + lc_hash, nclp) { if (clp->lc_flags & LCL_EXPIREIT) { if (!LIST_EMPTY(&clp->lc_open) || !LIST_EMPTY(&clp->lc_deleg)) @@ -814,7 +821,7 @@ * If flagged, search for open owners that haven't had any opens * for a long time. */ - if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) { + if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NOOPENS) { nfsrv_throwawayopens(p); } @@ -941,8 +948,10 @@ if (i == 0 && (nd->nd_rp == NULL || nd->nd_rp->rc_refcnt == 0) && (nfsrv_mallocmget_limit() || - nfsrc_tcpsavedreplies > nfsrc_floodlevel)) { - if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) + NFSD_VNET(nfsrc_tcpsavedreplies) > + NFSD_VNET(nfsrc_floodlevel))) { + if (NFSD_VNET(nfsrc_tcpsavedreplies) > + NFSD_VNET(nfsrc_floodlevel)) printf("nfsd server cache flooded, try " "increasing vfs.nfsd.tcphighwater\n"); nd->nd_repstat = NFSERR_RESOURCE; @@ -1033,7 +1042,7 @@ } break; case NFSV4OP_PUTROOTFH: - if (nfs_rootfhset) { + if (NFSD_VNET(nfs_rootfhset)) { if ((nd->nd_flag & ND_LASTOP) == 0) { /* * Pre-parse the next op#. If it is @@ -1054,8 +1063,8 @@ } while (nextop == NFSV4OP_SAVEFH && i < numops - 1); } - nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp, - &nes, NULL, 0, nextop); + nfsd_fhtovp(nd, &NFSD_VNET(nfs_rootfh), + LK_SHARED, &nvp, &nes, NULL, 0, nextop); if (!nd->nd_repstat) { if (vp) vrele(vp); diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c.vnet b/sys/fs/nfsserver/nfs_nfsdstate.c --- a/sys/fs/nfsserver/nfs_nfsdstate.c.vnet +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -35,17 +35,18 @@ #include #include -struct nfsrv_stablefirst nfsrv_stablefirst; int nfsrv_issuedelegs = 0; int nfsrv_dolocallocks = 0; struct nfsv4lock nfsv4rootfs_lock; time_t nfsdev_time = 0; int nfsrv_layouthashsize; volatile int nfsrv_layoutcnt = 0; -extern uint32_t nfs_srvmaxio; -extern int newnfs_numnfsd; -extern struct nfsstatsv1 nfsstatsv1; +NFSD_VNET_DEFINE(struct nfsrv_stablefirst, nfsrv_stablefirst); + +NFSD_VNET_DECLARE(int, nfsrv_numnfsd); + +extern uint32_t nfs_srvmaxio; extern int nfsrv_lease; extern struct timeval nfsboottime; extern u_int32_t newnfs_true, newnfs_false; @@ -64,6 +65,8 @@ extern struct nfslayouthead nfsrv_recalllisthead; extern char *nfsrv_zeropnfsdat; +NFSDSTATSDECLARE(nfsstatsv1); + SYSCTL_DECL(_vfs_nfsd); int nfsrv_statehashsize = NFSSTATEHASHSIZE; SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN, @@ -118,20 +121,22 @@ /* * Hash lists for nfs V4. */ -struct nfsclienthashhead *nfsclienthash; -struct nfslockhashhead *nfslockhash; -struct nfssessionhash *nfssessionhash; +NFSD_VNET_DEFINE(struct nfsclienthashhead *, nfsclienthash); +NFSD_VNET_DEFINE(struct nfslockhashhead *, nfslockhash); +NFSD_VNET_DEFINE(struct nfssessionhash *, nfssessionhash); + struct nfslayouthash *nfslayouthash; volatile int nfsrv_dontlistlen = 0; static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 0; -static time_t nfsrvboottime; static int nfsrv_returnoldstateid = 0, nfsrv_clients = 0; static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER; static int nfsrv_nogsscallback = 0; static volatile int nfsrv_writedelegcnt = 0; static int nfsrv_faildscnt; +NFSD_VNET_DEFINE_STATIC(time_t, nfsrvboottime); + /* local functions */ static void nfsrv_dumpaclient(struct nfsclient *clp, struct nfsd_dumpclients *dumpp); @@ -298,7 +303,7 @@ */ gotit = i = 0; while (i < nfsrv_clienthashsize && !gotit) { - LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { + LIST_FOREACH(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash) { if (new_clp->lc_idlen == clp->lc_idlen && !NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) { gotit = 1; @@ -343,7 +348,7 @@ confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; clientidp->lval[0] = new_clp->lc_clientid.lval[0] = - (u_int32_t)nfsrvboottime; + NFSD_VNET(nfsrvboottime); clientidp->lval[1] = new_clp->lc_clientid.lval[1] = nfsrv_nextclientindex(); new_clp->lc_stateindex = 0; @@ -359,7 +364,7 @@ LIST_INIT(&new_clp->lc_stateid[i]); LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, lc_hash); - nfsstatsv1.srvclients++; + NFSDSTATS()->srvclients++; nfsrv_openpluslock++; nfsrv_clients++; NFSLOCKV4ROOTMUTEX(); @@ -457,7 +462,7 @@ confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; clientidp->lval[0] = new_clp->lc_clientid.lval[0] = - nfsrvboottime; + NFSD_VNET(nfsrvboottime); clientidp->lval[1] = new_clp->lc_clientid.lval[1] = nfsrv_nextclientindex(); new_clp->lc_stateindex = 0; @@ -488,7 +493,7 @@ LIST_INIT(&new_clp->lc_session); LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, lc_hash); - nfsstatsv1.srvclients++; + NFSDSTATS()->srvclients++; nfsrv_openpluslock++; nfsrv_clients++; NFSLOCKV4ROOTMUTEX(); @@ -553,7 +558,7 @@ LIST_INIT(&new_clp->lc_session); LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, lc_hash); - nfsstatsv1.srvclients++; + NFSDSTATS()->srvclients++; nfsrv_openpluslock++; nfsrv_clients++; } @@ -604,7 +609,8 @@ if (clpp) *clpp = NULL; if ((nd == NULL || (nd->nd_flag & ND_NFSV41) == 0 || - opflags != CLOPS_RENEW) && nfsrvboottime != clientid.lval[0]) { + opflags != CLOPS_RENEW) && NFSD_VNET(nfsrvboottime) != + clientid.lval[0]) { error = NFSERR_STALECLIENTID; goto out; } @@ -820,7 +826,7 @@ struct nfsclienthashhead *hp; int error = 0, i, igotlock; - if (nfsrvboottime != clientid.lval[0]) { + if (NFSD_VNET(nfsrvboottime) != clientid.lval[0]) { error = NFSERR_STALECLIENTID; goto out; } @@ -912,7 +918,7 @@ */ gotit = i = 0; while (i < nfsrv_clienthashsize && !gotit) { - LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { + LIST_FOREACH(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash) { if (revokep->nclid_idlen == clp->lc_idlen && !NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) { gotit = 1; @@ -974,8 +980,9 @@ * Rattle through the client lists until done. */ while (i < nfsrv_clienthashsize && cnt < maxcnt) { - clp = LIST_FIRST(&nfsclienthash[i]); - while (clp != LIST_END(&nfsclienthash[i]) && cnt < maxcnt) { + clp = LIST_FIRST(&NFSD_VNET(nfsclienthash)[i]); + while (clp != LIST_END(&NFSD_VNET(nfsclienthash)[i]) && cnt < + maxcnt) { nfsrv_dumpaclient(clp, &dumpp[cnt]); cnt++; clp = LIST_NEXT(clp, lc_hash); @@ -1233,7 +1240,7 @@ * Should be called once per second. */ void -nfsrv_servertimer(void) +nfsrv_servertimer(void *arg __unused) { struct nfsclient *clp, *nclp; struct nfsstate *stp, *nstp; @@ -1251,14 +1258,15 @@ * If server hasn't started yet, just return. */ NFSLOCKSTATE(); - if (nfsrv_stablefirst.nsf_eograce == 0) { + if (NFSD_VNET(nfsrv_stablefirst).nsf_eograce == 0) { NFSUNLOCKSTATE(); return; } - if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) { - if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) && - NFSD_MONOSEC > nfsrv_stablefirst.nsf_eograce) - nfsrv_stablefirst.nsf_flags |= + if (!(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_UPDATEDONE)) { + if (!(NFSD_VNET(nfsrv_stablefirst).nsf_flags & + NFSNSF_GRACEOVER) && + NFSD_MONOSEC > NFSD_VNET(nfsrv_stablefirst).nsf_eograce) + NFSD_VNET(nfsrv_stablefirst).nsf_flags |= (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); NFSUNLOCKSTATE(); return; @@ -1281,8 +1289,8 @@ * For each client... */ for (i = 0; i < nfsrv_clienthashsize; i++) { - clp = LIST_FIRST(&nfsclienthash[i]); - while (clp != LIST_END(&nfsclienthash[i])) { + clp = LIST_FIRST(&NFSD_VNET(nfsclienthash)[i]); + while (clp != LIST_END(&NFSD_VNET(nfsclienthash)[i])) { nclp = LIST_NEXT(clp, lc_hash); if (!(clp->lc_flags & LCL_EXPIREIT)) { if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC @@ -1313,7 +1321,7 @@ * by an nfsd sometime soon. */ clp->lc_flags |= LCL_EXPIREIT; - nfsrv_stablefirst.nsf_flags |= + NFSD_VNET(nfsrv_stablefirst).nsf_flags |= (NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT); } else { /* @@ -1331,7 +1339,7 @@ if (stp->ls_noopens > NFSNOOPEN || (nfsrv_openpluslock * 2) > nfsrv_v4statelimit) - nfsrv_stablefirst.nsf_flags |= + NFSD_VNET(nfsrv_stablefirst).nsf_flags |= NFSNSF_NOOPENS; } else { stp->ls_noopens = 0; @@ -1397,7 +1405,7 @@ free(clp->lc_stateid, M_NFSDCLIENT); free(clp, M_NFSDCLIENT); NFSLOCKSTATE(); - nfsstatsv1.srvclients--; + NFSDSTATS()->srvclients--; nfsrv_openpluslock--; nfsrv_clients--; NFSUNLOCKSTATE(); @@ -1440,7 +1448,7 @@ nfsv4_testlock(&lfp->lf_locallock_lck) == 0) nfsrv_freenfslockfile(lfp); free(stp, M_NFSDSTATE); - nfsstatsv1.srvdelegates--; + NFSDSTATS()->srvdelegates--; nfsrv_openpluslock--; nfsrv_delegatecnt--; } @@ -1466,7 +1474,7 @@ if (stp->ls_op) nfsrvd_derefcache(stp->ls_op); free(stp, M_NFSDSTATE); - nfsstatsv1.srvopenowners--; + NFSDSTATS()->srvopenowners--; nfsrv_openpluslock--; } @@ -1516,7 +1524,7 @@ if (cansleep != 0) NFSUNLOCKSTATE(); free(stp, M_NFSDSTATE); - nfsstatsv1.srvopens--; + NFSDSTATS()->srvopens--; nfsrv_openpluslock--; return (ret); } @@ -1535,7 +1543,7 @@ if (stp->ls_op) nfsrvd_derefcache(stp->ls_op); free(stp, M_NFSDSTATE); - nfsstatsv1.srvlockowners--; + NFSDSTATS()->srvlockowners--; nfsrv_openpluslock--; } @@ -1611,7 +1619,7 @@ if (lop->lo_lckfile.le_prev != NULL) { LIST_REMOVE(lop, lo_lckfile); - nfsstatsv1.srvlocks--; + NFSDSTATS()->srvlocks--; nfsrv_openpluslock--; } LIST_REMOVE(lop, lo_lckowner); @@ -2388,7 +2396,7 @@ LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list); *new_lopp = NULL; *new_stpp = NULL; - nfsstatsv1.srvlockowners++; + NFSDSTATS()->srvlockowners++; nfsrv_openpluslock++; } if (filestruct_locked != 0) { @@ -3040,12 +3048,12 @@ LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); *new_stpp = NULL; - nfsstatsv1.srvopenowners++; + NFSDSTATS()->srvopenowners++; nfsrv_openpluslock++; } openstp = new_open; new_open = NULL; - nfsstatsv1.srvopens++; + NFSDSTATS()->srvopens++; nfsrv_openpluslock++; break; } @@ -3106,7 +3114,7 @@ NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) || !NFSVNO_DELEGOK(vp)) *rflagsp |= NFSV4OPEN_RECALL; - nfsstatsv1.srvdelegates++; + NFSDSTATS()->srvdelegates++; nfsrv_openpluslock++; nfsrv_delegatecnt++; @@ -3146,12 +3154,12 @@ LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); *new_stpp = NULL; - nfsstatsv1.srvopenowners++; + NFSDSTATS()->srvopenowners++; nfsrv_openpluslock++; } openstp = new_open; new_open = NULL; - nfsstatsv1.srvopens++; + NFSDSTATS()->srvopens++; nfsrv_openpluslock++; } else { error = NFSERR_RECLAIMCONFLICT; @@ -3223,7 +3231,7 @@ new_deleg->ls_stateid), new_deleg, ls_hash); LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); new_deleg = NULL; - nfsstatsv1.srvdelegates++; + NFSDSTATS()->srvdelegates++; nfsrv_openpluslock++; nfsrv_delegatecnt++; } @@ -3245,7 +3253,7 @@ new_open, ls_hash); openstp = new_open; new_open = NULL; - nfsstatsv1.srvopens++; + NFSDSTATS()->srvopens++; nfsrv_openpluslock++; /* @@ -3293,7 +3301,7 @@ new_deleg->ls_stateid), new_deleg, ls_hash); LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); new_deleg = NULL; - nfsstatsv1.srvdelegates++; + NFSDSTATS()->srvdelegates++; nfsrv_openpluslock++; nfsrv_delegatecnt++; } @@ -3374,7 +3382,7 @@ LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); new_deleg = NULL; - nfsstatsv1.srvdelegates++; + NFSDSTATS()->srvdelegates++; nfsrv_openpluslock++; nfsrv_delegatecnt++; } @@ -3402,9 +3410,9 @@ openstp = new_open; new_open = NULL; *new_stpp = NULL; - nfsstatsv1.srvopens++; + NFSDSTATS()->srvopens++; nfsrv_openpluslock++; - nfsstatsv1.srvopenowners++; + NFSDSTATS()->srvopenowners++; nfsrv_openpluslock++; } if (!error) { @@ -3880,7 +3888,7 @@ else LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner); if (stp != NULL) { - nfsstatsv1.srvlocks++; + NFSDSTATS()->srvlocks++; nfsrv_openpluslock++; } } @@ -4357,11 +4365,11 @@ */ if (flags & (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { - if (clientid.lval[0] != nfsrvboottime) { + if (clientid.lval[0] != NFSD_VNET(nfsrvboottime)) { ret = NFSERR_STALECLIENTID; goto out; } - } else if (stateidp->other[0] != nfsrvboottime && + } else if (stateidp->other[0] != NFSD_VNET(nfsrvboottime) && specialid == 0) { ret = NFSERR_STALESTATEID; goto out; @@ -4394,25 +4402,26 @@ int error = 0, notreclaimed; struct nfsrv_stable *sp; - if ((nfsrv_stablefirst.nsf_flags & (NFSNSF_UPDATEDONE | + if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags & (NFSNSF_UPDATEDONE | NFSNSF_GRACEOVER)) == 0) { /* * First, check to see if all of the clients have done a * ReclaimComplete. If so, grace can end now. */ notreclaimed = 0; - LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { + LIST_FOREACH(sp, &NFSD_VNET(nfsrv_stablefirst).nsf_head, + nst_list) { if ((sp->nst_flag & NFSNST_RECLAIMED) == 0) { notreclaimed = 1; break; } } if (notreclaimed == 0) - nfsrv_stablefirst.nsf_flags |= (NFSNSF_GRACEOVER | - NFSNSF_NEEDLOCK); + NFSD_VNET(nfsrv_stablefirst).nsf_flags |= + (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); } - if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) { + if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_GRACEOVER) != 0) { if (flags & NFSLCK_RECLAIM) { error = NFSERR_NOGRACE; goto out; @@ -4434,9 +4443,9 @@ * extend grace a bit. */ if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > - nfsrv_stablefirst.nsf_eograce) - nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC + - NFSRV_LEASEDELTA; + NFSD_VNET(nfsrv_stablefirst).nsf_eograce) + NFSD_VNET(nfsrv_stablefirst).nsf_eograce = + NFSD_MONOSEC + NFSRV_LEASEDELTA; } out: @@ -4870,7 +4879,7 @@ void nfsrv_setupstable(NFSPROC_T *p) { - struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; + struct nfsrv_stablefirst *sf = &NFSD_VNET(nfsrv_stablefirst); struct nfsrv_stable *sp, *nsp; struct nfst_rec *tsp; int error, i, tryagain; @@ -4886,7 +4895,7 @@ /* * Set Grace over just until the file reads successfully. */ - nfsrvboottime = time_second; + NFSD_VNET(nfsrvboottime) = time_second; LIST_INIT(&sf->nsf_head); sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA; @@ -4903,7 +4912,7 @@ * Now, read in the boottimes. */ sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) * - sizeof (time_t), M_TEMP, M_WAITOK); + sizeof(time_t), M_TEMP, M_WAITOK); off = sizeof (struct nfsf_rec); error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off, @@ -4921,8 +4930,8 @@ do { tryagain = 0; for (i = 0; i < sf->nsf_numboots; i++) { - if (nfsrvboottime == sf->nsf_bootvals[i]) { - nfsrvboottime++; + if (NFSD_VNET(nfsrvboottime) == sf->nsf_bootvals[i]) { + NFSD_VNET(nfsrvboottime)++; tryagain = 1; break; } @@ -5005,7 +5014,7 @@ void nfsrv_updatestable(NFSPROC_T *p) { - struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; + struct nfsrv_stablefirst *sf = &NFSD_VNET(nfsrv_stablefirst); struct nfsrv_stable *sp, *nsp; int i; struct nfsvattr nva; @@ -5031,10 +5040,10 @@ sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i]; } else { sf->nsf_numboots = 1; - sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t), + sf->nsf_bootvals = (time_t *)malloc(sizeof(time_t), M_TEMP, M_WAITOK); } - sf->nsf_bootvals[0] = nfsrvboottime; + sf->nsf_bootvals[0] = NFSD_VNET(nfsrvboottime); sf->nsf_lease = nfsrv_lease; NFSVNO_ATTRINIT(&nva); NFSVNO_SETATTRVAL(&nva, size, 0); @@ -5088,7 +5097,7 @@ void nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p) { - struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; + struct nfsrv_stablefirst *sf = &NFSD_VNET(nfsrv_stablefirst); struct nfst_rec *sp; int error; @@ -5121,12 +5130,12 @@ /* * First find the client structure. */ - LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { + LIST_FOREACH(sp, &NFSD_VNET(nfsrv_stablefirst).nsf_head, nst_list) { if (sp->nst_len == clp->lc_idlen && !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) break; } - if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) + if (sp == LIST_END(&NFSD_VNET(nfsrv_stablefirst).nsf_head)) return; /* @@ -5148,12 +5157,12 @@ /* * First find the client structure. */ - LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { + LIST_FOREACH(sp, &NFSD_VNET(nfsrv_stablefirst).nsf_head, nst_list) { if (sp->nst_len == clp->lc_idlen && !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) break; } - if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) + if (sp == LIST_END(&NFSD_VNET(nfsrv_stablefirst).nsf_head)) return; /* @@ -5174,7 +5183,7 @@ /* * First, find the entry for the client. */ - LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { + LIST_FOREACH(sp, &NFSD_VNET(nfsrv_stablefirst).nsf_head, nst_list) { if (sp->nst_len == clp->lc_idlen && !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) break; @@ -5184,9 +5193,9 @@ * If not in the list, state was revoked or no state was issued * since the previous reboot, a reclaim is denied. */ - if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) || + if (sp == LIST_END(&NFSD_VNET(nfsrv_stablefirst).nsf_head) || (sp->nst_flag & NFSNST_REVOKE) || - !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK)) + !(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_OK)) return (1); return (0); } @@ -5214,7 +5223,7 @@ * If lease hasn't expired, we can't fix it. */ if (clp->lc_expiry >= NFSD_MONOSEC || - !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) + !(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_UPDATEDONE)) return (0); if (*haslockp == 0) { NFSUNLOCKSTATE(); @@ -5613,7 +5622,7 @@ * First, check to see if the server is currently running and it has * been called for a regular file when issuing delegations. */ - if (newnfs_numnfsd == 0 || vp->v_type != VREG || + if (NFSD_VNET(nfsrv_numnfsd) == 0 || vp->v_type != VREG || nfsrv_issuedelegs == 0) return; @@ -5847,12 +5856,13 @@ int i; NFSLOCKSTATE(); - nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS; + NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NOOPENS; /* * For each client... */ for (i = 0; i < nfsrv_clienthashsize; i++) { - LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { + LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash, + nclp) { LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { if (LIST_EMPTY(&stp->ls_open) && (stp->ls_noopens > NFSNOOPEN || @@ -5867,8 +5877,7 @@ /* * This function checks to see if the credentials are the same. - * The check for same credentials is needed for state management operations - * for NFSv4.0 where 1 is returned if not same, 0 is returned otherwise. + * Returns 1 for not same, 0 otherwise. */ static int nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp) @@ -5913,7 +5922,7 @@ nfsrv_leaseexpiry(void) { - if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC) + if (NFSD_VNET(nfsrv_stablefirst).nsf_eograce > NFSD_MONOSEC) return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA)); return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA); } @@ -6234,7 +6243,8 @@ * For each client, clean out the state and then free the structure. */ for (i = 0; i < nfsrv_clienthashsize; i++) { - LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { + LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash, + nclp) { nfsrv_cleanclient(clp, p); nfsrv_freedeleglist(&clp->lc_deleg); nfsrv_freedeleglist(&clp->lc_olddeleg); @@ -6247,7 +6257,8 @@ * Also, free up any remaining lock file structures. */ for (i = 0; i < nfsrv_lockhashsize; i++) { - LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) { + LIST_FOREACH_SAFE(lfp, &NFSD_VNET(nfslockhash)[i], lf_hash, + nlfp) { printf("nfsd unload: fnd a lock file struct\n"); nfsrv_freenfslockfile(lfp); } @@ -6365,7 +6376,8 @@ sep = nfsrv_findsession(nd->nd_sessionid); if (sep == NULL) { NFSUNLOCKSESSION(shp); - if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) { + if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags & + NFSNSF_GRACEOVER) != 0) { buf = malloc(INET6_ADDRSTRLEN, M_TEMP, M_WAITOK); switch (nd->nd_nam->sa_family) { #ifdef INET @@ -6727,7 +6739,7 @@ int i; for (i = 0; i < nfsrv_clienthashsize; i++) { - LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { + LIST_FOREACH(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash) { LIST_FOREACH(sep, &clp->lc_session, sess_list) { xprt = sep->sess_cbsess.nfsess_xprt; sep->sess_cbsess.nfsess_xprt = NULL; @@ -7443,7 +7455,7 @@ /* Insert the new layout in the lists. */ *lypp = NULL; atomic_add_int(&nfsrv_layoutcnt, 1); - nfsstatsv1.srvlayouts++; + NFSDSTATS()->srvlayouts++; NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen); *layoutlenp = lyp->lay_layoutlen; TAILQ_INSERT_HEAD(&lhyp->list, lyp, lay_list); @@ -7536,7 +7548,7 @@ NFSD_DEBUG(4, "Freelayout=%p\n", lyp); atomic_add_int(&nfsrv_layoutcnt, -1); - nfsstatsv1.srvlayouts--; + NFSDSTATS()->srvlayouts--; TAILQ_REMOVE(lhp, lyp, lay_list); free(lyp, M_NFSDSTATE); } @@ -7686,6 +7698,10 @@ NFSD_DEBUG(4, "setdssrv path=%s\n", dspathp); *dsp = NULL; + if (jailed(p->td_ucred)) { + printf("A pNFS nfsd cannot run in a jail\n"); + return (EPERM); + } NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE, dspathp); error = namei(&nd); diff --git a/sys/fs/nfsserver/nfs_nfsdsubs.c.vnet b/sys/fs/nfsserver/nfs_nfsdsubs.c --- a/sys/fs/nfsserver/nfs_nfsdsubs.c.vnet +++ b/sys/fs/nfsserver/nfs_nfsdsubs.c @@ -44,18 +44,24 @@ #include extern u_int32_t newnfs_true, newnfs_false; -extern int nfs_rootfhset; extern int nfs_pubfhset; -extern struct nfsclienthashhead *nfsclienthash; extern int nfsrv_clienthashsize; -extern struct nfslockhashhead *nfslockhash; extern int nfsrv_lockhashsize; -extern struct nfssessionhash *nfssessionhash; extern int nfsrv_sessionhashsize; extern int nfsrv_useacl; extern uid_t nfsrv_defaultuid; extern gid_t nfsrv_defaultgid; +NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash); +NFSD_VNET_DECLARE(struct nfslockhashhead *, nfslockhash); +NFSD_VNET_DECLARE(struct nfssessionhash *, nfssessionhash); +NFSD_VNET_DECLARE(int, nfs_rootfhset); +NFSD_VNET_DECLARE(uid_t, nfsrv_defaultuid); +NFSD_VNET_DECLARE(gid_t, nfsrv_defaultgid); + +NFSD_VNET_DEFINE(struct nfsdontlisthead, nfsrv_dontlisthead); + + char nfs_v2pubfh[NFSX_V2FH]; struct nfsdontlisthead nfsrv_dontlisthead; struct nfslayouthead nfsrv_recalllisthead; @@ -1607,10 +1613,12 @@ */ if (NFSVNO_NOTSETUID(nvap) && NFSVNO_NOTSETGID(nvap)) goto out; - if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid == nfsrv_defaultuid && - enable_nobodycheck == 1) - || (NFSVNO_ISSETGID(nvap) && nvap->na_gid == nfsrv_defaultgid && - enable_nogroupcheck == 1)) { + if ((NFSVNO_ISSETUID(nvap) && + nvap->na_uid == NFSD_VNET(nfsrv_defaultuid) && + enable_nobodycheck == 1) || + (NFSVNO_ISSETGID(nvap) && + nvap->na_gid == NFSD_VNET(nfsrv_defaultgid) && + enable_nogroupcheck == 1)) { error = NFSERR_BADOWNER; goto out; } @@ -2080,29 +2088,26 @@ nfsd_init(void) { int i; - static int inited = 0; - if (inited) - return; - inited = 1; /* * Initialize client queues. Don't free/reinitialize * them when nfsds are restarted. */ - nfsclienthash = malloc(sizeof(struct nfsclienthashhead) * + NFSD_VNET(nfsclienthash) = malloc(sizeof(struct nfsclienthashhead) * nfsrv_clienthashsize, M_NFSDCLIENT, M_WAITOK | M_ZERO); for (i = 0; i < nfsrv_clienthashsize; i++) - LIST_INIT(&nfsclienthash[i]); - nfslockhash = malloc(sizeof(struct nfslockhashhead) * + LIST_INIT(&NFSD_VNET(nfsclienthash)[i]); + NFSD_VNET(nfslockhash) = malloc(sizeof(struct nfslockhashhead) * nfsrv_lockhashsize, M_NFSDLOCKFILE, M_WAITOK | M_ZERO); for (i = 0; i < nfsrv_lockhashsize; i++) - LIST_INIT(&nfslockhash[i]); - nfssessionhash = malloc(sizeof(struct nfssessionhash) * + LIST_INIT(&NFSD_VNET(nfslockhash)[i]); + NFSD_VNET(nfssessionhash) = malloc(sizeof(struct nfssessionhash) * nfsrv_sessionhashsize, M_NFSDSESSION, M_WAITOK | M_ZERO); for (i = 0; i < nfsrv_sessionhashsize; i++) { - mtx_init(&nfssessionhash[i].mtx, "nfssm", NULL, MTX_DEF); - LIST_INIT(&nfssessionhash[i].list); + mtx_init(&NFSD_VNET(nfssessionhash)[i].mtx, "nfssm", NULL, + MTX_DEF); + LIST_INIT(&NFSD_VNET(nfssessionhash)[i].list); } LIST_INIT(&nfsrv_dontlisthead); TAILQ_INIT(&nfsrv_recalllisthead); @@ -2119,12 +2124,15 @@ nfsd_checkrootexp(struct nfsrv_descript *nd) { - if (nfs_rootfhset == 0) + if (NFSD_VNET(nfs_rootfhset) == 0) return (NFSERR_AUTHERR | AUTH_FAILED); /* * For NFSv4.1/4.2, if the client specifies SP4_NONE, then these * operations are allowed regardless of the value of the "sec=XXX" * field in the V4: exports line. + * For SP4_MACH_CRED, the check for Kerberos with Integrity or + * Privacy will be done later in the functions, once a ClientID + * is referenced. * As such, these Kerberos checks only apply to NFSv4.0 mounts. */ if ((nd->nd_flag & ND_NFSV41) != 0) diff --git a/sys/kgssapi/gss_delete_sec_context.c.vnetkgssapi b/sys/kgssapi/gss_delete_sec_context.c --- a/sys/kgssapi/gss_delete_sec_context.c.vnetkgssapi +++ b/sys/kgssapi/gss_delete_sec_context.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -54,8 +55,12 @@ *minor_status = 0; - if (!kgss_gssd_handle) + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); + if (!KGSS_VNET(kgss_gssd_handle)) { + KGSS_CURVNET_RESTORE(); return (GSS_S_FAILURE); + } + KGSS_CURVNET_RESTORE(); if (*context_handle) { ctx = *context_handle; diff --git a/sys/kgssapi/gss_impl.c.vnetkgssapi b/sys/kgssapi/gss_impl.c --- a/sys/kgssapi/gss_impl.c.vnetkgssapi +++ b/sys/kgssapi/gss_impl.c @@ -31,13 +31,16 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include #include #include #include +#include #include +#include #include #include #include @@ -62,9 +65,10 @@ }; struct kgss_mech_list kgss_mechs; -CLIENT *kgss_gssd_handle; struct mtx kgss_gssd_lock; +KGSS_VNET_DEFINE(CLIENT *, kgss_gssd_handle) = NULL; + static int kgss_load(void) { @@ -134,10 +138,12 @@ } else cl = NULL; + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); mtx_lock(&kgss_gssd_lock); - oldcl = kgss_gssd_handle; - kgss_gssd_handle = cl; + oldcl = KGSS_VNET(kgss_gssd_handle); + KGSS_VNET(kgss_gssd_handle) = cl; mtx_unlock(&kgss_gssd_lock); + KGSS_CURVNET_RESTORE(); if (oldcl != NULL) { CLNT_CLOSE(oldcl); @@ -249,12 +255,16 @@ enum clnt_stat stat; OM_uint32 maj_stat; - if (!kgss_gssd_handle) + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); + if (!KGSS_VNET(kgss_gssd_handle)) { + KGSS_CURVNET_RESTORE(); return (GSS_S_FAILURE); + } args.ctx = ctx->handle; bzero(&res, sizeof(res)); - stat = gssd_export_sec_context_1(&args, &res, kgss_gssd_handle); + stat = gssd_export_sec_context_1(&args, &res, KGSS_VNET(kgss_gssd_handle)); + KGSS_CURVNET_RESTORE(); if (stat != RPC_SUCCESS) { return (GSS_S_FAILURE); } @@ -288,11 +298,13 @@ { CLIENT *cl; + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); mtx_lock(&kgss_gssd_lock); - cl = kgss_gssd_handle; + cl = KGSS_VNET(kgss_gssd_handle); if (cl != NULL) CLNT_ACQUIRE(cl); mtx_unlock(&kgss_gssd_lock); + KGSS_CURVNET_RESTORE(); return (cl); } @@ -303,6 +315,9 @@ kgssapi_modevent(module_t mod, int type, void *data) { int error = 0; + osd_method_t methods[PR_MAXMETHOD] = { + [PR_METHOD_REMOVE] = rpcgss_prison_cleanup, + }; switch (type) { case MOD_LOAD: @@ -331,6 +346,9 @@ rpc_gss_svc_max_data_length; mtx_init(&kgss_gssd_lock, "kgss_gssd_lock", NULL, MTX_DEF); error = kgss_load(); + /* XXX-BZ OSD to VNET? */ + if (error == 0) + osd_jail_register(NULL, methods); break; case MOD_UNLOAD: kgss_unload(); diff --git a/sys/kgssapi/gss_release_cred.c.vnetkgssapi b/sys/kgssapi/gss_release_cred.c --- a/sys/kgssapi/gss_release_cred.c.vnetkgssapi +++ b/sys/kgssapi/gss_release_cred.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -52,8 +53,12 @@ *minor_status = 0; - if (!kgss_gssd_handle) + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); + if (!KGSS_VNET(kgss_gssd_handle)) { + KGSS_CURVNET_RESTORE(); return (GSS_S_FAILURE); + } + KGSS_CURVNET_RESTORE(); if (*cred_handle) { args.cred = (*cred_handle)->handle; diff --git a/sys/kgssapi/gss_release_name.c.vnetkgssapi b/sys/kgssapi/gss_release_name.c --- a/sys/kgssapi/gss_release_name.c.vnetkgssapi +++ b/sys/kgssapi/gss_release_name.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -53,8 +54,12 @@ *minor_status = 0; - if (!kgss_gssd_handle) + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); + if (!KGSS_VNET(kgss_gssd_handle)) { + KGSS_CURVNET_RESTORE(); return (GSS_S_FAILURE); + } + KGSS_CURVNET_RESTORE(); if (*input_name) { name = *input_name; diff --git a/sys/kgssapi/gssapi_impl.h.vnetkgssapi b/sys/kgssapi/gssapi_impl.h --- a/sys/kgssapi/gssapi_impl.h.vnetkgssapi +++ b/sys/kgssapi/gssapi_impl.h @@ -54,9 +54,25 @@ }; LIST_HEAD(kgss_mech_list, kgss_mech); -extern CLIENT *kgss_gssd_handle; +/* Macros for VIMAGE. */ +/* Just define the KGSS_VNETxxx() macros as VNETxxx() macros. */ +#define KGSS_VNET_DEFINE(t, n) VNET_DEFINE(t, n) +#define KGSS_VNET_DEFINE_STATIC(t, n) VNET_DEFINE_STATIC(t, n) +#define KGSS_VNET_DECLARE(t, n) VNET_DECLARE(t, n) +#define KGSS_VNET(n) VNET(n) + +#define KGSS_CURVNET_SET(n) CURVNET_SET(n) +#define KGSS_CURVNET_SET_QUIET(n) CURVNET_SET_QUIET(n) +#define KGSS_CURVNET_RESTORE() CURVNET_RESTORE() +#define KGSS_TD_TO_VNET(n) TD_TO_VNET(n) + +/* Osd cleanup function. */ +int rpcgss_prison_cleanup(void *obj, void *data __unused); + extern struct mtx kgss_gssd_lock; extern struct kgss_mech_list kgss_mechs; + +KGSS_VNET_DECLARE(CLIENT *, kgss_gssd_handle); CLIENT *kgss_gssd_client(void); int kgss_oid_equal(const gss_OID oid1, const gss_OID oid2); diff --git a/sys/rpc/rpc_generic.c.vnetrpctls b/sys/rpc/rpc_generic.c --- a/sys/rpc/rpc_generic.c.vnetrpctls +++ b/sys/rpc/rpc_generic.c @@ -45,10 +45,12 @@ #include "opt_inet6.h" #include +#include #include #include #include #include +#include #include #include #include @@ -965,10 +967,16 @@ krpc_modevent(module_t mod, int type, void *data) { int error = 0; + osd_method_t methods[PR_MAXMETHOD] = { + [PR_METHOD_REMOVE] = rpctls_prison_cleanup, + }; switch (type) { case MOD_LOAD: error = rpctls_init(); + /* XXX-BZ OSD to VNET? */ + if (error == 0) + osd_jail_register(NULL, methods); break; case MOD_UNLOAD: /* diff --git a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c.vnetkgssapi b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c --- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c.vnetkgssapi +++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c @@ -102,8 +102,9 @@ SLIST_ENTRY(svc_rpc_gss_callback) cb_link; rpc_gss_callback_t cb_callback; }; -static SLIST_HEAD(svc_rpc_gss_callback_list, svc_rpc_gss_callback) - svc_rpc_gss_callbacks = SLIST_HEAD_INITIALIZER(svc_rpc_gss_callbacks); +SLIST_HEAD(svc_rpc_gss_callback_list, svc_rpc_gss_callback); +KGSS_VNET_DEFINE_STATIC(struct svc_rpc_gss_callback_list, + svc_rpc_gss_callbacks) = SLIST_HEAD_INITIALIZER(svc_rpc_gss_callbacks); struct svc_rpc_gss_svc_name { SLIST_ENTRY(svc_rpc_gss_svc_name) sn_link; @@ -114,8 +115,9 @@ u_int sn_program; u_int sn_version; }; -static SLIST_HEAD(svc_rpc_gss_svc_name_list, svc_rpc_gss_svc_name) - svc_rpc_gss_svc_names = SLIST_HEAD_INITIALIZER(svc_rpc_gss_svc_names); +SLIST_HEAD(svc_rpc_gss_svc_name_list, svc_rpc_gss_svc_name); +KGSS_VNET_DEFINE_STATIC(struct svc_rpc_gss_svc_name_list, + svc_rpc_gss_svc_names) = SLIST_HEAD_INITIALIZER(svc_rpc_gss_svc_names); enum svc_rpc_gss_client_state { CLIENT_NEW, /* still authenticating */ @@ -197,24 +199,43 @@ &svc_rpc_gss_client_count, 0, "Number of rpc-gss clients"); -struct svc_rpc_gss_client_list *svc_rpc_gss_client_hash; -struct svc_rpc_gss_client_list svc_rpc_gss_clients; -static uint32_t svc_rpc_gss_next_clientid = 1; +KGSS_VNET_DEFINE(struct svc_rpc_gss_client_list *, svc_rpc_gss_client_hash); +KGSS_VNET_DEFINE(struct svc_rpc_gss_client_list, svc_rpc_gss_clients); +KGSS_VNET_DEFINE_STATIC(uint32_t, svc_rpc_gss_next_clientid) = 1; static void svc_rpc_gss_init(void *arg) { int i; - svc_rpc_gss_client_hash = mem_alloc(sizeof(struct svc_rpc_gss_client_list) * svc_rpc_gss_client_hash_size); + KGSS_VNET(svc_rpc_gss_client_hash) = mem_alloc( + sizeof(struct svc_rpc_gss_client_list) * + svc_rpc_gss_client_hash_size); for (i = 0; i < svc_rpc_gss_client_hash_size; i++) - TAILQ_INIT(&svc_rpc_gss_client_hash[i]); - TAILQ_INIT(&svc_rpc_gss_clients); - svc_auth_reg(RPCSEC_GSS, svc_rpc_gss, rpc_gss_svc_getcred); - sx_init(&svc_rpc_gss_lock, "gsslock"); + TAILQ_INIT(&KGSS_VNET(svc_rpc_gss_client_hash)[i]); + TAILQ_INIT(&KGSS_VNET(svc_rpc_gss_clients)); + if (IS_DEFAULT_VNET(curvnet)) { + svc_auth_reg(RPCSEC_GSS, svc_rpc_gss, rpc_gss_svc_getcred); + sx_init(&svc_rpc_gss_lock, "gsslock"); + } } -SYSINIT(svc_rpc_gss_init, SI_SUB_KMEM, SI_ORDER_ANY, svc_rpc_gss_init, NULL); +VNET_SYSINIT(svc_rpc_gss_init, SI_SUB_VNET_DONE, SI_ORDER_ANY, + svc_rpc_gss_init, NULL); +/* Osd entry for prison cleanup. */ +int +rpcgss_prison_cleanup(void *obj, void *data __unused) +{ + struct prison *pr = obj; + + if ((pr->pr_flags & PR_VNET) == 0) + return (0); + KGSS_CURVNET_SET(pr->pr_vnet); + free(KGSS_VNET(svc_rpc_gss_client_hash), M_RPC); + KGSS_CURVNET_RESTORE(); + return (0); +} + bool_t rpc_gss_set_callback(rpc_gss_callback_t *cb) { @@ -227,7 +248,7 @@ } scb->cb_callback = *cb; sx_xlock(&svc_rpc_gss_lock); - SLIST_INSERT_HEAD(&svc_rpc_gss_callbacks, scb, cb_link); + SLIST_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_callbacks), scb, cb_link); sx_xunlock(&svc_rpc_gss_lock); return (TRUE); @@ -239,11 +260,11 @@ struct svc_rpc_gss_callback *scb; sx_xlock(&svc_rpc_gss_lock); - SLIST_FOREACH(scb, &svc_rpc_gss_callbacks, cb_link) { + SLIST_FOREACH(scb, &KGSS_VNET(svc_rpc_gss_callbacks), cb_link) { if (scb->cb_callback.program == cb->program && scb->cb_callback.version == cb->version && scb->cb_callback.callback == cb->callback) { - SLIST_REMOVE(&svc_rpc_gss_callbacks, scb, + SLIST_REMOVE(&KGSS_VNET(svc_rpc_gss_callbacks), scb, svc_rpc_gss_callback, cb_link); sx_xunlock(&svc_rpc_gss_lock); mem_free(scb, sizeof(*scb)); @@ -314,7 +335,7 @@ } sx_xlock(&svc_rpc_gss_lock); - SLIST_INSERT_HEAD(&svc_rpc_gss_svc_names, sname, sn_link); + SLIST_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_svc_names), sname, sn_link); sx_xunlock(&svc_rpc_gss_lock); return (TRUE); @@ -327,10 +348,10 @@ struct svc_rpc_gss_svc_name *sname; sx_xlock(&svc_rpc_gss_lock); - SLIST_FOREACH(sname, &svc_rpc_gss_svc_names, sn_link) { + SLIST_FOREACH(sname, &KGSS_VNET(svc_rpc_gss_svc_names), sn_link) { if (sname->sn_program == program && sname->sn_version == version) { - SLIST_REMOVE(&svc_rpc_gss_svc_names, sname, + SLIST_REMOVE(&KGSS_VNET(svc_rpc_gss_svc_names), sname, svc_rpc_gss_svc_name, sn_link); sx_xunlock(&svc_rpc_gss_lock); gss_release_cred(&min_stat, &sname->sn_cred); @@ -478,11 +499,9 @@ cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid; cr->cr_rgid = cr->cr_svgid = uc->gid; crsetgroups(cr, uc->gidlen, uc->gidlist); -#ifdef VNET_NFSD if (jailed(curthread->td_ucred)) cr->cr_prison = curthread->td_ucred->cr_prison; else -#endif cr->cr_prison = &prison0; prison_hold(cr->cr_prison); *crp = crhold(cr); @@ -548,7 +567,8 @@ if (id->ci_hostid != hostid || id->ci_boottime != boottime.tv_sec) return (NULL); - list = &svc_rpc_gss_client_hash[id->ci_id % svc_rpc_gss_client_hash_size]; + list = &KGSS_VNET(svc_rpc_gss_client_hash) + [id->ci_id % svc_rpc_gss_client_hash_size]; sx_xlock(&svc_rpc_gss_lock); TAILQ_FOREACH(client, list, cl_link) { if (client->cl_id.ci_id == id->ci_id) { @@ -556,9 +576,10 @@ * Move this client to the front of the LRU * list. */ - TAILQ_REMOVE(&svc_rpc_gss_clients, client, cl_alllink); - TAILQ_INSERT_HEAD(&svc_rpc_gss_clients, client, + TAILQ_REMOVE(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink); + TAILQ_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_clients), + client, cl_alllink); refcount_acquire(&client->cl_refs); break; } @@ -591,7 +612,7 @@ client->cl_id.ci_hostid = hostid; getboottime(&boottime); client->cl_id.ci_boottime = boottime.tv_sec; - client->cl_id.ci_id = svc_rpc_gss_next_clientid++; + client->cl_id.ci_id = KGSS_VNET(svc_rpc_gss_next_clientid)++; /* * Start the client off with a short expiration time. We will @@ -601,10 +622,11 @@ client->cl_locked = FALSE; client->cl_expiration = time_uptime + 5*60; - list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; + list = &KGSS_VNET(svc_rpc_gss_client_hash) + [client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; sx_xlock(&svc_rpc_gss_lock); TAILQ_INSERT_HEAD(list, client, cl_link); - TAILQ_INSERT_HEAD(&svc_rpc_gss_clients, client, cl_alllink); + TAILQ_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink); svc_rpc_gss_client_count++; sx_xunlock(&svc_rpc_gss_lock); return (client); @@ -658,9 +680,10 @@ struct svc_rpc_gss_client_list *list; sx_assert(&svc_rpc_gss_lock, SX_XLOCKED); - list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; + list = &KGSS_VNET(svc_rpc_gss_client_hash) + [client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; TAILQ_REMOVE(list, client, cl_link); - TAILQ_REMOVE(&svc_rpc_gss_clients, client, cl_alllink); + TAILQ_REMOVE(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink); svc_rpc_gss_client_count--; } @@ -673,7 +696,8 @@ struct svc_rpc_gss_client_list *list; struct svc_rpc_gss_client *tclient; - list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; + list = &KGSS_VNET(svc_rpc_gss_client_hash) + [client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; sx_xlock(&svc_rpc_gss_lock); TAILQ_FOREACH(tclient, list, cl_link) { /* @@ -704,17 +728,18 @@ * svc_rpc_gss_clients in LRU order. */ sx_xlock(&svc_rpc_gss_lock); - client = TAILQ_LAST(&svc_rpc_gss_clients, svc_rpc_gss_client_list); + client = TAILQ_LAST(&KGSS_VNET(svc_rpc_gss_clients), + svc_rpc_gss_client_list); while (svc_rpc_gss_client_count > svc_rpc_gss_client_max && client != NULL) { svc_rpc_gss_forget_client_locked(client); sx_xunlock(&svc_rpc_gss_lock); svc_rpc_gss_release_client(client); sx_xlock(&svc_rpc_gss_lock); - client = TAILQ_LAST(&svc_rpc_gss_clients, + client = TAILQ_LAST(&KGSS_VNET(svc_rpc_gss_clients), svc_rpc_gss_client_list); } again: - TAILQ_FOREACH(client, &svc_rpc_gss_clients, cl_alllink) { + TAILQ_FOREACH(client, &KGSS_VNET(svc_rpc_gss_clients), cl_alllink) { if (client->cl_state == CLIENT_STALE || now > client->cl_expiration) { svc_rpc_gss_forget_client_locked(client); @@ -883,7 +908,8 @@ */ sx_xlock(&svc_rpc_gss_lock); if (!client->cl_sname) { - SLIST_FOREACH(sname, &svc_rpc_gss_svc_names, sn_link) { + SLIST_FOREACH(sname, &KGSS_VNET(svc_rpc_gss_svc_names), + sn_link) { if (sname->sn_program == rqst->rq_prog && sname->sn_version == rqst->rq_vers) { retry: @@ -1137,7 +1163,7 @@ * See if we have a callback for this guy. */ result = TRUE; - SLIST_FOREACH(scb, &svc_rpc_gss_callbacks, cb_link) { + SLIST_FOREACH(scb, &KGSS_VNET(svc_rpc_gss_callbacks), cb_link) { if (scb->cb_callback.program == rqst->rq_prog && scb->cb_callback.version == rqst->rq_vers) { /* @@ -1273,6 +1299,7 @@ int call_stat; enum auth_stat result; + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); rpc_gss_log_debug("in svc_rpc_gss()"); /* Garbage collect old clients. */ @@ -1282,8 +1309,10 @@ rqst->rq_verf = _null_auth; /* Deserialize client credentials. */ - if (rqst->rq_cred.oa_length <= 0) + if (rqst->rq_cred.oa_length <= 0) { + KGSS_CURVNET_RESTORE(); return (AUTH_BADCRED); + } memset(&gc, 0, sizeof(gc)); @@ -1292,6 +1321,7 @@ if (!xdr_rpc_gss_cred(&xdrs, &gc)) { XDR_DESTROY(&xdrs); + KGSS_CURVNET_RESTORE(); return (AUTH_BADCRED); } XDR_DESTROY(&xdrs); @@ -1527,6 +1557,7 @@ svc_rpc_gss_release_client(client); xdr_free((xdrproc_t) xdr_rpc_gss_cred, (char *) &gc); + KGSS_CURVNET_RESTORE(); return (result); } diff --git a/sys/rpc/rpcsec_tls.h.vnetrpctls b/sys/rpc/rpcsec_tls.h --- a/sys/rpc/rpcsec_tls.h.vnetrpctls +++ b/sys/rpc/rpcsec_tls.h @@ -86,6 +86,20 @@ /* ssl refno value to indicate TLS handshake being done. */ #define RPCTLS_REFNO_HANDSHAKE 0xFFFFFFFFFFFFFFFFULL +/* Macros for VIMAGE. */ +/* Just define the KRPC_VNETxxx() macros as VNETxxx() macros. */ +#define KRPC_VNET_DEFINE(t, n) VNET_DEFINE(t, n) +#define KRPC_VNET_DEFINE_STATIC(t, n) VNET_DEFINE_STATIC(t, n) +#define KRPC_VNET(n) VNET(n) + +#define KRPC_CURVNET_SET(n) CURVNET_SET(n) +#define KRPC_CURVNET_SET_QUIET(n) CURVNET_SET_QUIET(n) +#define KRPC_CURVNET_RESTORE() CURVNET_RESTORE() +#define KRPC_TD_TO_VNET(n) TD_TO_VNET(n) + +/* Jail OSD cleanup function. */ +int rpctls_prison_cleanup(void *obj, void *data __unused); + #endif /* _KERNEL */ #endif /* _RPC_RPCSEC_TLS_H_ */ diff --git a/sys/rpc/rpcsec_tls/rpctls_impl.c.vnetrpctls b/sys/rpc/rpcsec_tls/rpctls_impl.c --- a/sys/rpc/rpcsec_tls/rpctls_impl.c.vnetrpctls +++ b/sys/rpc/rpcsec_tls/rpctls_impl.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,8 @@ #include #include +#include + #include #include #include @@ -74,15 +77,16 @@ static struct mtx rpctls_connect_lock; static struct socket *rpctls_connect_so = NULL; static CLIENT *rpctls_connect_cl = NULL; -static CLIENT *rpctls_server_handle[RPCTLS_SRV_MAXNPROCS]; static struct mtx rpctls_server_lock; -static struct socket *rpctls_server_so = NULL; -static SVCXPRT *rpctls_server_xprt = NULL; -static bool rpctls_srv_newdaemon = false; -static int rpctls_srv_prevproc = 0; -static bool rpctls_server_busy[RPCTLS_SRV_MAXNPROCS]; static struct opaque_auth rpctls_null_verf; +KRPC_VNET_DEFINE_STATIC(CLIENT **, rpctls_server_handle); +KRPC_VNET_DEFINE_STATIC(struct socket *, rpctls_server_so) = NULL; +KRPC_VNET_DEFINE_STATIC(SVCXPRT *, rpctls_server_xprt) = NULL; +KRPC_VNET_DEFINE_STATIC(bool, rpctls_srv_newdaemon) = false; +KRPC_VNET_DEFINE_STATIC(int, rpctls_srv_prevproc) = 0; +KRPC_VNET_DEFINE_STATIC(bool *, rpctls_server_busy); + static CLIENT *rpctls_connect_client(void); static CLIENT *rpctls_server_client(int procpos); static enum clnt_stat rpctls_server(SVCXPRT *xprt, struct socket *so, @@ -90,10 +94,25 @@ uid_t *uid, int *ngrps, gid_t **gids, int *procposp); +static void +rpctls_vnetinit(const void *unused __unused) +{ + int i; + + KRPC_VNET(rpctls_server_handle) = malloc(sizeof(CLIENT *) * + RPCTLS_SRV_MAXNPROCS, M_RPC, M_WAITOK | M_ZERO); + KRPC_VNET(rpctls_server_busy) = malloc(sizeof(bool) * + RPCTLS_SRV_MAXNPROCS, M_RPC, M_WAITOK | M_ZERO); + for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) + KRPC_VNET(rpctls_server_busy)[i] = false; +} +VNET_SYSINIT(rpctls_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY, + rpctls_vnetinit, NULL); + int rpctls_init(void) { - int error, i; + int error; error = syscall_helper_register(rpctls_syscalls, SY_THR_STATIC_KLD); if (error != 0) { @@ -107,8 +126,6 @@ rpctls_null_verf.oa_flavor = AUTH_NULL; rpctls_null_verf.oa_base = RPCTLS_START_STRING; rpctls_null_verf.oa_length = strlen(RPCTLS_START_STRING); - for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) - rpctls_server_busy[i] = false; return (0); } @@ -133,27 +150,36 @@ if (error != 0) return (error); + KRPC_CURVNET_SET(KRPC_TD_TO_VNET(td)); switch (uap->op) { case RPCTLS_SYSC_SRVSTARTUP: - /* Get rid of all old CLIENTs. */ - mtx_lock(&rpctls_server_lock); - for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { - oldcl[i] = rpctls_server_handle[i]; - rpctls_server_handle[i] = NULL; - rpctls_server_busy[i] = false; - } - rpctls_srv_newdaemon = true; - rpctls_srv_prevproc = 0; - mtx_unlock(&rpctls_server_lock); - for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { - if (oldcl[i] != NULL) { - CLNT_CLOSE(oldcl[i]); - CLNT_RELEASE(oldcl[i]); + if (jailed(curthread->td_ucred) && + !prison_check_nfsd(curthread->td_ucred)) + error = EPERM; + if (error == 0) { + /* Get rid of all old CLIENTs. */ + mtx_lock(&rpctls_server_lock); + for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { + oldcl[i] = KRPC_VNET(rpctls_server_handle)[i]; + KRPC_VNET(rpctls_server_handle)[i] = NULL; + KRPC_VNET(rpctls_server_busy)[i] = false; } + KRPC_VNET(rpctls_srv_newdaemon) = true; + KRPC_VNET(rpctls_srv_prevproc) = 0; + mtx_unlock(&rpctls_server_lock); + for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { + if (oldcl[i] != NULL) { + CLNT_CLOSE(oldcl[i]); + CLNT_RELEASE(oldcl[i]); + } + } } break; case RPCTLS_SYSC_CLSETPATH: - error = copyinstr(uap->path, path, sizeof(path), NULL); + if (jailed(curthread->td_ucred)) + error = EPERM; + if (error == 0) + error = copyinstr(uap->path, path, sizeof(path), NULL); if (error == 0) { error = ENXIO; #ifdef KERN_TLS @@ -209,7 +235,11 @@ } break; case RPCTLS_SYSC_SRVSETPATH: - error = copyinstr(uap->path, path, sizeof(path), NULL); + if (jailed(curthread->td_ucred) && + !prison_check_nfsd(curthread->td_ucred)) + error = EPERM; + if (error == 0) + error = copyinstr(uap->path, path, sizeof(path), NULL); if (error == 0) { error = ENXIO; #ifdef KERN_TLS @@ -254,14 +284,14 @@ for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) oldcl[i] = NULL; mtx_lock(&rpctls_server_lock); - if (rpctls_srv_newdaemon) { + if (KRPC_VNET(rpctls_srv_newdaemon)) { /* * For a new daemon, the rpctls_srv_handles have * already been cleaned up by RPCTLS_SYSC_SRVSTARTUP. * Scan for an available array entry to use. */ for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { - if (rpctls_server_handle[i] == NULL) + if (KRPC_VNET(rpctls_server_handle)[i] == NULL) break; } if (i == RPCTLS_SRV_MAXNPROCS && error == 0) @@ -269,14 +299,14 @@ } else { /* For an old daemon, clear out old CLIENTs. */ for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { - oldcl[i] = rpctls_server_handle[i]; - rpctls_server_handle[i] = NULL; - rpctls_server_busy[i] = false; + oldcl[i] = KRPC_VNET(rpctls_server_handle)[i]; + KRPC_VNET(rpctls_server_handle)[i] = NULL; + KRPC_VNET(rpctls_server_busy)[i] = false; } i = 0; /* Set to use rpctls_server_handle[0]. */ } if (error == 0) - rpctls_server_handle[i] = cl; + KRPC_VNET(rpctls_server_handle)[i] = cl; mtx_unlock(&rpctls_server_lock); for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { @@ -300,10 +330,10 @@ case RPCTLS_SYSC_SRVSHUTDOWN: mtx_lock(&rpctls_server_lock); for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { - oldcl[i] = rpctls_server_handle[i]; - rpctls_server_handle[i] = NULL; + oldcl[i] = KRPC_VNET(rpctls_server_handle)[i]; + KRPC_VNET(rpctls_server_handle)[i] = NULL; } - rpctls_srv_newdaemon = false; + KRPC_VNET(rpctls_srv_newdaemon) = false; mtx_unlock(&rpctls_server_lock); for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { @@ -342,10 +372,10 @@ break; case RPCTLS_SYSC_SRVSOCKET: mtx_lock(&rpctls_server_lock); - so = rpctls_server_so; - rpctls_server_so = NULL; - xprt = rpctls_server_xprt; - rpctls_server_xprt = NULL; + so = KRPC_VNET(rpctls_server_so); + KRPC_VNET(rpctls_server_so) = NULL; + xprt = KRPC_VNET(rpctls_server_xprt); + KRPC_VNET(rpctls_server_xprt) = NULL; mtx_unlock(&rpctls_server_lock); if (so != NULL) { error = falloc(td, &fp, &fd, 0); @@ -370,6 +400,7 @@ default: error = EINVAL; } + KRPC_CURVNET_RESTORE(); return (error); } @@ -400,11 +431,13 @@ { CLIENT *cl; + KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread)); mtx_lock(&rpctls_server_lock); - cl = rpctls_server_handle[procpos]; + cl = KRPC_VNET(rpctls_server_handle)[procpos]; if (cl != NULL) CLNT_ACQUIRE(cl); mtx_unlock(&rpctls_server_lock); + KRPC_CURVNET_RESTORE(); return (cl); } @@ -611,33 +644,37 @@ uint32_t *gidv; int i, procpos; + KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread)); cl = NULL; procpos = -1; mtx_lock(&rpctls_server_lock); - for (i = (rpctls_srv_prevproc + 1) % RPCTLS_SRV_MAXNPROCS; - i != rpctls_srv_prevproc; i = (i + 1) % RPCTLS_SRV_MAXNPROCS) { - if (rpctls_server_handle[i] != NULL) + for (i = (KRPC_VNET(rpctls_srv_prevproc) + 1) % RPCTLS_SRV_MAXNPROCS; + i != KRPC_VNET(rpctls_srv_prevproc); + i = (i + 1) % RPCTLS_SRV_MAXNPROCS) { + if (KRPC_VNET(rpctls_server_handle)[i] != NULL) break; } - if (i == rpctls_srv_prevproc) { - if (rpctls_server_handle[i] != NULL) + if (i == KRPC_VNET(rpctls_srv_prevproc)) { + if (KRPC_VNET(rpctls_server_handle)[i] != NULL) procpos = i; } else - rpctls_srv_prevproc = procpos = i; + KRPC_VNET(rpctls_srv_prevproc) = procpos = i; mtx_unlock(&rpctls_server_lock); if (procpos >= 0) cl = rpctls_server_client(procpos); - if (cl == NULL) + if (cl == NULL) { + KRPC_CURVNET_RESTORE(); return (RPC_SYSTEMERROR); + } /* Serialize the server upcalls. */ mtx_lock(&rpctls_server_lock); - while (rpctls_server_busy[procpos]) - msleep(&rpctls_server_busy[procpos], &rpctls_server_lock, PVFS, - "rtlssn", 0); - rpctls_server_busy[procpos] = true; - rpctls_server_so = so; - rpctls_server_xprt = xprt; + while (KRPC_VNET(rpctls_server_busy)[procpos]) + msleep(&KRPC_VNET(rpctls_server_busy)[procpos], + &rpctls_server_lock, PVFS, "rtlssn", 0); + KRPC_VNET(rpctls_server_busy)[procpos] = true; + KRPC_VNET(rpctls_server_so) = so; + KRPC_VNET(rpctls_server_xprt) = xprt; mtx_unlock(&rpctls_server_lock); /* Do the server upcall. */ @@ -672,11 +709,12 @@ /* Once the upcall is done, the daemon is done with the fp and so. */ mtx_lock(&rpctls_server_lock); - rpctls_server_so = NULL; - rpctls_server_xprt = NULL; - rpctls_server_busy[procpos] = false; - wakeup(&rpctls_server_busy[procpos]); + KRPC_VNET(rpctls_server_so) = NULL; + KRPC_VNET(rpctls_server_xprt) = NULL; + KRPC_VNET(rpctls_server_busy)[procpos] = false; + wakeup(&KRPC_VNET(rpctls_server_busy)[procpos]); mtx_unlock(&rpctls_server_lock); + KRPC_CURVNET_RESTORE(); return (stat); } @@ -795,9 +833,28 @@ return (false); if (rpctlscd_run && rpctls_connect_handle == NULL) return (false); - if (rpctlssd_run && rpctls_server_handle[0] == NULL) + KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread)); + if (rpctlssd_run && KRPC_VNET(rpctls_server_handle)[0] == NULL) { + KRPC_CURVNET_RESTORE(); return (false); + } + KRPC_CURVNET_RESTORE(); *maxlenp = maxlen; return (enable); +} + +/* Osd entry for prison cleanup. */ +int +rpctls_prison_cleanup(void *obj, void *data __unused) +{ + struct prison *pr = obj; + + if ((pr->pr_flags & PR_VNET) == 0) + return (0); + KRPC_CURVNET_SET(pr->pr_vnet); + free(KRPC_VNET(rpctls_server_handle), M_RPC); + free(KRPC_VNET(rpctls_server_busy), M_RPC); + KRPC_CURVNET_RESTORE(); + return (0); } diff --git a/sys/rpc/svc.c.vnet b/sys/rpc/svc.c --- a/sys/rpc/svc.c.vnet +++ b/sys/rpc/svc.c @@ -48,6 +48,7 @@ */ #include +#include #include #include #include @@ -126,7 +127,7 @@ pool->sp_space_low = (pool->sp_space_high / 3) * 2; sysctl_ctx_init(&pool->sp_sysctl); - if (sysctl_base) { + if (!jailed(curthread->td_ucred) && sysctl_base) { SYSCTL_ADD_PROC(&pool->sp_sysctl, sysctl_base, OID_AUTO, "minthreads", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, pool, 0, svcpool_minthread_sysctl, "I", diff --git a/sys/rpc/svc_auth.c.vnet b/sys/rpc/svc_auth.c --- a/sys/rpc/svc_auth.c.vnet +++ b/sys/rpc/svc_auth.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -197,7 +198,10 @@ cr->cr_uid = cr->cr_ruid = cr->cr_svuid = xprt->xp_uid; crsetgroups(cr, xprt->xp_ngrps, xprt->xp_gidp); cr->cr_rgid = cr->cr_svgid = xprt->xp_gidp[0]; - cr->cr_prison = &prison0; + if (jailed(curthread->td_ucred)) + cr->cr_prison = curthread->td_ucred->cr_prison; + else + cr->cr_prison = &prison0; prison_hold(cr->cr_prison); *crp = cr; return (TRUE); @@ -210,7 +214,10 @@ cr->cr_uid = cr->cr_ruid = cr->cr_svuid = xcr->cr_uid; crsetgroups(cr, xcr->cr_ngroups, xcr->cr_groups); cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0]; - cr->cr_prison = &prison0; + if (jailed(curthread->td_ucred)) + cr->cr_prison = curthread->td_ucred->cr_prison; + else + cr->cr_prison = &prison0; prison_hold(cr->cr_prison); *crp = cr; return (TRUE); diff --git a/sys/rpc/svc_dg.c.vnet b/sys/rpc/svc_dg.c --- a/sys/rpc/svc_dg.c.vnet +++ b/sys/rpc/svc_dg.c @@ -45,11 +45,13 @@ */ #include +#include #include #include #include #include #include +#include #include #include #include @@ -104,6 +106,8 @@ struct sockaddr* sa; int error; + if (jailed(curthread->td_ucred)) + return (NULL); if (!__rpc_socket2sockinfo(so, &si)) { printf(svc_dg_str, svc_dg_err1); return (NULL);