Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157293417
D37519.id115908.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
144 KB
Referenced Files
None
Subscribers
None
D37519.id115908.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D37519: modify the nfsd so that it can be run in a vnet prison
Attached
Detach File
Event Timeline
Log In to Comment