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. --- 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]; }; _