summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-02-26 06:46:54 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-02-26 06:46:54 -0800
commit9154e5fb6a0f3b670b41febe70308af11784ce8d (patch)
treed6baac1a515a1ffeb61d9d0e33bde5e7cb51f27d
parente997763aaaddd4f4b62397c2b8d88ca0514467db (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.c19
-rw-r--r--fs/nfsd/nfs4xdr.c1
-rw-r--r--include/linux/nfsd/state.h2
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(&current_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];
};