Page MenuHomeFreeBSD

D37519.id115908.diff
No OneTemporary

D37519.id115908.diff

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 <fs/nfs/nfsport.h>
+#include <sys/osd.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
@@ -56,12 +57,9 @@
#include <vm/uma.h>
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 <fs/nfs/nfsport.h>
-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 <sys/callout.h>
#include <sys/filio.h>
#include <sys/hash.h>
+#include <sys/osd.h>
#include <sys/sysctl.h>
#include <nlm/nlm_prot.h>
#include <nlm/nlm.h>
@@ -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 <fs/nfs/nfsport.h>
-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 <sys/extattr.h>
#include <fs/nfs/nfsport.h>
-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 <fs/nfs/nfsport.h>
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 <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <sys/lock.h>
@@ -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 <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/osd.h>
#include <sys/priv.h>
+#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
@@ -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 <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <sys/lock.h>
@@ -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 <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <sys/lock.h>
@@ -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 <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
+#include <sys/osd.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/sbuf.h>
@@ -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 <sys/capsicum.h>
#include <sys/file.h>
#include <sys/filedesc.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -51,6 +52,8 @@
#include <sys/sysent.h>
#include <sys/sysproto.h>
+#include <net/vnet.h>
+
#include <rpc/rpc.h>
#include <rpc/rpc_com.h>
#include <rpc/rpcsec_tls.h>
@@ -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 <sys/param.h>
+#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
@@ -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 <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/jail.h>
#include <sys/ucred.h>
@@ -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 <sys/param.h>
+#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
+#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/queue.h>
#include <sys/socket.h>
@@ -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);

File Metadata

Mime Type
text/plain
Expires
Thu, May 21, 2:22 AM (4 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33369321
Default Alt Text
D37519.id115908.diff (144 KB)

Event Timeline