aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorNeilBrown <neilb@cse.unsw.edu.au>2005-07-07 20:59:19 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-07 21:24:09 -0400
commitbd9aac523b812d58e644fde5e59f5697fb9e3822 (patch)
treea3adb8ac833a8e776cca8df91e96f85aa28e81c6 /fs/nfsd
parent893f87701c9e5bd5610dfbb3f8bf1135f86d85cb (diff)
[PATCH] nfsd4: fix open_reclaim seqid
The sequence number we store in the sequence id is the last one we received from the client. So on the next operation we'll check that the client gives us the next higher number. We increment sequence id's at the last moment, in encode, so that we're sure of knowing the right error return. (The decision to increment the sequence id depends on the exact error returned.) However on the *first* use of a sequence number, if we set the sequence number to the one received from the client and then let the increment happen on encode, we'll be left with a sequence number one to high. For that reason, ENCODE_SEQID_OP_TAIL only increments the sequence id on *confirmed* stateowners. This creates a problem for open reclaims, which are confirmed on first use. Therefore the open reclaim code, as a special exception, *decrements* the sequence id, cancelling out the undesired increment on encode. But this prevents the sequence id from ever being incremented in the case where multiple reclaims are sent with the same openowner. Yuch! We could add another exception to the open reclaim code, decrementing the sequence id only if this is the first use of the open owner. But it's simpler by far to modify the meaning of the op_seqid field: instead of representing the previous value sent by the client, we take op_seqid, after encoding, to represent the *next* sequence id that we expect from the client. This eliminates the need for special-case handling of the first use of a stateowner. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c15
-rw-r--r--fs/nfsd/nfs4xdr.c3
2 files changed, 7 insertions, 11 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 74cd9bf3e0a1..f60bcad77f71 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1483,7 +1483,7 @@ nfsd4_process_open1(struct nfsd4_open *open)
1483 if (sop) { 1483 if (sop) {
1484 open->op_stateowner = sop; 1484 open->op_stateowner = sop;
1485 /* check for replay */ 1485 /* check for replay */
1486 if (open->op_seqid == sop->so_seqid){ 1486 if (open->op_seqid == sop->so_seqid - 1){
1487 if (sop->so_replay.rp_buflen) 1487 if (sop->so_replay.rp_buflen)
1488 return NFSERR_REPLAY_ME; 1488 return NFSERR_REPLAY_ME;
1489 else { 1489 else {
@@ -1498,7 +1498,7 @@ nfsd4_process_open1(struct nfsd4_open *open)
1498 goto renew; 1498 goto renew;
1499 } 1499 }
1500 } else if (sop->so_confirmed) { 1500 } else if (sop->so_confirmed) {
1501 if (open->op_seqid == sop->so_seqid + 1) 1501 if (open->op_seqid == sop->so_seqid)
1502 goto renew; 1502 goto renew;
1503 status = nfserr_bad_seqid; 1503 status = nfserr_bad_seqid;
1504 goto out; 1504 goto out;
@@ -1684,13 +1684,11 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
1684} 1684}
1685 1685
1686 1686
1687/* decrement seqid on successful reclaim, it will be bumped in encode_open */
1688static void 1687static void
1689nfs4_set_claim_prev(struct nfsd4_open *open) 1688nfs4_set_claim_prev(struct nfsd4_open *open)
1690{ 1689{
1691 open->op_stateowner->so_confirmed = 1; 1690 open->op_stateowner->so_confirmed = 1;
1692 open->op_stateowner->so_client->cl_firststate = 1; 1691 open->op_stateowner->so_client->cl_firststate = 1;
1693 open->op_stateowner->so_seqid--;
1694} 1692}
1695 1693
1696/* 1694/*
@@ -2234,7 +2232,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
2234 * For the moment, we ignore the possibility of 2232 * For the moment, we ignore the possibility of
2235 * generation number wraparound. 2233 * generation number wraparound.
2236 */ 2234 */
2237 if (seqid != sop->so_seqid + 1) 2235 if (seqid != sop->so_seqid)
2238 goto check_replay; 2236 goto check_replay;
2239 2237
2240 if (sop->so_confirmed) { 2238 if (sop->so_confirmed) {
@@ -2280,12 +2278,12 @@ no_nfs4_stateid:
2280 *sopp = sop; 2278 *sopp = sop;
2281 2279
2282check_replay: 2280check_replay:
2283 if (seqid == sop->so_seqid) { 2281 if (seqid == sop->so_seqid - 1) {
2284 printk("NFSD: preprocess_seqid_op: retransmission?\n"); 2282 printk("NFSD: preprocess_seqid_op: retransmission?\n");
2285 /* indicate replay to calling function */ 2283 /* indicate replay to calling function */
2286 status = NFSERR_REPLAY_ME; 2284 status = NFSERR_REPLAY_ME;
2287 } else { 2285 } else {
2288 printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid); 2286 printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid, seqid);
2289 2287
2290 *sopp = NULL; 2288 *sopp = NULL;
2291 status = nfserr_bad_seqid; 2289 status = nfserr_bad_seqid;
@@ -2608,7 +2606,6 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
2608 * occured. 2606 * occured.
2609 * 2607 *
2610 * strhashval = lock_ownerstr_hashval 2608 * strhashval = lock_ownerstr_hashval
2611 * so_seqid = lock->lk_new_lock_seqid - 1: it gets bumped in encode
2612 */ 2609 */
2613 2610
2614static struct nfs4_stateowner * 2611static struct nfs4_stateowner *
@@ -2633,7 +2630,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2633 sop->so_is_open_owner = 0; 2630 sop->so_is_open_owner = 0;
2634 sop->so_id = current_ownerid++; 2631 sop->so_id = current_ownerid++;
2635 sop->so_client = clp; 2632 sop->so_client = clp;
2636 sop->so_seqid = lock->lk_new_lock_seqid - 1; 2633 sop->so_seqid = lock->lk_new_lock_seqid;
2637 sop->so_confirmed = 1; 2634 sop->so_confirmed = 1;
2638 rp = &sop->so_replay; 2635 rp = &sop->so_replay;
2639 rp->rp_status = NFSERR_SERVERFAULT; 2636 rp->rp_status = NFSERR_SERVERFAULT;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 91fb171d2ace..5207068cde1a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1218,8 +1218,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1218 1218
1219#define ENCODE_SEQID_OP_TAIL(stateowner) do { \ 1219#define ENCODE_SEQID_OP_TAIL(stateowner) do { \
1220 if (seqid_mutating_err(nfserr) && stateowner) { \ 1220 if (seqid_mutating_err(nfserr) && stateowner) { \
1221 if (stateowner->so_confirmed) \ 1221 stateowner->so_seqid++; \
1222 stateowner->so_seqid++; \
1223 stateowner->so_replay.rp_status = nfserr; \ 1222 stateowner->so_replay.rp_status = nfserr; \
1224 stateowner->so_replay.rp_buflen = \ 1223 stateowner->so_replay.rp_buflen = \
1225 (((char *)(resp)->p - (char *)save)); \ 1224 (((char *)(resp)->p - (char *)save)); \