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. --- 25-akpm/fs/nfsd/nfs4proc.c | 19 +++++++++++++++++++ 25-akpm/fs/nfsd/nfs4xdr.c | 1 + 25-akpm/include/linux/nfsd/state.h | 2 ++ 3 files changed, 22 insertions(+) diff -puN fs/nfsd/nfs4proc.c~knfsd-replaying-fixes fs/nfsd/nfs4proc.c --- 25/fs/nfsd/nfs4proc.c~knfsd-replaying-fixes Mon Feb 23 16:33:45 2004 +++ 25-akpm/fs/nfsd/nfs4proc.c Mon Feb 23 16:33:45 2004 @@ -89,6 +89,12 @@ do_open_lookup(struct svc_rqst *rqstp, s 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, struc /* 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 -puN fs/nfsd/nfs4xdr.c~knfsd-replaying-fixes fs/nfsd/nfs4xdr.c --- 25/fs/nfsd/nfs4xdr.c~knfsd-replaying-fixes Mon Feb 23 16:33:45 2004 +++ 25-akpm/fs/nfsd/nfs4xdr.c Mon Feb 23 16:33:45 2004 @@ -1913,6 +1913,7 @@ nfsd4_encode_open(struct nfsd4_compoundr default: BUG(); } + /* XXX save filehandle here */ ENCODE_SEQID_OP_TAIL(open->op_stateowner); } diff -puN include/linux/nfsd/state.h~knfsd-replaying-fixes include/linux/nfsd/state.h --- 25/include/linux/nfsd/state.h~knfsd-replaying-fixes Mon Feb 23 16:33:45 2004 +++ 25-akpm/include/linux/nfsd/state.h Mon Feb 23 16:33:45 2004 @@ -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]; }; _