From 9154e5fb6a0f3b670b41febe70308af11784ce8d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 26 Feb 2004 06:46:54 -0800 Subject: [PATCH] [PATCH] kNFSd: NFSdV4 fixes for replaying open requests. From: NeilBrown Since the open op changes the current filehandle, we can't correctly replay compounds containing opens unless we save the filehandle resulting from the open as well as the encoded reply. --- fs/nfsd/nfs4proc.c | 19 +++++++++++++++++++ fs/nfsd/nfs4xdr.c | 1 + include/linux/nfsd/state.h | 2 ++ 3 files changed, 22 insertions(+) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index c9398a6531e43..a7c429b750ced 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -89,6 +89,12 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o if (!status) { set_change_info(&open->op_cinfo, current_fh); fh_dup2(current_fh, &resfh); + /* XXXJBF: keep a saved svc_fh struct instead?? */ + open->op_stateowner->so_replay.rp_openfh_len = + resfh.fh_handle.fh_size; + memcpy(open->op_stateowner->so_replay.rp_openfh, + &resfh.fh_handle.fh_base, + resfh.fh_handle.fh_size); accmode = MAY_NOP; if (open->op_share_access & NFS4_SHARE_ACCESS_READ) @@ -116,6 +122,19 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open /* check seqid for replay. set nfs4_owner */ status = nfsd4_process_open1(open); + if (status == NFSERR_REPLAY_ME) { + struct nfs4_replay *rp = &open->op_stateowner->so_replay; + fh_put(current_fh); + current_fh->fh_handle.fh_size = rp->rp_openfh_len; + memcpy(¤t_fh->fh_handle.fh_base, rp->rp_openfh, + rp->rp_openfh_len); + status = fh_verify(rqstp, current_fh, 0, MAY_NOP); + if (status) + dprintk("nfsd4_open: replay failed" + " restoring previous filehandle\n"); + else + status = NFSERR_REPLAY_ME; + } if (status) return status; /* diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 919141d7cbcf3..5ff917c855601 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1913,6 +1913,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open default: BUG(); } + /* XXX save filehandle here */ ENCODE_SEQID_OP_TAIL(open->op_stateowner); } diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h index b48b362015854..4fdd1d2e8c25d 100644 --- a/include/linux/nfsd/state.h +++ b/include/linux/nfsd/state.h @@ -113,6 +113,8 @@ struct nfs4_replay { unsigned int rp_buflen; char *rp_buf; unsigned intrp_allocated; + int rp_openfh_len; + char rp_openfh[NFS4_FHSIZE]; char rp_ibuf[NFSD4_REPLAY_ISIZE]; }; -- 2.53.0