diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-02-26 06:46:54 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-02-26 06:46:54 -0800 |
| commit | 9154e5fb6a0f3b670b41febe70308af11784ce8d (patch) | |
| tree | d6baac1a515a1ffeb61d9d0e33bde5e7cb51f27d | |
| parent | e997763aaaddd4f4b62397c2b8d88ca0514467db (diff) | |
[PATCH] kNFSd: NFSdV4 fixes for replaying open requests.
From: NeilBrown <neilb@cse.unsw.edu.au>
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.
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 19 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 1 | ||||
| -rw-r--r-- | include/linux/nfsd/state.h | 2 |
3 files changed, 22 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index c9398a6531e4..a7c429b750ce 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 919141d7cbcf..5ff917c85560 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 b48b36201585..4fdd1d2e8c25 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]; }; |
