nfsd4: cleanup handling of nfsv4.0 closed stateid's
Closed stateid's are kept around a little while to handle close replays in the 4.0 case. So we stash them in the last-used stateid in the oo_last_closed_stateid field of the open owner. We can free that in encode_seqid_op_tail once the seqid on the open owner is next incremented. But we don't want to do that on the close itself; so we set NFS4_OO_PURGE_CLOSE flag set on the open owner, skip freeing it the first time through encode_seqid_op_tail, then when we see that flag set next time we free it. This is unnecessarily baroque. Instead, just move the logic that increments the seqid out of the xdr code and into the operation code itself. The justification given for the current placement is that we need to wait till the last minute to be sure we know whether the status is a sequence-id-mutating error or not, but examination of the code shows that can't actually happen. Reported-by: Yanchuan Nian <ycnian@gmail.com> Tested-by: Yanchuan Nian <ycnian@gmail.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
@@ -1701,28 +1701,6 @@ static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
|
||||
\
|
||||
save = resp->p;
|
||||
|
||||
/*
|
||||
* Routine for encoding the result of a "seqid-mutating" NFSv4 operation. This
|
||||
* is where sequence id's are incremented, and the replay cache is filled.
|
||||
* Note that we increment sequence id's here, at the last moment, so we're sure
|
||||
* we know whether the error to be returned is a sequence id mutating error.
|
||||
*/
|
||||
|
||||
static void encode_seqid_op_tail(struct nfsd4_compoundres *resp, __be32 *save, __be32 nfserr)
|
||||
{
|
||||
struct nfs4_stateowner *stateowner = resp->cstate.replay_owner;
|
||||
|
||||
if (seqid_mutating_err(ntohl(nfserr)) && stateowner) {
|
||||
stateowner->so_seqid++;
|
||||
stateowner->so_replay.rp_status = nfserr;
|
||||
stateowner->so_replay.rp_buflen =
|
||||
(char *)resp->p - (char *)save;
|
||||
memcpy(stateowner->so_replay.rp_buf, save,
|
||||
stateowner->so_replay.rp_buflen);
|
||||
nfsd4_purge_closed_stateid(stateowner);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode as an array of strings the string given with components
|
||||
* separated @sep, escaped with esc_enter and esc_exit.
|
||||
*/
|
||||
@@ -2667,7 +2645,6 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_c
|
||||
if (!nfserr)
|
||||
nfsd4_encode_stateid(resp, &close->cl_stateid);
|
||||
|
||||
encode_seqid_op_tail(resp, save, nfserr);
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
@@ -2770,7 +2747,6 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lo
|
||||
else if (nfserr == nfserr_denied)
|
||||
nfsd4_encode_lock_denied(resp, &lock->lk_denied);
|
||||
|
||||
encode_seqid_op_tail(resp, save, nfserr);
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
@@ -2790,7 +2766,6 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l
|
||||
if (!nfserr)
|
||||
nfsd4_encode_stateid(resp, &locku->lu_stateid);
|
||||
|
||||
encode_seqid_op_tail(resp, save, nfserr);
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
@@ -2885,7 +2860,6 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
|
||||
}
|
||||
/* XXX save filehandle here */
|
||||
out:
|
||||
encode_seqid_op_tail(resp, save, nfserr);
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
@@ -2897,7 +2871,6 @@ nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct
|
||||
if (!nfserr)
|
||||
nfsd4_encode_stateid(resp, &oc->oc_resp_stateid);
|
||||
|
||||
encode_seqid_op_tail(resp, save, nfserr);
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
@@ -2909,7 +2882,6 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struc
|
||||
if (!nfserr)
|
||||
nfsd4_encode_stateid(resp, &od->od_stateid);
|
||||
|
||||
encode_seqid_op_tail(resp, save, nfserr);
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
@@ -3567,6 +3539,7 @@ __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad)
|
||||
void
|
||||
nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
||||
{
|
||||
struct nfs4_stateowner *so = resp->cstate.replay_owner;
|
||||
__be32 *statp;
|
||||
__be32 *p;
|
||||
|
||||
@@ -3583,6 +3556,11 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
||||
/* nfsd4_check_drc_limit guarantees enough room for error status */
|
||||
if (!op->status)
|
||||
op->status = nfsd4_check_resp_size(resp, 0);
|
||||
if (so) {
|
||||
so->so_replay.rp_status = op->status;
|
||||
so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1);
|
||||
memcpy(so->so_replay.rp_buf, statp+1, so->so_replay.rp_buflen);
|
||||
}
|
||||
status:
|
||||
/*
|
||||
* Note: We write the status directly, instead of using WRITE32(),
|
||||
|
Reference in New Issue
Block a user