Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/nfsserver/nfs_nfsdstate.c
Show All 29 Lines | |||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_inet.h" | #include "opt_inet.h" | ||||
#include "opt_inet6.h" | #include "opt_inet6.h" | ||||
#include <sys/extattr.h> | #include <sys/extattr.h> | ||||
#include <fs/nfs/nfsport.h> | #include <fs/nfs/nfsport.h> | ||||
struct nfsrv_stablefirst nfsrv_stablefirst; | |||||
int nfsrv_issuedelegs = 0; | int nfsrv_issuedelegs = 0; | ||||
int nfsrv_dolocallocks = 0; | int nfsrv_dolocallocks = 0; | ||||
struct nfsv4lock nfsv4rootfs_lock; | struct nfsv4lock nfsv4rootfs_lock; | ||||
time_t nfsdev_time = 0; | time_t nfsdev_time = 0; | ||||
int nfsrv_layouthashsize; | int nfsrv_layouthashsize; | ||||
volatile int nfsrv_layoutcnt = 0; | volatile int nfsrv_layoutcnt = 0; | ||||
extern uint32_t nfs_srvmaxio; | |||||
extern int newnfs_numnfsd; | NFSD_VNET_DEFINE(struct nfsrv_stablefirst, nfsrv_stablefirst); | ||||
extern struct nfsstatsv1 nfsstatsv1; | |||||
NFSD_VNET_DECLARE(int, nfsrv_numnfsd); | |||||
extern uint32_t nfs_srvmaxio; | |||||
extern int nfsrv_lease; | extern int nfsrv_lease; | ||||
extern struct timeval nfsboottime; | extern struct timeval nfsboottime; | ||||
extern u_int32_t newnfs_true, newnfs_false; | extern u_int32_t newnfs_true, newnfs_false; | ||||
extern struct mtx nfsrv_dslock_mtx; | extern struct mtx nfsrv_dslock_mtx; | ||||
extern struct mtx nfsrv_recalllock_mtx; | extern struct mtx nfsrv_recalllock_mtx; | ||||
extern struct mtx nfsrv_dontlistlock_mtx; | extern struct mtx nfsrv_dontlistlock_mtx; | ||||
extern int nfsd_debuglevel; | extern int nfsd_debuglevel; | ||||
extern u_int nfsrv_dsdirsize; | extern u_int nfsrv_dsdirsize; | ||||
extern struct nfsdevicehead nfsrv_devidhead; | extern struct nfsdevicehead nfsrv_devidhead; | ||||
extern int nfsrv_doflexfile; | extern int nfsrv_doflexfile; | ||||
extern int nfsrv_maxpnfsmirror; | extern int nfsrv_maxpnfsmirror; | ||||
NFSV4ROOTLOCKMUTEX; | NFSV4ROOTLOCKMUTEX; | ||||
NFSSTATESPINLOCK; | NFSSTATESPINLOCK; | ||||
extern struct nfsdontlisthead nfsrv_dontlisthead; | extern struct nfsdontlisthead nfsrv_dontlisthead; | ||||
extern volatile int nfsrv_devidcnt; | extern volatile int nfsrv_devidcnt; | ||||
extern struct nfslayouthead nfsrv_recalllisthead; | extern struct nfslayouthead nfsrv_recalllisthead; | ||||
extern char *nfsrv_zeropnfsdat; | extern char *nfsrv_zeropnfsdat; | ||||
NFSDSTATSDECLARE(nfsstatsv1); | |||||
SYSCTL_DECL(_vfs_nfsd); | SYSCTL_DECL(_vfs_nfsd); | ||||
int nfsrv_statehashsize = NFSSTATEHASHSIZE; | int nfsrv_statehashsize = NFSSTATEHASHSIZE; | ||||
SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN, | SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN, | ||||
&nfsrv_statehashsize, 0, | &nfsrv_statehashsize, 0, | ||||
"Size of state hash table set via loader.conf"); | "Size of state hash table set via loader.conf"); | ||||
int nfsrv_clienthashsize = NFSCLIENTHASHSIZE; | int nfsrv_clienthashsize = NFSCLIENTHASHSIZE; | ||||
SYSCTL_INT(_vfs_nfsd, OID_AUTO, clienthashsize, CTLFLAG_RDTUN, | SYSCTL_INT(_vfs_nfsd, OID_AUTO, clienthashsize, CTLFLAG_RDTUN, | ||||
Show All 38 Lines | |||||
int nfsrv_flexlinuxhack = 0; | int nfsrv_flexlinuxhack = 0; | ||||
SYSCTL_INT(_vfs_nfsd, OID_AUTO, flexlinuxhack, CTLFLAG_RW, | SYSCTL_INT(_vfs_nfsd, OID_AUTO, flexlinuxhack, CTLFLAG_RW, | ||||
&nfsrv_flexlinuxhack, 0, | &nfsrv_flexlinuxhack, 0, | ||||
"For Linux clients, hack around Flex File Layout bug"); | "For Linux clients, hack around Flex File Layout bug"); | ||||
/* | /* | ||||
* Hash lists for nfs V4. | * Hash lists for nfs V4. | ||||
*/ | */ | ||||
struct nfsclienthashhead *nfsclienthash; | NFSD_VNET_DEFINE(struct nfsclienthashhead *, nfsclienthash); | ||||
struct nfslockhashhead *nfslockhash; | NFSD_VNET_DEFINE(struct nfslockhashhead *, nfslockhash); | ||||
struct nfssessionhash *nfssessionhash; | NFSD_VNET_DEFINE(struct nfssessionhash *, nfssessionhash); | ||||
struct nfslayouthash *nfslayouthash; | struct nfslayouthash *nfslayouthash; | ||||
volatile int nfsrv_dontlistlen = 0; | volatile int nfsrv_dontlistlen = 0; | ||||
static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 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_returnoldstateid = 0, nfsrv_clients = 0; | ||||
static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER; | static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER; | ||||
static int nfsrv_nogsscallback = 0; | static int nfsrv_nogsscallback = 0; | ||||
static volatile int nfsrv_writedelegcnt = 0; | static volatile int nfsrv_writedelegcnt = 0; | ||||
static int nfsrv_faildscnt; | static int nfsrv_faildscnt; | ||||
NFSD_VNET_DEFINE_STATIC(time_t, nfsrvboottime); | |||||
/* local functions */ | /* local functions */ | ||||
static void nfsrv_dumpaclient(struct nfsclient *clp, | static void nfsrv_dumpaclient(struct nfsclient *clp, | ||||
struct nfsd_dumpclients *dumpp); | struct nfsd_dumpclients *dumpp); | ||||
static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, | static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, | ||||
NFSPROC_T *p); | NFSPROC_T *p); | ||||
static int nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, | static int nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, | ||||
NFSPROC_T *p); | NFSPROC_T *p); | ||||
static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, | static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | #endif | ||||
} while (!igotlock); | } while (!igotlock); | ||||
NFSUNLOCKV4ROOTMUTEX(); | NFSUNLOCKV4ROOTMUTEX(); | ||||
/* | /* | ||||
* Search for a match in the client list. | * Search for a match in the client list. | ||||
*/ | */ | ||||
gotit = i = 0; | gotit = i = 0; | ||||
while (i < nfsrv_clienthashsize && !gotit) { | 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 && | if (new_clp->lc_idlen == clp->lc_idlen && | ||||
!NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) { | !NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) { | ||||
gotit = 1; | gotit = 1; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (gotit == 0) | if (gotit == 0) | ||||
i++; | i++; | ||||
Show All 28 Lines | if (!gotit || | ||||
new_clp->lc_flags |= LCL_NEEDSCONFIRM; | new_clp->lc_flags |= LCL_NEEDSCONFIRM; | ||||
if ((nd->nd_flag & ND_NFSV41) != 0) { | if ((nd->nd_flag & ND_NFSV41) != 0) { | ||||
confirmp->lval[0] = ++confirm_index; | confirmp->lval[0] = ++confirm_index; | ||||
new_clp->lc_confirm.lval[0] = confirmp->lval[0] - 1; | new_clp->lc_confirm.lval[0] = confirmp->lval[0] - 1; | ||||
} else | } else | ||||
confirmp->qval = new_clp->lc_confirm.qval = | confirmp->qval = new_clp->lc_confirm.qval = | ||||
++confirm_index; | ++confirm_index; | ||||
clientidp->lval[0] = new_clp->lc_clientid.lval[0] = | 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] = | clientidp->lval[1] = new_clp->lc_clientid.lval[1] = | ||||
nfsrv_nextclientindex(); | nfsrv_nextclientindex(); | ||||
new_clp->lc_stateindex = 0; | new_clp->lc_stateindex = 0; | ||||
new_clp->lc_statemaxindex = 0; | new_clp->lc_statemaxindex = 0; | ||||
new_clp->lc_prevsess = 0; | new_clp->lc_prevsess = 0; | ||||
new_clp->lc_cbref = 0; | new_clp->lc_cbref = 0; | ||||
new_clp->lc_expiry = nfsrv_leaseexpiry(); | new_clp->lc_expiry = nfsrv_leaseexpiry(); | ||||
LIST_INIT(&new_clp->lc_open); | LIST_INIT(&new_clp->lc_open); | ||||
LIST_INIT(&new_clp->lc_deleg); | LIST_INIT(&new_clp->lc_deleg); | ||||
LIST_INIT(&new_clp->lc_olddeleg); | LIST_INIT(&new_clp->lc_olddeleg); | ||||
LIST_INIT(&new_clp->lc_session); | LIST_INIT(&new_clp->lc_session); | ||||
for (i = 0; i < nfsrv_statehashsize; i++) | for (i = 0; i < nfsrv_statehashsize; i++) | ||||
LIST_INIT(&new_clp->lc_stateid[i]); | LIST_INIT(&new_clp->lc_stateid[i]); | ||||
LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, | LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, | ||||
lc_hash); | lc_hash); | ||||
nfsstatsv1.srvclients++; | NFSDSTATS()->srvclients++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
nfsrv_clients++; | nfsrv_clients++; | ||||
NFSLOCKV4ROOTMUTEX(); | NFSLOCKV4ROOTMUTEX(); | ||||
nfsv4_unlock(&nfsv4rootfs_lock, 1); | nfsv4_unlock(&nfsv4rootfs_lock, 1); | ||||
NFSUNLOCKV4ROOTMUTEX(); | NFSUNLOCKV4ROOTMUTEX(); | ||||
if (zapit) | if (zapit) | ||||
nfsrv_zapclient(clp, p); | nfsrv_zapclient(clp, p); | ||||
*new_clpp = NULL; | *new_clpp = NULL; | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | if (NFSBCMP(new_clp->lc_verf, clp->lc_verf, NFSX_VERF)) { | ||||
new_clp->lc_flags |= LCL_NEEDSCONFIRM; | new_clp->lc_flags |= LCL_NEEDSCONFIRM; | ||||
if ((nd->nd_flag & ND_NFSV41) != 0) { | if ((nd->nd_flag & ND_NFSV41) != 0) { | ||||
confirmp->lval[0] = ++confirm_index; | confirmp->lval[0] = ++confirm_index; | ||||
new_clp->lc_confirm.lval[0] = confirmp->lval[0] - 1; | new_clp->lc_confirm.lval[0] = confirmp->lval[0] - 1; | ||||
} else | } else | ||||
confirmp->qval = new_clp->lc_confirm.qval = | confirmp->qval = new_clp->lc_confirm.qval = | ||||
++confirm_index; | ++confirm_index; | ||||
clientidp->lval[0] = new_clp->lc_clientid.lval[0] = | clientidp->lval[0] = new_clp->lc_clientid.lval[0] = | ||||
nfsrvboottime; | NFSD_VNET(nfsrvboottime); | ||||
clientidp->lval[1] = new_clp->lc_clientid.lval[1] = | clientidp->lval[1] = new_clp->lc_clientid.lval[1] = | ||||
nfsrv_nextclientindex(); | nfsrv_nextclientindex(); | ||||
new_clp->lc_stateindex = 0; | new_clp->lc_stateindex = 0; | ||||
new_clp->lc_statemaxindex = 0; | new_clp->lc_statemaxindex = 0; | ||||
new_clp->lc_prevsess = 0; | new_clp->lc_prevsess = 0; | ||||
new_clp->lc_cbref = 0; | new_clp->lc_cbref = 0; | ||||
new_clp->lc_expiry = nfsrv_leaseexpiry(); | new_clp->lc_expiry = nfsrv_leaseexpiry(); | ||||
Show All 14 Lines | for (i = 0; i < nfsrv_statehashsize; i++) { | ||||
LIST_NEWHEAD(&new_clp->lc_stateid[i], | LIST_NEWHEAD(&new_clp->lc_stateid[i], | ||||
&clp->lc_stateid[i], ls_hash); | &clp->lc_stateid[i], ls_hash); | ||||
LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) | LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) | ||||
tstp->ls_clp = new_clp; | tstp->ls_clp = new_clp; | ||||
} | } | ||||
LIST_INIT(&new_clp->lc_session); | LIST_INIT(&new_clp->lc_session); | ||||
LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, | LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, | ||||
lc_hash); | lc_hash); | ||||
nfsstatsv1.srvclients++; | NFSDSTATS()->srvclients++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
nfsrv_clients++; | nfsrv_clients++; | ||||
NFSLOCKV4ROOTMUTEX(); | NFSLOCKV4ROOTMUTEX(); | ||||
nfsv4_unlock(&nfsv4rootfs_lock, 1); | nfsv4_unlock(&nfsv4rootfs_lock, 1); | ||||
NFSUNLOCKV4ROOTMUTEX(); | NFSUNLOCKV4ROOTMUTEX(); | ||||
/* | /* | ||||
* Must wait until any outstanding callback on the old clp | * Must wait until any outstanding callback on the old clp | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | for (i = 0; i < nfsrv_statehashsize; i++) { | ||||
LIST_NEWHEAD(&new_clp->lc_stateid[i], | LIST_NEWHEAD(&new_clp->lc_stateid[i], | ||||
&clp->lc_stateid[i], ls_hash); | &clp->lc_stateid[i], ls_hash); | ||||
LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) | LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) | ||||
tstp->ls_clp = new_clp; | tstp->ls_clp = new_clp; | ||||
} | } | ||||
LIST_INIT(&new_clp->lc_session); | LIST_INIT(&new_clp->lc_session); | ||||
LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, | LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, | ||||
lc_hash); | lc_hash); | ||||
nfsstatsv1.srvclients++; | NFSDSTATS()->srvclients++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
nfsrv_clients++; | nfsrv_clients++; | ||||
} | } | ||||
NFSLOCKV4ROOTMUTEX(); | NFSLOCKV4ROOTMUTEX(); | ||||
nfsv4_unlock(&nfsv4rootfs_lock, 1); | nfsv4_unlock(&nfsv4rootfs_lock, 1); | ||||
NFSUNLOCKV4ROOTMUTEX(); | NFSUNLOCKV4ROOTMUTEX(); | ||||
if ((nd->nd_flag & ND_NFSV41) == 0) { | if ((nd->nd_flag & ND_NFSV41) == 0) { | ||||
Show All 34 Lines | nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, | ||||
struct nfsdsession *sep; | struct nfsdsession *sep; | ||||
uint64_t sessid[2]; | uint64_t sessid[2]; | ||||
bool sess_replay; | bool sess_replay; | ||||
static uint64_t next_sess = 0; | static uint64_t next_sess = 0; | ||||
if (clpp) | if (clpp) | ||||
*clpp = NULL; | *clpp = NULL; | ||||
if ((nd == NULL || (nd->nd_flag & ND_NFSV41) == 0 || | 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; | error = NFSERR_STALECLIENTID; | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* If called with opflags == CLOPS_RENEW, the State Lock is | * If called with opflags == CLOPS_RENEW, the State Lock is | ||||
* already held. Otherwise, we need to get either that or, | * already held. Otherwise, we need to get either that or, | ||||
* for the case of Confirm, lock out the nfsd threads. | * for the case of Confirm, lock out the nfsd threads. | ||||
▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
int | int | ||||
nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p) | nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsclient *clp; | struct nfsclient *clp; | ||||
struct nfsclienthashhead *hp; | struct nfsclienthashhead *hp; | ||||
int error = 0, i, igotlock; | int error = 0, i, igotlock; | ||||
if (nfsrvboottime != clientid.lval[0]) { | if (NFSD_VNET(nfsrvboottime) != clientid.lval[0]) { | ||||
error = NFSERR_STALECLIENTID; | error = NFSERR_STALECLIENTID; | ||||
goto out; | goto out; | ||||
} | } | ||||
/* Lock out other nfsd threads */ | /* Lock out other nfsd threads */ | ||||
NFSLOCKV4ROOTMUTEX(); | NFSLOCKV4ROOTMUTEX(); | ||||
nfsv4_relref(&nfsv4rootfs_lock); | nfsv4_relref(&nfsv4rootfs_lock); | ||||
do { | do { | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p) | ||||
} while (!igotlock); | } while (!igotlock); | ||||
NFSUNLOCKV4ROOTMUTEX(); | NFSUNLOCKV4ROOTMUTEX(); | ||||
/* | /* | ||||
* Search for a match in the client list. | * Search for a match in the client list. | ||||
*/ | */ | ||||
gotit = i = 0; | gotit = i = 0; | ||||
while (i < nfsrv_clienthashsize && !gotit) { | 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 && | if (revokep->nclid_idlen == clp->lc_idlen && | ||||
!NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) { | !NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) { | ||||
gotit = 1; | gotit = 1; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
i++; | i++; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt) | ||||
NFSLOCKV4ROOTMUTEX(); | NFSLOCKV4ROOTMUTEX(); | ||||
nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); | nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); | ||||
NFSUNLOCKV4ROOTMUTEX(); | NFSUNLOCKV4ROOTMUTEX(); | ||||
NFSLOCKSTATE(); | NFSLOCKSTATE(); | ||||
/* | /* | ||||
* Rattle through the client lists until done. | * Rattle through the client lists until done. | ||||
*/ | */ | ||||
while (i < nfsrv_clienthashsize && cnt < maxcnt) { | while (i < nfsrv_clienthashsize && cnt < maxcnt) { | ||||
clp = LIST_FIRST(&nfsclienthash[i]); | clp = LIST_FIRST(&NFSD_VNET(nfsclienthash)[i]); | ||||
while (clp != LIST_END(&nfsclienthash[i]) && cnt < maxcnt) { | while (clp != LIST_END(&NFSD_VNET(nfsclienthash)[i]) && cnt < | ||||
maxcnt) { | |||||
nfsrv_dumpaclient(clp, &dumpp[cnt]); | nfsrv_dumpaclient(clp, &dumpp[cnt]); | ||||
cnt++; | cnt++; | ||||
clp = LIST_NEXT(clp, lc_hash); | clp = LIST_NEXT(clp, lc_hash); | ||||
} | } | ||||
i++; | i++; | ||||
} | } | ||||
if (cnt < maxcnt) | if (cnt < maxcnt) | ||||
dumpp[cnt].ndcl_clid.nclid_idlen = 0; | dumpp[cnt].ndcl_clid.nclid_idlen = 0; | ||||
▲ Show 20 Lines • Show All 241 Lines • ▼ Show 20 Lines | |||||
* as it holds the spin/mutex lock and there is no exclusive lock on | * as it holds the spin/mutex lock and there is no exclusive lock on | ||||
* nfsv4rootfs_lock. | * nfsv4rootfs_lock. | ||||
* (For OpenBSD, a kthread is ok. For FreeBSD, I think it is ok | * (For OpenBSD, a kthread is ok. For FreeBSD, I think it is ok | ||||
* to do this from a callout, since the spin locks work. For | * to do this from a callout, since the spin locks work. For | ||||
* Darwin, I'm not sure what will work correctly yet.) | * Darwin, I'm not sure what will work correctly yet.) | ||||
* Should be called once per second. | * Should be called once per second. | ||||
*/ | */ | ||||
void | void | ||||
nfsrv_servertimer(void) | nfsrv_servertimer(void *arg __unused) | ||||
{ | { | ||||
struct nfsclient *clp, *nclp; | struct nfsclient *clp, *nclp; | ||||
struct nfsstate *stp, *nstp; | struct nfsstate *stp, *nstp; | ||||
int got_ref, i; | int got_ref, i; | ||||
/* | /* | ||||
* Make sure nfsboottime is set. This is used by V3 as well | * Make sure nfsboottime is set. This is used by V3 as well | ||||
* as V4. Note that nfsboottime is not nfsrvboottime, which is | * as V4. Note that nfsboottime is not nfsrvboottime, which is | ||||
* only used by the V4 server for leases. | * only used by the V4 server for leases. | ||||
*/ | */ | ||||
if (nfsboottime.tv_sec == 0) | if (nfsboottime.tv_sec == 0) | ||||
NFSSETBOOTTIME(nfsboottime); | NFSSETBOOTTIME(nfsboottime); | ||||
/* | /* | ||||
* If server hasn't started yet, just return. | * If server hasn't started yet, just return. | ||||
*/ | */ | ||||
NFSLOCKSTATE(); | NFSLOCKSTATE(); | ||||
if (nfsrv_stablefirst.nsf_eograce == 0) { | if (NFSD_VNET(nfsrv_stablefirst).nsf_eograce == 0) { | ||||
NFSUNLOCKSTATE(); | NFSUNLOCKSTATE(); | ||||
return; | return; | ||||
} | } | ||||
if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) { | if (!(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_UPDATEDONE)) { | ||||
if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) && | if (!(NFSD_VNET(nfsrv_stablefirst).nsf_flags & | ||||
NFSD_MONOSEC > nfsrv_stablefirst.nsf_eograce) | NFSNSF_GRACEOVER) && | ||||
nfsrv_stablefirst.nsf_flags |= | NFSD_MONOSEC > NFSD_VNET(nfsrv_stablefirst).nsf_eograce) | ||||
NFSD_VNET(nfsrv_stablefirst).nsf_flags |= | |||||
(NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); | (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); | ||||
NFSUNLOCKSTATE(); | NFSUNLOCKSTATE(); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Try and get a reference count on the nfsv4rootfs_lock so that | * Try and get a reference count on the nfsv4rootfs_lock so that | ||||
* no nfsd thread can acquire an exclusive lock on it before this | * no nfsd thread can acquire an exclusive lock on it before this | ||||
* call is done. If it is already exclusively locked, just return. | * call is done. If it is already exclusively locked, just return. | ||||
*/ | */ | ||||
NFSLOCKV4ROOTMUTEX(); | NFSLOCKV4ROOTMUTEX(); | ||||
got_ref = nfsv4_getref_nonblock(&nfsv4rootfs_lock); | got_ref = nfsv4_getref_nonblock(&nfsv4rootfs_lock); | ||||
NFSUNLOCKV4ROOTMUTEX(); | NFSUNLOCKV4ROOTMUTEX(); | ||||
if (got_ref == 0) { | if (got_ref == 0) { | ||||
NFSUNLOCKSTATE(); | NFSUNLOCKSTATE(); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* For each client... | * For each client... | ||||
*/ | */ | ||||
for (i = 0; i < nfsrv_clienthashsize; i++) { | for (i = 0; i < nfsrv_clienthashsize; i++) { | ||||
clp = LIST_FIRST(&nfsclienthash[i]); | clp = LIST_FIRST(&NFSD_VNET(nfsclienthash)[i]); | ||||
while (clp != LIST_END(&nfsclienthash[i])) { | while (clp != LIST_END(&NFSD_VNET(nfsclienthash)[i])) { | ||||
nclp = LIST_NEXT(clp, lc_hash); | nclp = LIST_NEXT(clp, lc_hash); | ||||
if (!(clp->lc_flags & LCL_EXPIREIT)) { | if (!(clp->lc_flags & LCL_EXPIREIT)) { | ||||
if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC | if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC | ||||
&& ((LIST_EMPTY(&clp->lc_deleg) | && ((LIST_EMPTY(&clp->lc_deleg) | ||||
&& LIST_EMPTY(&clp->lc_open)) || | && LIST_EMPTY(&clp->lc_open)) || | ||||
nfsrv_clients > nfsrv_clienthighwater)) || | nfsrv_clients > nfsrv_clienthighwater)) || | ||||
(clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC || | (clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC || | ||||
(clp->lc_expiry < NFSD_MONOSEC && | (clp->lc_expiry < NFSD_MONOSEC && | ||||
Show All 14 Lines | if (!(clp->lc_flags & LCL_EXPIREIT)) { | ||||
* OR | * OR | ||||
* Lease has expired PLUS the number of opens + locks | * Lease has expired PLUS the number of opens + locks | ||||
* has exceeded 90% of capacity | * has exceeded 90% of capacity | ||||
* | * | ||||
* --> Mark for expiry. The actual expiry will be done | * --> Mark for expiry. The actual expiry will be done | ||||
* by an nfsd sometime soon. | * by an nfsd sometime soon. | ||||
*/ | */ | ||||
clp->lc_flags |= LCL_EXPIREIT; | clp->lc_flags |= LCL_EXPIREIT; | ||||
nfsrv_stablefirst.nsf_flags |= | NFSD_VNET(nfsrv_stablefirst).nsf_flags |= | ||||
(NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT); | (NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT); | ||||
} else { | } else { | ||||
/* | /* | ||||
* If there are no opens, increment no open tick cnt | * If there are no opens, increment no open tick cnt | ||||
* If time exceeds NFSNOOPEN, mark it to be thrown away | * If time exceeds NFSNOOPEN, mark it to be thrown away | ||||
* otherwise, if there is an open, reset no open time | * otherwise, if there is an open, reset no open time | ||||
* Hopefully, this will avoid excessive re-creation | * Hopefully, this will avoid excessive re-creation | ||||
* of open owners and subsequent open confirms. | * of open owners and subsequent open confirms. | ||||
*/ | */ | ||||
stp = LIST_FIRST(&clp->lc_open); | stp = LIST_FIRST(&clp->lc_open); | ||||
while (stp != LIST_END(&clp->lc_open)) { | while (stp != LIST_END(&clp->lc_open)) { | ||||
nstp = LIST_NEXT(stp, ls_list); | nstp = LIST_NEXT(stp, ls_list); | ||||
if (LIST_EMPTY(&stp->ls_open)) { | if (LIST_EMPTY(&stp->ls_open)) { | ||||
stp->ls_noopens++; | stp->ls_noopens++; | ||||
if (stp->ls_noopens > NFSNOOPEN || | if (stp->ls_noopens > NFSNOOPEN || | ||||
(nfsrv_openpluslock * 2) > | (nfsrv_openpluslock * 2) > | ||||
nfsrv_v4statelimit) | nfsrv_v4statelimit) | ||||
nfsrv_stablefirst.nsf_flags |= | NFSD_VNET(nfsrv_stablefirst).nsf_flags |= | ||||
NFSNSF_NOOPENS; | NFSNSF_NOOPENS; | ||||
} else { | } else { | ||||
stp->ls_noopens = 0; | stp->ls_noopens = 0; | ||||
} | } | ||||
stp = nstp; | stp = nstp; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | #ifdef notyet | ||||
} | } | ||||
#endif | #endif | ||||
newnfs_disconnect(NULL, &clp->lc_req); | newnfs_disconnect(NULL, &clp->lc_req); | ||||
free(clp->lc_req.nr_nam, M_SONAME); | free(clp->lc_req.nr_nam, M_SONAME); | ||||
NFSFREEMUTEX(&clp->lc_req.nr_mtx); | NFSFREEMUTEX(&clp->lc_req.nr_mtx); | ||||
free(clp->lc_stateid, M_NFSDCLIENT); | free(clp->lc_stateid, M_NFSDCLIENT); | ||||
free(clp, M_NFSDCLIENT); | free(clp, M_NFSDCLIENT); | ||||
NFSLOCKSTATE(); | NFSLOCKSTATE(); | ||||
nfsstatsv1.srvclients--; | NFSDSTATS()->srvclients--; | ||||
nfsrv_openpluslock--; | nfsrv_openpluslock--; | ||||
nfsrv_clients--; | nfsrv_clients--; | ||||
NFSUNLOCKSTATE(); | NFSUNLOCKSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* Free a list of delegation state structures. | * Free a list of delegation state structures. | ||||
* (This function will also free all nfslockfile structures that no | * (This function will also free all nfslockfile structures that no | ||||
Show All 26 Lines | nfsrv_freedeleg(struct nfsstate *stp) | ||||
lfp = stp->ls_lfp; | lfp = stp->ls_lfp; | ||||
if (LIST_EMPTY(&lfp->lf_open) && | if (LIST_EMPTY(&lfp->lf_open) && | ||||
LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) && | LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) && | ||||
LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && | LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && | ||||
lfp->lf_usecount == 0 && | lfp->lf_usecount == 0 && | ||||
nfsv4_testlock(&lfp->lf_locallock_lck) == 0) | nfsv4_testlock(&lfp->lf_locallock_lck) == 0) | ||||
nfsrv_freenfslockfile(lfp); | nfsrv_freenfslockfile(lfp); | ||||
free(stp, M_NFSDSTATE); | free(stp, M_NFSDSTATE); | ||||
nfsstatsv1.srvdelegates--; | NFSDSTATS()->srvdelegates--; | ||||
nfsrv_openpluslock--; | nfsrv_openpluslock--; | ||||
nfsrv_delegatecnt--; | nfsrv_delegatecnt--; | ||||
} | } | ||||
/* | /* | ||||
* This function frees an open owner and all associated opens. | * This function frees an open owner and all associated opens. | ||||
*/ | */ | ||||
static void | static void | ||||
Show All 9 Lines | nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p) | ||||
while (nstp != LIST_END(&stp->ls_open)) { | while (nstp != LIST_END(&stp->ls_open)) { | ||||
tstp = nstp; | tstp = nstp; | ||||
nstp = LIST_NEXT(nstp, ls_list); | nstp = LIST_NEXT(nstp, ls_list); | ||||
(void) nfsrv_freeopen(tstp, NULL, cansleep, p); | (void) nfsrv_freeopen(tstp, NULL, cansleep, p); | ||||
} | } | ||||
if (stp->ls_op) | if (stp->ls_op) | ||||
nfsrvd_derefcache(stp->ls_op); | nfsrvd_derefcache(stp->ls_op); | ||||
free(stp, M_NFSDSTATE); | free(stp, M_NFSDSTATE); | ||||
nfsstatsv1.srvopenowners--; | NFSDSTATS()->srvopenowners--; | ||||
nfsrv_openpluslock--; | nfsrv_openpluslock--; | ||||
} | } | ||||
/* | /* | ||||
* This function frees an open (nfsstate open structure) with all associated | * This function frees an open (nfsstate open structure) with all associated | ||||
* lock_owners and locks. It also frees the nfslockfile structure iff there | * lock_owners and locks. It also frees the nfslockfile structure iff there | ||||
* are no other opens on the file. | * are no other opens on the file. | ||||
* Returns 1 if it free'd the nfslockfile, 0 otherwise. | * Returns 1 if it free'd the nfslockfile, 0 otherwise. | ||||
Show All 33 Lines | if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) && | ||||
(cansleep != 0 || nfsv4_testlock(&lfp->lf_locallock_lck) == 0)) { | (cansleep != 0 || nfsv4_testlock(&lfp->lf_locallock_lck) == 0)) { | ||||
nfsrv_freenfslockfile(lfp); | nfsrv_freenfslockfile(lfp); | ||||
ret = 1; | ret = 1; | ||||
} else | } else | ||||
ret = 0; | ret = 0; | ||||
if (cansleep != 0) | if (cansleep != 0) | ||||
NFSUNLOCKSTATE(); | NFSUNLOCKSTATE(); | ||||
free(stp, M_NFSDSTATE); | free(stp, M_NFSDSTATE); | ||||
nfsstatsv1.srvopens--; | NFSDSTATS()->srvopens--; | ||||
nfsrv_openpluslock--; | nfsrv_openpluslock--; | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* | /* | ||||
* Frees a lockowner and all associated locks. | * Frees a lockowner and all associated locks. | ||||
*/ | */ | ||||
static void | static void | ||||
nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, | nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, | ||||
NFSPROC_T *p) | NFSPROC_T *p) | ||||
{ | { | ||||
LIST_REMOVE(stp, ls_hash); | LIST_REMOVE(stp, ls_hash); | ||||
LIST_REMOVE(stp, ls_list); | LIST_REMOVE(stp, ls_list); | ||||
nfsrv_freeallnfslocks(stp, vp, cansleep, p); | nfsrv_freeallnfslocks(stp, vp, cansleep, p); | ||||
if (stp->ls_op) | if (stp->ls_op) | ||||
nfsrvd_derefcache(stp->ls_op); | nfsrvd_derefcache(stp->ls_op); | ||||
free(stp, M_NFSDSTATE); | free(stp, M_NFSDSTATE); | ||||
nfsstatsv1.srvlockowners--; | NFSDSTATS()->srvlockowners--; | ||||
nfsrv_openpluslock--; | nfsrv_openpluslock--; | ||||
} | } | ||||
/* | /* | ||||
* Free all the nfs locks on a lockowner. | * Free all the nfs locks on a lockowner. | ||||
*/ | */ | ||||
static void | static void | ||||
nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep, | nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep, | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
* Free an nfslock structure. | * Free an nfslock structure. | ||||
*/ | */ | ||||
static void | static void | ||||
nfsrv_freenfslock(struct nfslock *lop) | nfsrv_freenfslock(struct nfslock *lop) | ||||
{ | { | ||||
if (lop->lo_lckfile.le_prev != NULL) { | if (lop->lo_lckfile.le_prev != NULL) { | ||||
LIST_REMOVE(lop, lo_lckfile); | LIST_REMOVE(lop, lo_lckfile); | ||||
nfsstatsv1.srvlocks--; | NFSDSTATS()->srvlocks--; | ||||
nfsrv_openpluslock--; | nfsrv_openpluslock--; | ||||
} | } | ||||
LIST_REMOVE(lop, lo_lckowner); | LIST_REMOVE(lop, lo_lckowner); | ||||
free(lop, M_NFSDLOCK); | free(lop, M_NFSDLOCK); | ||||
} | } | ||||
/* | /* | ||||
* This function frees an nfslockfile structure. | * This function frees an nfslockfile structure. | ||||
▲ Show 20 Lines • Show All 760 Lines • ▼ Show 20 Lines | if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) { | ||||
new_stp->ls_lfp = lfp; | new_stp->ls_lfp = lfp; | ||||
nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp, | nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp, | ||||
lfp); | lfp); | ||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid), | LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid), | ||||
new_stp, ls_hash); | new_stp, ls_hash); | ||||
LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list); | LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list); | ||||
*new_lopp = NULL; | *new_lopp = NULL; | ||||
*new_stpp = NULL; | *new_stpp = NULL; | ||||
nfsstatsv1.srvlockowners++; | NFSDSTATS()->srvlockowners++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
} | } | ||||
if (filestruct_locked != 0) { | if (filestruct_locked != 0) { | ||||
NFSUNLOCKSTATE(); | NFSUNLOCKSTATE(); | ||||
nfsrv_locallock_commit(lfp, lock_flags, first, end); | nfsrv_locallock_commit(lfp, lock_flags, first, end); | ||||
NFSLOCKSTATE(); | NFSLOCKSTATE(); | ||||
nfsrv_unlocklf(lfp); | nfsrv_unlocklf(lfp); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 635 Lines • ▼ Show 20 Lines | if (stp->ls_lfp == lfp) { | ||||
new_open->ls_openowner = new_stp; | new_open->ls_openowner = new_stp; | ||||
new_stp->ls_flags = 0; | new_stp->ls_flags = 0; | ||||
nfsrvd_refcache(new_stp->ls_op); | nfsrvd_refcache(new_stp->ls_op); | ||||
new_stp->ls_noopens = 0; | new_stp->ls_noopens = 0; | ||||
LIST_INIT(&new_stp->ls_open); | LIST_INIT(&new_stp->ls_open); | ||||
LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); | LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); | ||||
LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); | LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); | ||||
*new_stpp = NULL; | *new_stpp = NULL; | ||||
nfsstatsv1.srvopenowners++; | NFSDSTATS()->srvopenowners++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
} | } | ||||
openstp = new_open; | openstp = new_open; | ||||
new_open = NULL; | new_open = NULL; | ||||
nfsstatsv1.srvopens++; | NFSDSTATS()->srvopens++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (stp == LIST_END(&clp->lc_olddeleg)) | if (stp == LIST_END(&clp->lc_olddeleg)) | ||||
error = NFSERR_EXPIRED; | error = NFSERR_EXPIRED; | ||||
} else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { | } else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | if (new_stp->ls_flags & NFSLCK_DELEGPREV) { | ||||
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); | LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); | ||||
new_deleg = NULL; | new_deleg = NULL; | ||||
if (delegate == 2 || nfsrv_issuedelegs == 0 || | if (delegate == 2 || nfsrv_issuedelegs == 0 || | ||||
(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != | (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != | ||||
LCL_CALLBACKSON || | LCL_CALLBACKSON || | ||||
NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) || | NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) || | ||||
!NFSVNO_DELEGOK(vp)) | !NFSVNO_DELEGOK(vp)) | ||||
*rflagsp |= NFSV4OPEN_RECALL; | *rflagsp |= NFSV4OPEN_RECALL; | ||||
nfsstatsv1.srvdelegates++; | NFSDSTATS()->srvdelegates++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
nfsrv_delegatecnt++; | nfsrv_delegatecnt++; | ||||
/* | /* | ||||
* Now, do the associated open. | * Now, do the associated open. | ||||
*/ | */ | ||||
new_open->ls_stateid.seqid = 1; | new_open->ls_stateid.seqid = 1; | ||||
new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; | new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; | ||||
Show All 23 Lines | if (ownerstp) { | ||||
new_open->ls_openowner = new_stp; | new_open->ls_openowner = new_stp; | ||||
new_stp->ls_flags = 0; | new_stp->ls_flags = 0; | ||||
nfsrvd_refcache(new_stp->ls_op); | nfsrvd_refcache(new_stp->ls_op); | ||||
new_stp->ls_noopens = 0; | new_stp->ls_noopens = 0; | ||||
LIST_INIT(&new_stp->ls_open); | LIST_INIT(&new_stp->ls_open); | ||||
LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); | LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); | ||||
LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); | LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); | ||||
*new_stpp = NULL; | *new_stpp = NULL; | ||||
nfsstatsv1.srvopenowners++; | NFSDSTATS()->srvopenowners++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
} | } | ||||
openstp = new_open; | openstp = new_open; | ||||
new_open = NULL; | new_open = NULL; | ||||
nfsstatsv1.srvopens++; | NFSDSTATS()->srvopens++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
} else { | } else { | ||||
error = NFSERR_RECLAIMCONFLICT; | error = NFSERR_RECLAIMCONFLICT; | ||||
} | } | ||||
} else if (ownerstp) { | } else if (ownerstp) { | ||||
if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) { | if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) { | ||||
/* Replace the open */ | /* Replace the open */ | ||||
if (ownerstp->ls_op) | if (ownerstp->ls_op) | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) { | ||||
new_deleg->ls_compref = nd->nd_compref; | new_deleg->ls_compref = nd->nd_compref; | ||||
new_deleg->ls_lastrecall = 0; | new_deleg->ls_lastrecall = 0; | ||||
nfsrv_writedelegcnt++; | nfsrv_writedelegcnt++; | ||||
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); | LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); | ||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp, | LIST_INSERT_HEAD(NFSSTATEHASH(clp, | ||||
new_deleg->ls_stateid), new_deleg, ls_hash); | new_deleg->ls_stateid), new_deleg, ls_hash); | ||||
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); | LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); | ||||
new_deleg = NULL; | new_deleg = NULL; | ||||
nfsstatsv1.srvdelegates++; | NFSDSTATS()->srvdelegates++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
nfsrv_delegatecnt++; | nfsrv_delegatecnt++; | ||||
} | } | ||||
} else { | } else { | ||||
new_open->ls_stateid.seqid = 1; | new_open->ls_stateid.seqid = 1; | ||||
new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; | new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; | ||||
new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; | new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; | ||||
new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); | new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); | ||||
new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)| | new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)| | ||||
NFSLCK_OPEN; | NFSLCK_OPEN; | ||||
new_open->ls_uid = new_stp->ls_uid; | new_open->ls_uid = new_stp->ls_uid; | ||||
new_open->ls_openowner = ownerstp; | new_open->ls_openowner = ownerstp; | ||||
new_open->ls_lfp = lfp; | new_open->ls_lfp = lfp; | ||||
new_open->ls_clp = clp; | new_open->ls_clp = clp; | ||||
LIST_INIT(&new_open->ls_open); | LIST_INIT(&new_open->ls_open); | ||||
LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); | LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); | ||||
LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); | LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); | ||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), | LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), | ||||
new_open, ls_hash); | new_open, ls_hash); | ||||
openstp = new_open; | openstp = new_open; | ||||
new_open = NULL; | new_open = NULL; | ||||
nfsstatsv1.srvopens++; | NFSDSTATS()->srvopens++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
/* | /* | ||||
* This is where we can choose to issue a delegation. | * This is where we can choose to issue a delegation. | ||||
*/ | */ | ||||
if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0) | if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0) | ||||
*rflagsp |= NFSV4OPEN_WDNOTWANTED; | *rflagsp |= NFSV4OPEN_WDNOTWANTED; | ||||
else if (nfsrv_issuedelegs == 0) | else if (nfsrv_issuedelegs == 0) | ||||
Show All 31 Lines | if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) { | ||||
new_deleg->ls_filerev = filerev; | new_deleg->ls_filerev = filerev; | ||||
new_deleg->ls_compref = nd->nd_compref; | new_deleg->ls_compref = nd->nd_compref; | ||||
new_deleg->ls_lastrecall = 0; | new_deleg->ls_lastrecall = 0; | ||||
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); | LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); | ||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp, | LIST_INSERT_HEAD(NFSSTATEHASH(clp, | ||||
new_deleg->ls_stateid), new_deleg, ls_hash); | new_deleg->ls_stateid), new_deleg, ls_hash); | ||||
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); | LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); | ||||
new_deleg = NULL; | new_deleg = NULL; | ||||
nfsstatsv1.srvdelegates++; | NFSDSTATS()->srvdelegates++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
nfsrv_delegatecnt++; | nfsrv_delegatecnt++; | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
/* | /* | ||||
* New owner case. Start the open_owner sequence with a | * New owner case. Start the open_owner sequence with a | ||||
* Needs confirmation (unless a reclaim) and hang the | * Needs confirmation (unless a reclaim) and hang the | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | if (new_stp->ls_flags & NFSLCK_RECLAIM) { | ||||
new_deleg->ls_lastrecall = 0; | new_deleg->ls_lastrecall = 0; | ||||
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, | LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, | ||||
ls_file); | ls_file); | ||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp, | LIST_INSERT_HEAD(NFSSTATEHASH(clp, | ||||
new_deleg->ls_stateid), new_deleg, ls_hash); | new_deleg->ls_stateid), new_deleg, ls_hash); | ||||
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, | LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, | ||||
ls_list); | ls_list); | ||||
new_deleg = NULL; | new_deleg = NULL; | ||||
nfsstatsv1.srvdelegates++; | NFSDSTATS()->srvdelegates++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
nfsrv_delegatecnt++; | nfsrv_delegatecnt++; | ||||
} | } | ||||
/* | /* | ||||
* Since NFSv4.1 never does an OpenConfirm, the first | * Since NFSv4.1 never does an OpenConfirm, the first | ||||
* open state will be acquired here. | * open state will be acquired here. | ||||
*/ | */ | ||||
if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { | if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { | ||||
Show All 11 Lines | if (new_stp->ls_flags & NFSLCK_DELEGPREV) { | ||||
LIST_INIT(&new_stp->ls_open); | LIST_INIT(&new_stp->ls_open); | ||||
LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); | LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); | ||||
LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); | LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); | ||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), | LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), | ||||
new_open, ls_hash); | new_open, ls_hash); | ||||
openstp = new_open; | openstp = new_open; | ||||
new_open = NULL; | new_open = NULL; | ||||
*new_stpp = NULL; | *new_stpp = NULL; | ||||
nfsstatsv1.srvopens++; | NFSDSTATS()->srvopens++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
nfsstatsv1.srvopenowners++; | NFSDSTATS()->srvopenowners++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
} | } | ||||
if (!error) { | if (!error) { | ||||
stateidp->seqid = openstp->ls_stateid.seqid; | stateidp->seqid = openstp->ls_stateid.seqid; | ||||
stateidp->other[0] = openstp->ls_stateid.other[0]; | stateidp->other[0] = openstp->ls_stateid.other[0]; | ||||
stateidp->other[1] = openstp->ls_stateid.other[1]; | stateidp->other[1] = openstp->ls_stateid.other[1]; | ||||
stateidp->other[2] = openstp->ls_stateid.other[2]; | stateidp->other[2] = openstp->ls_stateid.other[2]; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 459 Lines • ▼ Show 20 Lines | nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop, | ||||
*/ | */ | ||||
if (stp == NULL && (struct nfslockfile *)insert_lop == lfp) | if (stp == NULL && (struct nfslockfile *)insert_lop == lfp) | ||||
LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner); | LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner); | ||||
else if ((struct nfsstate *)insert_lop == stp) | else if ((struct nfsstate *)insert_lop == stp) | ||||
LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner); | LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner); | ||||
else | else | ||||
LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner); | LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner); | ||||
if (stp != NULL) { | if (stp != NULL) { | ||||
nfsstatsv1.srvlocks++; | NFSDSTATS()->srvlocks++; | ||||
nfsrv_openpluslock++; | nfsrv_openpluslock++; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* This function updates the locking for a lock owner and given file. It | * This function updates the locking for a lock owner and given file. It | ||||
* maintains a list of lock ranges ordered on increasing file offset that | * maintains a list of lock ranges ordered on increasing file offset that | ||||
* are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style). | * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style). | ||||
▲ Show 20 Lines • Show All 460 Lines • ▼ Show 20 Lines | nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, | ||||
int ret = 0; | int ret = 0; | ||||
/* | /* | ||||
* First check for a server restart. Open, LockT, ReleaseLockOwner | * First check for a server restart. Open, LockT, ReleaseLockOwner | ||||
* and DelegPurge have a clientid, the rest a stateid. | * and DelegPurge have a clientid, the rest a stateid. | ||||
*/ | */ | ||||
if (flags & | if (flags & | ||||
(NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { | (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { | ||||
if (clientid.lval[0] != nfsrvboottime) { | if (clientid.lval[0] != NFSD_VNET(nfsrvboottime)) { | ||||
ret = NFSERR_STALECLIENTID; | ret = NFSERR_STALECLIENTID; | ||||
goto out; | goto out; | ||||
} | } | ||||
} else if (stateidp->other[0] != nfsrvboottime && | } else if (stateidp->other[0] != NFSD_VNET(nfsrvboottime) && | ||||
specialid == 0) { | specialid == 0) { | ||||
ret = NFSERR_STALESTATEID; | ret = NFSERR_STALESTATEID; | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* Read, Write, Setattr and LockT can return NFSERR_GRACE and do | * Read, Write, Setattr and LockT can return NFSERR_GRACE and do | ||||
* not use a lock/open owner seqid#, so the check can be done now. | * not use a lock/open owner seqid#, so the check can be done now. | ||||
Show All 16 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp, | nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp, | ||||
u_int32_t flags) | u_int32_t flags) | ||||
{ | { | ||||
int error = 0, notreclaimed; | int error = 0, notreclaimed; | ||||
struct nfsrv_stable *sp; | struct nfsrv_stable *sp; | ||||
if ((nfsrv_stablefirst.nsf_flags & (NFSNSF_UPDATEDONE | | if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags & (NFSNSF_UPDATEDONE | | ||||
NFSNSF_GRACEOVER)) == 0) { | NFSNSF_GRACEOVER)) == 0) { | ||||
/* | /* | ||||
* First, check to see if all of the clients have done a | * First, check to see if all of the clients have done a | ||||
* ReclaimComplete. If so, grace can end now. | * ReclaimComplete. If so, grace can end now. | ||||
*/ | */ | ||||
notreclaimed = 0; | 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) { | if ((sp->nst_flag & NFSNST_RECLAIMED) == 0) { | ||||
notreclaimed = 1; | notreclaimed = 1; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (notreclaimed == 0) | if (notreclaimed == 0) | ||||
nfsrv_stablefirst.nsf_flags |= (NFSNSF_GRACEOVER | | NFSD_VNET(nfsrv_stablefirst).nsf_flags |= | ||||
NFSNSF_NEEDLOCK); | (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) { | if (flags & NFSLCK_RECLAIM) { | ||||
error = NFSERR_NOGRACE; | error = NFSERR_NOGRACE; | ||||
goto out; | goto out; | ||||
} | } | ||||
} else { | } else { | ||||
if (!(flags & NFSLCK_RECLAIM)) { | if (!(flags & NFSLCK_RECLAIM)) { | ||||
error = NFSERR_GRACE; | error = NFSERR_GRACE; | ||||
goto out; | goto out; | ||||
} | } | ||||
if (nd != NULL && clp != NULL && | if (nd != NULL && clp != NULL && | ||||
(nd->nd_flag & ND_NFSV41) != 0 && | (nd->nd_flag & ND_NFSV41) != 0 && | ||||
(clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) { | (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) { | ||||
error = NFSERR_NOGRACE; | error = NFSERR_NOGRACE; | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* If grace is almost over and we are still getting Reclaims, | * If grace is almost over and we are still getting Reclaims, | ||||
* extend grace a bit. | * extend grace a bit. | ||||
*/ | */ | ||||
if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > | if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > | ||||
nfsrv_stablefirst.nsf_eograce) | NFSD_VNET(nfsrv_stablefirst).nsf_eograce) | ||||
nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC + | NFSD_VNET(nfsrv_stablefirst).nsf_eograce = | ||||
NFSRV_LEASEDELTA; | NFSD_MONOSEC + NFSRV_LEASEDELTA; | ||||
} | } | ||||
out: | out: | ||||
NFSEXITCODE(error); | NFSEXITCODE(error); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 417 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Read in the stable storage file. Called by nfssvc() before the nfsd | * Read in the stable storage file. Called by nfssvc() before the nfsd | ||||
* processes start servicing requests. | * processes start servicing requests. | ||||
*/ | */ | ||||
void | void | ||||
nfsrv_setupstable(NFSPROC_T *p) | 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 nfsrv_stable *sp, *nsp; | ||||
struct nfst_rec *tsp; | struct nfst_rec *tsp; | ||||
int error, i, tryagain; | int error, i, tryagain; | ||||
off_t off = 0; | off_t off = 0; | ||||
ssize_t aresid, len; | ssize_t aresid, len; | ||||
/* | /* | ||||
* If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without | * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without | ||||
* a reboot, so state has not been lost. | * a reboot, so state has not been lost. | ||||
*/ | */ | ||||
if (sf->nsf_flags & NFSNSF_UPDATEDONE) | if (sf->nsf_flags & NFSNSF_UPDATEDONE) | ||||
return; | return; | ||||
/* | /* | ||||
* Set Grace over just until the file reads successfully. | * Set Grace over just until the file reads successfully. | ||||
*/ | */ | ||||
nfsrvboottime = time_second; | NFSD_VNET(nfsrvboottime) = time_second; | ||||
LIST_INIT(&sf->nsf_head); | LIST_INIT(&sf->nsf_head); | ||||
sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); | sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); | ||||
sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA; | sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA; | ||||
if (sf->nsf_fp == NULL) | if (sf->nsf_fp == NULL) | ||||
return; | return; | ||||
error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), | error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), | ||||
(caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE, | (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE, | ||||
0, NFSFPCRED(sf->nsf_fp), &aresid, p); | 0, NFSFPCRED(sf->nsf_fp), &aresid, p); | ||||
if (error || aresid || sf->nsf_numboots == 0 || | if (error || aresid || sf->nsf_numboots == 0 || | ||||
sf->nsf_numboots > NFSNSF_MAXNUMBOOTS) | sf->nsf_numboots > NFSNSF_MAXNUMBOOTS) | ||||
return; | return; | ||||
/* | /* | ||||
* Now, read in the boottimes. | * Now, read in the boottimes. | ||||
*/ | */ | ||||
sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) * | 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); | off = sizeof (struct nfsf_rec); | ||||
error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), | error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), | ||||
(caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off, | (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off, | ||||
UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); | UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); | ||||
if (error || aresid) { | if (error || aresid) { | ||||
free(sf->nsf_bootvals, M_TEMP); | free(sf->nsf_bootvals, M_TEMP); | ||||
sf->nsf_bootvals = NULL; | sf->nsf_bootvals = NULL; | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Make sure this nfsrvboottime is different from all recorded | * Make sure this nfsrvboottime is different from all recorded | ||||
* previous ones. | * previous ones. | ||||
*/ | */ | ||||
do { | do { | ||||
tryagain = 0; | tryagain = 0; | ||||
for (i = 0; i < sf->nsf_numboots; i++) { | for (i = 0; i < sf->nsf_numboots; i++) { | ||||
if (nfsrvboottime == sf->nsf_bootvals[i]) { | if (NFSD_VNET(nfsrvboottime) == sf->nsf_bootvals[i]) { | ||||
nfsrvboottime++; | NFSD_VNET(nfsrvboottime)++; | ||||
tryagain = 1; | tryagain = 1; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} while (tryagain); | } while (tryagain); | ||||
sf->nsf_flags |= NFSNSF_OK; | sf->nsf_flags |= NFSNSF_OK; | ||||
off += (sf->nsf_numboots * sizeof (time_t)); | off += (sf->nsf_numboots * sizeof (time_t)); | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Update the stable storage file, now that the grace period is over. | * Update the stable storage file, now that the grace period is over. | ||||
*/ | */ | ||||
void | void | ||||
nfsrv_updatestable(NFSPROC_T *p) | nfsrv_updatestable(NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; | struct nfsrv_stablefirst *sf = &NFSD_VNET(nfsrv_stablefirst); | ||||
struct nfsrv_stable *sp, *nsp; | struct nfsrv_stable *sp, *nsp; | ||||
int i; | int i; | ||||
struct nfsvattr nva; | struct nfsvattr nva; | ||||
vnode_t vp; | vnode_t vp; | ||||
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) | #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) | ||||
mount_t mp = NULL; | mount_t mp = NULL; | ||||
#endif | #endif | ||||
int error; | int error; | ||||
Show All 9 Lines | #endif | ||||
* have timestamps older than the old boot | * have timestamps older than the old boot | ||||
*/ | */ | ||||
if (sf->nsf_bootvals) { | if (sf->nsf_bootvals) { | ||||
sf->nsf_numboots++; | sf->nsf_numboots++; | ||||
for (i = sf->nsf_numboots - 2; i >= 0; i--) | for (i = sf->nsf_numboots - 2; i >= 0; i--) | ||||
sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i]; | sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i]; | ||||
} else { | } else { | ||||
sf->nsf_numboots = 1; | 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); | M_TEMP, M_WAITOK); | ||||
} | } | ||||
sf->nsf_bootvals[0] = nfsrvboottime; | sf->nsf_bootvals[0] = NFSD_VNET(nfsrvboottime); | ||||
sf->nsf_lease = nfsrv_lease; | sf->nsf_lease = nfsrv_lease; | ||||
NFSVNO_ATTRINIT(&nva); | NFSVNO_ATTRINIT(&nva); | ||||
NFSVNO_SETATTRVAL(&nva, size, 0); | NFSVNO_SETATTRVAL(&nva, size, 0); | ||||
vp = NFSFPVNODE(sf->nsf_fp); | vp = NFSFPVNODE(sf->nsf_fp); | ||||
vn_start_write(vp, &mp, V_WAIT); | vn_start_write(vp, &mp, V_WAIT); | ||||
if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { | if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { | ||||
error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p, | error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p, | ||||
NULL); | NULL); | ||||
Show All 37 Lines | |||||
} | } | ||||
/* | /* | ||||
* Append a record to the stable storage file. | * Append a record to the stable storage file. | ||||
*/ | */ | ||||
void | void | ||||
nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p) | 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; | struct nfst_rec *sp; | ||||
int error; | int error; | ||||
if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL) | if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL) | ||||
return; | return; | ||||
sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + | sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + | ||||
len - 1, M_TEMP, M_WAITOK); | len - 1, M_TEMP, M_WAITOK); | ||||
sp->len = len; | sp->len = len; | ||||
Show All 16 Lines | |||||
static void | static void | ||||
nfsrv_markstable(struct nfsclient *clp) | nfsrv_markstable(struct nfsclient *clp) | ||||
{ | { | ||||
struct nfsrv_stable *sp; | struct nfsrv_stable *sp; | ||||
/* | /* | ||||
* First find the client structure. | * 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 && | if (sp->nst_len == clp->lc_idlen && | ||||
!NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) | !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) | ||||
break; | break; | ||||
} | } | ||||
if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) | if (sp == LIST_END(&NFSD_VNET(nfsrv_stablefirst).nsf_head)) | ||||
return; | return; | ||||
/* | /* | ||||
* Now, just mark it and set the nfsclient back pointer. | * Now, just mark it and set the nfsclient back pointer. | ||||
*/ | */ | ||||
sp->nst_flag |= NFSNST_GOTSTATE; | sp->nst_flag |= NFSNST_GOTSTATE; | ||||
sp->nst_clp = clp; | sp->nst_clp = clp; | ||||
} | } | ||||
/* | /* | ||||
* This function is called when a NFSv4.1 client does a ReclaimComplete. | * This function is called when a NFSv4.1 client does a ReclaimComplete. | ||||
* Very similar to nfsrv_markstable(), except for the flag being set. | * Very similar to nfsrv_markstable(), except for the flag being set. | ||||
*/ | */ | ||||
static void | static void | ||||
nfsrv_markreclaim(struct nfsclient *clp) | nfsrv_markreclaim(struct nfsclient *clp) | ||||
{ | { | ||||
struct nfsrv_stable *sp; | struct nfsrv_stable *sp; | ||||
/* | /* | ||||
* First find the client structure. | * 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 && | if (sp->nst_len == clp->lc_idlen && | ||||
!NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) | !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) | ||||
break; | break; | ||||
} | } | ||||
if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) | if (sp == LIST_END(&NFSD_VNET(nfsrv_stablefirst).nsf_head)) | ||||
return; | return; | ||||
/* | /* | ||||
* Now, just set the flag. | * Now, just set the flag. | ||||
*/ | */ | ||||
sp->nst_flag |= NFSNST_RECLAIMED; | sp->nst_flag |= NFSNST_RECLAIMED; | ||||
} | } | ||||
/* | /* | ||||
* This function is called for a reclaim, to see if it gets grace. | * This function is called for a reclaim, to see if it gets grace. | ||||
* It returns 0 if a reclaim is allowed, 1 otherwise. | * It returns 0 if a reclaim is allowed, 1 otherwise. | ||||
*/ | */ | ||||
static int | static int | ||||
nfsrv_checkstable(struct nfsclient *clp) | nfsrv_checkstable(struct nfsclient *clp) | ||||
{ | { | ||||
struct nfsrv_stable *sp; | struct nfsrv_stable *sp; | ||||
/* | /* | ||||
* First, find the entry for the client. | * 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 && | if (sp->nst_len == clp->lc_idlen && | ||||
!NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) | !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) | ||||
break; | break; | ||||
} | } | ||||
/* | /* | ||||
* If not in the list, state was revoked or no state was issued | * If not in the list, state was revoked or no state was issued | ||||
* since the previous reboot, a reclaim is denied. | * 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) || | (sp->nst_flag & NFSNST_REVOKE) || | ||||
!(nfsrv_stablefirst.nsf_flags & NFSNSF_OK)) | !(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_OK)) | ||||
return (1); | return (1); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Test for and try to clear out a conflicting client. This is called by | * Test for and try to clear out a conflicting client. This is called by | ||||
* nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients | * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients | ||||
* a found. | * a found. | ||||
Show All 11 Lines | nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp, | ||||
NFSPROC_T *p) | NFSPROC_T *p) | ||||
{ | { | ||||
int gotlock, lktype = 0; | int gotlock, lktype = 0; | ||||
/* | /* | ||||
* If lease hasn't expired, we can't fix it. | * If lease hasn't expired, we can't fix it. | ||||
*/ | */ | ||||
if (clp->lc_expiry >= NFSD_MONOSEC || | if (clp->lc_expiry >= NFSD_MONOSEC || | ||||
!(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) | !(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_UPDATEDONE)) | ||||
return (0); | return (0); | ||||
if (*haslockp == 0) { | if (*haslockp == 0) { | ||||
NFSUNLOCKSTATE(); | NFSUNLOCKSTATE(); | ||||
if (vp != NULL) { | if (vp != NULL) { | ||||
lktype = NFSVOPISLOCKED(vp); | lktype = NFSVOPISLOCKED(vp); | ||||
NFSVOPUNLOCK(vp); | NFSVOPUNLOCK(vp); | ||||
} | } | ||||
NFSLOCKV4ROOTMUTEX(); | NFSLOCKV4ROOTMUTEX(); | ||||
▲ Show 20 Lines • Show All 382 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
time_t starttime; | time_t starttime; | ||||
int error; | int error; | ||||
/* | /* | ||||
* First, check to see if the server is currently running and it has | * First, check to see if the server is currently running and it has | ||||
* been called for a regular file when issuing delegations. | * 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) | nfsrv_issuedelegs == 0) | ||||
return; | return; | ||||
KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp)); | KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp)); | ||||
/* | /* | ||||
* First, get a reference on the nfsv4rootfs_lock so that an | * First, get a reference on the nfsv4rootfs_lock so that an | ||||
* exclusive lock cannot be acquired by another thread. | * exclusive lock cannot be acquired by another thread. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 217 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
nfsrv_throwawayopens(NFSPROC_T *p) | nfsrv_throwawayopens(NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsclient *clp, *nclp; | struct nfsclient *clp, *nclp; | ||||
struct nfsstate *stp, *nstp; | struct nfsstate *stp, *nstp; | ||||
int i; | int i; | ||||
NFSLOCKSTATE(); | NFSLOCKSTATE(); | ||||
nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS; | NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NOOPENS; | ||||
/* | /* | ||||
* For each client... | * For each client... | ||||
*/ | */ | ||||
for (i = 0; i < nfsrv_clienthashsize; i++) { | 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) { | LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { | ||||
if (LIST_EMPTY(&stp->ls_open) && | if (LIST_EMPTY(&stp->ls_open) && | ||||
(stp->ls_noopens > NFSNOOPEN || | (stp->ls_noopens > NFSNOOPEN || | ||||
(nfsrv_openpluslock * 2) > | (nfsrv_openpluslock * 2) > | ||||
nfsrv_v4statelimit)) | nfsrv_v4statelimit)) | ||||
nfsrv_freeopenowner(stp, 0, p); | nfsrv_freeopenowner(stp, 0, p); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
NFSUNLOCKSTATE(); | NFSUNLOCKSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* This function checks to see if the credentials are the same. | * This function checks to see if the credentials are the same. | ||||
* The check for same credentials is needed for state management operations | * Returns 1 for not same, 0 otherwise. | ||||
* for NFSv4.0 where 1 is returned if not same, 0 is returned otherwise. | |||||
*/ | */ | ||||
static int | static int | ||||
nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp) | nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp) | ||||
{ | { | ||||
/* For NFSv4.1/4.2, SP4_NONE always allows this. */ | /* For NFSv4.1/4.2, SP4_NONE always allows this. */ | ||||
if ((nd->nd_flag & ND_NFSV41) != 0) | if ((nd->nd_flag & ND_NFSV41) != 0) | ||||
return (0); | return (0); | ||||
Show All 28 Lines | |||||
/* | /* | ||||
* Calculate the lease expiry time. | * Calculate the lease expiry time. | ||||
*/ | */ | ||||
static time_t | static time_t | ||||
nfsrv_leaseexpiry(void) | 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 + 2 * (nfsrv_lease + NFSRV_LEASEDELTA)); | ||||
return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA); | return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA); | ||||
} | } | ||||
/* | /* | ||||
* Delay the delegation timeout as far as ls_delegtimelimit, as required. | * Delay the delegation timeout as far as ls_delegtimelimit, as required. | ||||
*/ | */ | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 304 Lines • ▼ Show 20 Lines | nfsrv_throwawayallstate(NFSPROC_T *p) | ||||
struct nfsclient *clp, *nclp; | struct nfsclient *clp, *nclp; | ||||
struct nfslockfile *lfp, *nlfp; | struct nfslockfile *lfp, *nlfp; | ||||
int i; | int i; | ||||
/* | /* | ||||
* For each client, clean out the state and then free the structure. | * For each client, clean out the state and then free the structure. | ||||
*/ | */ | ||||
for (i = 0; i < nfsrv_clienthashsize; i++) { | 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_cleanclient(clp, p); | ||||
nfsrv_freedeleglist(&clp->lc_deleg); | nfsrv_freedeleglist(&clp->lc_deleg); | ||||
nfsrv_freedeleglist(&clp->lc_olddeleg); | nfsrv_freedeleglist(&clp->lc_olddeleg); | ||||
free(clp->lc_stateid, M_NFSDCLIENT); | free(clp->lc_stateid, M_NFSDCLIENT); | ||||
free(clp, M_NFSDCLIENT); | free(clp, M_NFSDCLIENT); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Also, free up any remaining lock file structures. | * Also, free up any remaining lock file structures. | ||||
*/ | */ | ||||
for (i = 0; i < nfsrv_lockhashsize; i++) { | 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"); | printf("nfsd unload: fnd a lock file struct\n"); | ||||
nfsrv_freenfslockfile(lfp); | nfsrv_freenfslockfile(lfp); | ||||
} | } | ||||
} | } | ||||
/* And get rid of the deviceid structures and layouts. */ | /* And get rid of the deviceid structures and layouts. */ | ||||
nfsrv_freealllayoutsanddevids(); | nfsrv_freealllayoutsanddevids(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | #ifdef INET6 | ||||
struct sockaddr_in6 *sin6; | struct sockaddr_in6 *sin6; | ||||
#endif | #endif | ||||
shp = NFSSESSIONHASH(nd->nd_sessionid); | shp = NFSSESSIONHASH(nd->nd_sessionid); | ||||
NFSLOCKSESSION(shp); | NFSLOCKSESSION(shp); | ||||
sep = nfsrv_findsession(nd->nd_sessionid); | sep = nfsrv_findsession(nd->nd_sessionid); | ||||
if (sep == NULL) { | if (sep == NULL) { | ||||
NFSUNLOCKSESSION(shp); | 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); | buf = malloc(INET6_ADDRSTRLEN, M_TEMP, M_WAITOK); | ||||
switch (nd->nd_nam->sa_family) { | switch (nd->nd_nam->sa_family) { | ||||
#ifdef INET | #ifdef INET | ||||
case AF_INET: | case AF_INET: | ||||
sin = (struct sockaddr_in *)nd->nd_nam; | sin = (struct sockaddr_in *)nd->nd_nam; | ||||
cp = inet_ntop(sin->sin_family, | cp = inet_ntop(sin->sin_family, | ||||
&sin->sin_addr.s_addr, buf, | &sin->sin_addr.s_addr, buf, | ||||
INET6_ADDRSTRLEN); | INET6_ADDRSTRLEN); | ||||
▲ Show 20 Lines • Show All 345 Lines • ▼ Show 20 Lines | |||||
nfsrv_freeallbackchannel_xprts(void) | nfsrv_freeallbackchannel_xprts(void) | ||||
{ | { | ||||
struct nfsdsession *sep; | struct nfsdsession *sep; | ||||
struct nfsclient *clp; | struct nfsclient *clp; | ||||
SVCXPRT *xprt; | SVCXPRT *xprt; | ||||
int i; | int i; | ||||
for (i = 0; i < nfsrv_clienthashsize; 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) { | LIST_FOREACH(sep, &clp->lc_session, sess_list) { | ||||
xprt = sep->sess_cbsess.nfsess_xprt; | xprt = sep->sess_cbsess.nfsess_xprt; | ||||
sep->sess_cbsess.nfsess_xprt = NULL; | sep->sess_cbsess.nfsess_xprt = NULL; | ||||
if (xprt != NULL) | if (xprt != NULL) | ||||
SVC_RELEASE(xprt); | SVC_RELEASE(xprt); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 699 Lines • ▼ Show 20 Lines | if (nlyp != NULL) { | ||||
stateidp->other[2] = nlyp->lay_stateid.other[2]; | stateidp->other[2] = nlyp->lay_stateid.other[2]; | ||||
NFSUNLOCKLAYOUT(lhyp); | NFSUNLOCKLAYOUT(lhyp); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* Insert the new layout in the lists. */ | /* Insert the new layout in the lists. */ | ||||
*lypp = NULL; | *lypp = NULL; | ||||
atomic_add_int(&nfsrv_layoutcnt, 1); | atomic_add_int(&nfsrv_layoutcnt, 1); | ||||
nfsstatsv1.srvlayouts++; | NFSDSTATS()->srvlayouts++; | ||||
NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen); | NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen); | ||||
*layoutlenp = lyp->lay_layoutlen; | *layoutlenp = lyp->lay_layoutlen; | ||||
TAILQ_INSERT_HEAD(&lhyp->list, lyp, lay_list); | TAILQ_INSERT_HEAD(&lhyp->list, lyp, lay_list); | ||||
NFSUNLOCKLAYOUT(lhyp); | NFSUNLOCKLAYOUT(lhyp); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
* Free up a layout. | * Free up a layout. | ||||
*/ | */ | ||||
static void | static void | ||||
nfsrv_freelayout(struct nfslayouthead *lhp, struct nfslayout *lyp) | nfsrv_freelayout(struct nfslayouthead *lhp, struct nfslayout *lyp) | ||||
{ | { | ||||
NFSD_DEBUG(4, "Freelayout=%p\n", lyp); | NFSD_DEBUG(4, "Freelayout=%p\n", lyp); | ||||
atomic_add_int(&nfsrv_layoutcnt, -1); | atomic_add_int(&nfsrv_layoutcnt, -1); | ||||
nfsstatsv1.srvlayouts--; | NFSDSTATS()->srvlayouts--; | ||||
TAILQ_REMOVE(lhp, lyp, lay_list); | TAILQ_REMOVE(lhp, lyp, lay_list); | ||||
free(lyp, M_NFSDSTATE); | free(lyp, M_NFSDSTATE); | ||||
} | } | ||||
/* | /* | ||||
* Free up a device id. | * Free up a device id. | ||||
*/ | */ | ||||
void | void | ||||
▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | nfsrv_setdsserver(char *dspathp, char *mdspathp, NFSPROC_T *p, | ||||
struct nfsdevice *ds; | struct nfsdevice *ds; | ||||
struct mount *mp; | struct mount *mp; | ||||
int error, i; | int error, i; | ||||
char *dsdirpath; | char *dsdirpath; | ||||
size_t dsdirsize; | size_t dsdirsize; | ||||
NFSD_DEBUG(4, "setdssrv path=%s\n", dspathp); | NFSD_DEBUG(4, "setdssrv path=%s\n", dspathp); | ||||
*dsp = NULL; | *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, | NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE, | ||||
dspathp); | dspathp); | ||||
error = namei(&nd); | error = namei(&nd); | ||||
NFSD_DEBUG(4, "lookup=%d\n", error); | NFSD_DEBUG(4, "lookup=%d\n", error); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
if (nd.ni_vp->v_type != VDIR) { | if (nd.ni_vp->v_type != VDIR) { | ||||
vput(nd.ni_vp); | vput(nd.ni_vp); | ||||
▲ Show 20 Lines • Show All 1,173 Lines • Show Last 20 Lines |