mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
nfsd: Fix delegation handled for atomic upgrade
For NFSv4.1/4.2, an atomic upgrade of a delegation from a read delegation to a write delegation is allowed and can result in signoficantly improved performance. This patch adds support for this atomic upgrade, plus fixes a couple of other delegation related bugs. Since there were three cases where delegations were being issued, the patch factors this out into a separate function called nfsrv_issuedelegations(). This patch should only affect the NFSv4.1/4.2 behaviour when delegations are enabled, which is not the default. MFC after: 1 month
This commit is contained in:
parent
871b33ad65
commit
e2c9fad2e0
|
@ -3244,6 +3244,13 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
|
|||
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(NFSV4OPEN_RESOURCE);
|
||||
*tl = newnfs_false;
|
||||
} else if ((rflags &
|
||||
NFSV4OPEN_WDNOTSUPPDOWNGRADE) != 0) {
|
||||
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(NFSV4OPEN_NOTSUPPDOWNGRADE);
|
||||
} else if ((rflags & NFSV4OPEN_WDNOTSUPPUPGRADE) != 0) {
|
||||
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(NFSV4OPEN_NOTSUPPUPGRADE);
|
||||
} else {
|
||||
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(NFSV4OPEN_NOTWANTED);
|
||||
|
|
|
@ -240,6 +240,11 @@ static int nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf,
|
|||
static struct nfsdevice *nfsrv_findmirroredds(struct nfsmount *nmp);
|
||||
static int nfsrv_checkmachcred(int op, struct nfsrv_descript *nd,
|
||||
struct nfsclient *clp);
|
||||
static void nfsrv_issuedelegation(struct vnode *vp, struct nfsclient *clp,
|
||||
struct nfsrv_descript *nd, int delegate, int writedeleg, int readonly,
|
||||
u_quad_t filerev, uint64_t rdonly, struct nfsstate **new_delegp,
|
||||
struct nfsstate *new_stp, struct nfslockfile *lfp, uint32_t *rflagsp,
|
||||
nfsv4stateid_t *delegstateidp);
|
||||
|
||||
/*
|
||||
* Scan the client list for a match and either return the current one,
|
||||
|
@ -442,7 +447,8 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
|
|||
/*
|
||||
* If the verifier has changed, the client has rebooted
|
||||
* and a new client id is issued. The old state info
|
||||
* can be thrown away once the SETCLIENTID_CONFIRM occurs.
|
||||
* can be thrown away once the SetClientID_Confirm or
|
||||
* Create_Session that confirms the clientid occurs.
|
||||
*/
|
||||
LIST_REMOVE(clp, lc_hash);
|
||||
|
||||
|
@ -2648,6 +2654,8 @@ nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
|
|||
* considered a conflict since the client with a read delegation
|
||||
* could have done an Open with ReadAccess and WriteDeny
|
||||
* locally and then not have checked for the WriteDeny.)
|
||||
* The exception is a NFSv4.1/4.2 client that has requested
|
||||
* an atomic upgrade to a write delegation.
|
||||
* Don't check for a Reclaim, since that will be dealt with
|
||||
* by nfsrv_openctrl().
|
||||
*/
|
||||
|
@ -2657,9 +2665,10 @@ nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
|
|||
while (stp != LIST_END(&lfp->lf_deleg)) {
|
||||
nstp = LIST_NEXT(stp, ls_file);
|
||||
if ((readonly && stp->ls_clp != clp &&
|
||||
(stp->ls_flags & NFSLCK_DELEGWRITE)) ||
|
||||
(stp->ls_flags & NFSLCK_DELEGWRITE) != 0) ||
|
||||
(!readonly && (stp->ls_clp != clp ||
|
||||
(stp->ls_flags & NFSLCK_DELEGREAD)))) {
|
||||
((stp->ls_flags & NFSLCK_DELEGREAD) != 0 &&
|
||||
(new_stp->ls_flags & NFSLCK_WANTWDELEG) == 0)))) {
|
||||
ret = nfsrv_delegconflict(stp, &haslock, p, vp);
|
||||
if (ret) {
|
||||
/*
|
||||
|
@ -2944,6 +2953,8 @@ nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
|
|||
* considered a conflict since the client with a read delegation
|
||||
* could have done an Open with ReadAccess and WriteDeny
|
||||
* locally and then not have checked for the WriteDeny.)
|
||||
* The exception is a NFSv4.1/4.2 client that has requested
|
||||
* an atomic upgrade to a write delegation.
|
||||
*/
|
||||
if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) {
|
||||
stp = LIST_FIRST(&lfp->lf_deleg);
|
||||
|
@ -2951,12 +2962,15 @@ nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
|
|||
nstp = LIST_NEXT(stp, ls_file);
|
||||
if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD))
|
||||
writedeleg = 0;
|
||||
else
|
||||
else if (stp->ls_clp != clp ||
|
||||
(stp->ls_flags & NFSLCK_DELEGWRITE) != 0 ||
|
||||
(new_stp->ls_flags & NFSLCK_WANTWDELEG) == 0)
|
||||
delegate = 0;
|
||||
if ((readonly && stp->ls_clp != clp &&
|
||||
(stp->ls_flags & NFSLCK_DELEGWRITE)) ||
|
||||
(stp->ls_flags & NFSLCK_DELEGWRITE) != 0) ||
|
||||
(!readonly && (stp->ls_clp != clp ||
|
||||
(stp->ls_flags & NFSLCK_DELEGREAD)))) {
|
||||
((stp->ls_flags & NFSLCK_DELEGREAD) != 0 &&
|
||||
(new_stp->ls_flags & NFSLCK_WANTWDELEG) == 0)))) {
|
||||
if (new_stp->ls_flags & NFSLCK_RECLAIM) {
|
||||
delegate = 2;
|
||||
} else {
|
||||
|
@ -3204,47 +3218,9 @@ nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
|
|||
/*
|
||||
* This is where we can choose to issue a delegation.
|
||||
*/
|
||||
if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
|
||||
*rflagsp |= NFSV4OPEN_WDNOTWANTED;
|
||||
else if (nfsrv_issuedelegs == 0)
|
||||
*rflagsp |= NFSV4OPEN_WDSUPPFTYPE;
|
||||
else if (NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
|
||||
*rflagsp |= NFSV4OPEN_WDRESOURCE;
|
||||
else if (delegate == 0 || writedeleg == 0 ||
|
||||
NFSVNO_EXRDONLY(exp) || (readonly != 0 &&
|
||||
nfsrv_writedelegifpos == 0) ||
|
||||
!NFSVNO_DELEGOK(vp) ||
|
||||
(new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 ||
|
||||
(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
|
||||
LCL_CALLBACKSON)
|
||||
*rflagsp |= NFSV4OPEN_WDCONTENTION;
|
||||
else {
|
||||
new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
|
||||
new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
|
||||
= clp->lc_clientid.lval[0];
|
||||
new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
|
||||
= clp->lc_clientid.lval[1];
|
||||
new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
|
||||
= nfsrv_nextstateindex(clp);
|
||||
new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
|
||||
NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
|
||||
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
|
||||
new_deleg->ls_uid = new_stp->ls_uid;
|
||||
new_deleg->ls_lfp = lfp;
|
||||
new_deleg->ls_clp = clp;
|
||||
new_deleg->ls_filerev = filerev;
|
||||
new_deleg->ls_compref = nd->nd_compref;
|
||||
new_deleg->ls_lastrecall = 0;
|
||||
nfsrv_writedelegcnt++;
|
||||
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
|
||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp,
|
||||
new_deleg->ls_stateid), new_deleg, ls_hash);
|
||||
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
|
||||
new_deleg = NULL;
|
||||
NFSD_VNET(nfsstatsv1_p)->srvdelegates++;
|
||||
nfsrv_openpluslock++;
|
||||
nfsrv_delegatecnt++;
|
||||
}
|
||||
nfsrv_issuedelegation(vp, clp, nd, delegate, writedeleg,
|
||||
readonly, filerev, NFSVNO_EXRDONLY(exp), &new_deleg,
|
||||
new_stp, lfp, rflagsp, delegstateidp);
|
||||
} else {
|
||||
new_open->ls_stateid.seqid = 1;
|
||||
new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
|
||||
|
@ -3269,52 +3245,9 @@ nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
|
|||
/*
|
||||
* This is where we can choose to issue a delegation.
|
||||
*/
|
||||
if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
|
||||
*rflagsp |= NFSV4OPEN_WDNOTWANTED;
|
||||
else if (nfsrv_issuedelegs == 0)
|
||||
*rflagsp |= NFSV4OPEN_WDSUPPFTYPE;
|
||||
else if (NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
|
||||
*rflagsp |= NFSV4OPEN_WDRESOURCE;
|
||||
else if (delegate == 0 || (writedeleg == 0 &&
|
||||
readonly == 0) || !NFSVNO_DELEGOK(vp) ||
|
||||
(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
|
||||
LCL_CALLBACKSON)
|
||||
*rflagsp |= NFSV4OPEN_WDCONTENTION;
|
||||
else {
|
||||
new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
|
||||
new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
|
||||
= clp->lc_clientid.lval[0];
|
||||
new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
|
||||
= clp->lc_clientid.lval[1];
|
||||
new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
|
||||
= nfsrv_nextstateindex(clp);
|
||||
if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
|
||||
(nfsrv_writedelegifpos || !readonly) &&
|
||||
(new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) {
|
||||
new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
|
||||
NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
|
||||
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
|
||||
nfsrv_writedelegcnt++;
|
||||
} else {
|
||||
new_deleg->ls_flags = (NFSLCK_DELEGREAD |
|
||||
NFSLCK_READACCESS);
|
||||
*rflagsp |= NFSV4OPEN_READDELEGATE;
|
||||
}
|
||||
new_deleg->ls_uid = new_stp->ls_uid;
|
||||
new_deleg->ls_lfp = lfp;
|
||||
new_deleg->ls_clp = clp;
|
||||
new_deleg->ls_filerev = filerev;
|
||||
new_deleg->ls_compref = nd->nd_compref;
|
||||
new_deleg->ls_lastrecall = 0;
|
||||
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
|
||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp,
|
||||
new_deleg->ls_stateid), new_deleg, ls_hash);
|
||||
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
|
||||
new_deleg = NULL;
|
||||
NFSD_VNET(nfsstatsv1_p)->srvdelegates++;
|
||||
nfsrv_openpluslock++;
|
||||
nfsrv_delegatecnt++;
|
||||
}
|
||||
nfsrv_issuedelegation(vp, clp, nd, delegate, writedeleg,
|
||||
readonly, filerev, NFSVNO_EXRDONLY(exp), &new_deleg,
|
||||
new_stp, lfp, rflagsp, delegstateidp);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -3337,78 +3270,28 @@ nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
|
|||
if (new_stp->ls_flags & NFSLCK_RECLAIM) {
|
||||
new_stp->ls_flags = 0;
|
||||
} else if ((nd->nd_flag & ND_NFSV41) != 0) {
|
||||
/* NFSv4.1 never needs confirmation. */
|
||||
new_stp->ls_flags = 0;
|
||||
/*
|
||||
* This is where we can choose to issue a delegation.
|
||||
*/
|
||||
nfsrv_issuedelegation(vp, clp, nd, delegate, writedeleg,
|
||||
readonly, filerev, NFSVNO_EXRDONLY(exp), &new_deleg,
|
||||
new_stp, lfp, rflagsp, delegstateidp);
|
||||
/* NFSv4.1 never needs confirmation. */
|
||||
new_stp->ls_flags = 0;
|
||||
|
||||
/*
|
||||
* This is where we can choose to issue a delegation.
|
||||
*/
|
||||
if (delegate && nfsrv_issuedelegs &&
|
||||
(writedeleg || readonly) &&
|
||||
(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) ==
|
||||
LCL_CALLBACKSON &&
|
||||
!NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) &&
|
||||
NFSVNO_DELEGOK(vp) &&
|
||||
((nd->nd_flag & ND_NFSV41) == 0 ||
|
||||
(new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) {
|
||||
new_deleg->ls_stateid.seqid =
|
||||
delegstateidp->seqid = 1;
|
||||
new_deleg->ls_stateid.other[0] =
|
||||
delegstateidp->other[0]
|
||||
= clp->lc_clientid.lval[0];
|
||||
new_deleg->ls_stateid.other[1] =
|
||||
delegstateidp->other[1]
|
||||
= clp->lc_clientid.lval[1];
|
||||
new_deleg->ls_stateid.other[2] =
|
||||
delegstateidp->other[2]
|
||||
= nfsrv_nextstateindex(clp);
|
||||
if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
|
||||
(nfsrv_writedelegifpos || !readonly) &&
|
||||
((nd->nd_flag & ND_NFSV41) == 0 ||
|
||||
(new_stp->ls_flags & NFSLCK_WANTRDELEG) ==
|
||||
0)) {
|
||||
new_deleg->ls_flags =
|
||||
(NFSLCK_DELEGWRITE |
|
||||
NFSLCK_READACCESS |
|
||||
NFSLCK_WRITEACCESS);
|
||||
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
|
||||
nfsrv_writedelegcnt++;
|
||||
} else {
|
||||
new_deleg->ls_flags =
|
||||
(NFSLCK_DELEGREAD |
|
||||
NFSLCK_READACCESS);
|
||||
*rflagsp |= NFSV4OPEN_READDELEGATE;
|
||||
}
|
||||
new_deleg->ls_uid = new_stp->ls_uid;
|
||||
new_deleg->ls_lfp = lfp;
|
||||
new_deleg->ls_clp = clp;
|
||||
new_deleg->ls_filerev = filerev;
|
||||
new_deleg->ls_compref = nd->nd_compref;
|
||||
new_deleg->ls_lastrecall = 0;
|
||||
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg,
|
||||
ls_file);
|
||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp,
|
||||
new_deleg->ls_stateid), new_deleg, ls_hash);
|
||||
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg,
|
||||
ls_list);
|
||||
new_deleg = NULL;
|
||||
NFSD_VNET(nfsstatsv1_p)->srvdelegates++;
|
||||
nfsrv_openpluslock++;
|
||||
nfsrv_delegatecnt++;
|
||||
}
|
||||
/*
|
||||
* Since NFSv4.1 never does an OpenConfirm, the first
|
||||
* open state will be acquired here.
|
||||
*/
|
||||
if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
|
||||
clp->lc_flags |= LCL_STAMPEDSTABLE;
|
||||
len = clp->lc_idlen;
|
||||
NFSBCOPY(clp->lc_id, clidp, len);
|
||||
gotstate = 1;
|
||||
}
|
||||
/*
|
||||
* Since NFSv4.1 never does an OpenConfirm, the first
|
||||
* open state will be acquired here.
|
||||
*/
|
||||
if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
|
||||
clp->lc_flags |= LCL_STAMPEDSTABLE;
|
||||
len = clp->lc_idlen;
|
||||
NFSBCOPY(clp->lc_id, clidp, len);
|
||||
gotstate = 1;
|
||||
}
|
||||
} else {
|
||||
*rflagsp |= NFSV4OPEN_RESULTCONFIRM;
|
||||
new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
|
||||
*rflagsp |= NFSV4OPEN_RESULTCONFIRM;
|
||||
new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
|
||||
}
|
||||
nfsrvd_refcache(new_stp->ls_op);
|
||||
new_stp->ls_noopens = 0;
|
||||
|
@ -5179,6 +5062,11 @@ nfsrv_markreclaim(struct nfsclient *clp)
|
|||
* Now, just set the flag.
|
||||
*/
|
||||
sp->nst_flag |= NFSNST_RECLAIMED;
|
||||
|
||||
/*
|
||||
* Free up any old delegations.
|
||||
*/
|
||||
nfsrv_freedeleglist(&clp->lc_olddeleg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8943,3 +8831,86 @@ nfsrv_checkmachcred(int op, struct nfsrv_descript *nd, struct nfsclient *clp)
|
|||
return (0);
|
||||
return (NFSERR_AUTHERR | AUTH_TOOWEAK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue a delegation and, optionally set rflagsp for why not.
|
||||
*/
|
||||
static void
|
||||
nfsrv_issuedelegation(struct vnode *vp, struct nfsclient *clp,
|
||||
struct nfsrv_descript *nd, int delegate, int writedeleg, int readonly,
|
||||
u_quad_t filerev, uint64_t rdonly, struct nfsstate **new_delegp,
|
||||
struct nfsstate *new_stp, struct nfslockfile *lfp, uint32_t *rflagsp,
|
||||
nfsv4stateid_t *delegstateidp)
|
||||
{
|
||||
struct nfsstate *up_deleg, *new_deleg;
|
||||
|
||||
new_deleg = *new_delegp;
|
||||
up_deleg = LIST_FIRST(&lfp->lf_deleg);
|
||||
if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
|
||||
*rflagsp |= NFSV4OPEN_WDNOTWANTED;
|
||||
else if (nfsrv_issuedelegs == 0)
|
||||
*rflagsp |= NFSV4OPEN_WDSUPPFTYPE;
|
||||
else if (NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
|
||||
*rflagsp |= NFSV4OPEN_WDRESOURCE;
|
||||
else if (delegate == 0 || !NFSVNO_DELEGOK(vp) ||
|
||||
(writedeleg == 0 && (readonly == 0 ||
|
||||
(new_stp->ls_flags & NFSLCK_WANTWDELEG) != 0)) ||
|
||||
(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
|
||||
LCL_CALLBACKSON) {
|
||||
/* Is this a downgrade attempt? */
|
||||
if (up_deleg != NULL && up_deleg->ls_clp == clp &&
|
||||
(up_deleg->ls_flags & NFSLCK_DELEGWRITE) != 0 &&
|
||||
(new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0)
|
||||
*rflagsp |= NFSV4OPEN_WDNOTSUPPDOWNGRADE;
|
||||
else
|
||||
*rflagsp |= NFSV4OPEN_WDCONTENTION;
|
||||
} else if (up_deleg != NULL &&
|
||||
(up_deleg->ls_flags & NFSLCK_DELEGREAD) != 0 &&
|
||||
(new_stp->ls_flags & NFSLCK_WANTWDELEG) != 0) {
|
||||
/* This is an atomic upgrade. */
|
||||
up_deleg->ls_stateid.seqid++;
|
||||
delegstateidp->seqid = up_deleg->ls_stateid.seqid;
|
||||
delegstateidp->other[0] = up_deleg->ls_stateid.other[0];
|
||||
delegstateidp->other[1] = up_deleg->ls_stateid.other[1];
|
||||
delegstateidp->other[2] = up_deleg->ls_stateid.other[2];
|
||||
up_deleg->ls_flags = (NFSLCK_DELEGWRITE |
|
||||
NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
|
||||
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
|
||||
nfsrv_writedelegcnt++;
|
||||
} else {
|
||||
new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
|
||||
new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
|
||||
= clp->lc_clientid.lval[0];
|
||||
new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
|
||||
= clp->lc_clientid.lval[1];
|
||||
new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
|
||||
= nfsrv_nextstateindex(clp);
|
||||
if (writedeleg && !rdonly &&
|
||||
(nfsrv_writedelegifpos || !readonly) &&
|
||||
(new_stp->ls_flags & (NFSLCK_WANTRDELEG |
|
||||
NFSLCK_WANTWDELEG)) != NFSLCK_WANTRDELEG) {
|
||||
new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
|
||||
NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
|
||||
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
|
||||
nfsrv_writedelegcnt++;
|
||||
} else {
|
||||
new_deleg->ls_flags = (NFSLCK_DELEGREAD |
|
||||
NFSLCK_READACCESS);
|
||||
*rflagsp |= NFSV4OPEN_READDELEGATE;
|
||||
}
|
||||
new_deleg->ls_uid = new_stp->ls_uid;
|
||||
new_deleg->ls_lfp = lfp;
|
||||
new_deleg->ls_clp = clp;
|
||||
new_deleg->ls_filerev = filerev;
|
||||
new_deleg->ls_compref = nd->nd_compref;
|
||||
new_deleg->ls_lastrecall = 0;
|
||||
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
|
||||
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_deleg->ls_stateid),
|
||||
new_deleg, ls_hash);
|
||||
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
|
||||
*new_delegp = NULL;
|
||||
NFSD_VNET(nfsstatsv1_p)->srvdelegates++;
|
||||
nfsrv_openpluslock++;
|
||||
nfsrv_delegatecnt++;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue