aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-12-15 15:36:07 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-12-15 15:39:59 -0500
commitac20d163fccf9fa6acec8b68f127003635e13b72 (patch)
tree2424cf9b4a61b6889e484b35c6385d1bf1e03600
parent8e63b6a8adabb0551124c3b78f7f5f36912c3728 (diff)
NFSv4.1: Deal effectively with interrupted RPC calls.
If an RPC call is interrupted, assume that the server hasn't processed the RPC call so that the next time we use the slot, we know that if we get a NFS4ERR_SEQ_MISORDERED or NFS4ERR_SEQ_FALSE_RETRY, we just have to bump the sequence number. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4proc.c32
-rw-r--r--fs/nfs/nfs4session.c1
-rw-r--r--fs/nfs/nfs4session.h1
3 files changed, 25 insertions, 9 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index afb428e63b52..493f0f41c554 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -420,17 +420,9 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
420 struct nfs4_session *session; 420 struct nfs4_session *session;
421 struct nfs4_slot *slot; 421 struct nfs4_slot *slot;
422 struct nfs_client *clp; 422 struct nfs_client *clp;
423 bool interrupted = false;
423 int ret = 1; 424 int ret = 1;
424 425
425 /*
426 * sr_status remains 1 if an RPC level error occurred. The server
427 * may or may not have processed the sequence operation..
428 * Proceed as if the server received and processed the sequence
429 * operation.
430 */
431 if (res->sr_status == 1)
432 res->sr_status = NFS_OK;
433
434 /* don't increment the sequence number if the task wasn't sent */ 426 /* don't increment the sequence number if the task wasn't sent */
435 if (!RPC_WAS_SENT(task)) 427 if (!RPC_WAS_SENT(task))
436 goto out; 428 goto out;
@@ -438,6 +430,11 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
438 slot = res->sr_slot; 430 slot = res->sr_slot;
439 session = slot->table->session; 431 session = slot->table->session;
440 432
433 if (slot->interrupted) {
434 slot->interrupted = 0;
435 interrupted = true;
436 }
437
441 /* Check the SEQUENCE operation status */ 438 /* Check the SEQUENCE operation status */
442 switch (res->sr_status) { 439 switch (res->sr_status) {
443 case 0: 440 case 0:
@@ -450,6 +447,15 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
450 nfs4_schedule_lease_recovery(clp); 447 nfs4_schedule_lease_recovery(clp);
451 nfs41_update_target_slotid(slot->table, slot, res); 448 nfs41_update_target_slotid(slot->table, slot, res);
452 break; 449 break;
450 case 1:
451 /*
452 * sr_status remains 1 if an RPC level error occurred.
453 * The server may or may not have processed the sequence
454 * operation..
455 * Mark the slot as having hosted an interrupted RPC call.
456 */
457 slot->interrupted = 1;
458 goto out;
453 case -NFS4ERR_DELAY: 459 case -NFS4ERR_DELAY:
454 /* The server detected a resend of the RPC call and 460 /* The server detected a resend of the RPC call and
455 * returned NFS4ERR_DELAY as per Section 2.10.6.2 461 * returned NFS4ERR_DELAY as per Section 2.10.6.2
@@ -468,6 +474,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
468 goto retry_nowait; 474 goto retry_nowait;
469 case -NFS4ERR_SEQ_MISORDERED: 475 case -NFS4ERR_SEQ_MISORDERED:
470 /* 476 /*
477 * Was the last operation on this sequence interrupted?
478 * If so, retry after bumping the sequence number.
479 */
480 if (interrupted) {
481 ++slot->seq_nr;
482 goto retry_nowait;
483 }
484 /*
471 * Could this slot have been previously retired? 485 * Could this slot have been previously retired?
472 * If so, then the server may be expecting seq_nr = 1! 486 * If so, then the server may be expecting seq_nr = 1!
473 */ 487 */
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c
index 0e1cc1f4e51a..ebda5f4a031b 100644
--- a/fs/nfs/nfs4session.c
+++ b/fs/nfs/nfs4session.c
@@ -172,6 +172,7 @@ static void nfs4_reset_slot_table(struct nfs4_slot_table *tbl,
172 p = &tbl->slots; 172 p = &tbl->slots;
173 while (*p) { 173 while (*p) {
174 (*p)->seq_nr = ivalue; 174 (*p)->seq_nr = ivalue;
175 (*p)->interrupted = 0;
175 p = &(*p)->next; 176 p = &(*p)->next;
176 } 177 }
177 tbl->highest_used_slotid = NFS4_NO_SLOT; 178 tbl->highest_used_slotid = NFS4_NO_SLOT;
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
index d17b08091d4b..6f3cb39386d4 100644
--- a/fs/nfs/nfs4session.h
+++ b/fs/nfs/nfs4session.h
@@ -21,6 +21,7 @@ struct nfs4_slot {
21 unsigned long generation; 21 unsigned long generation;
22 u32 slot_nr; 22 u32 slot_nr;
23 u32 seq_nr; 23 u32 seq_nr;
24 unsigned int interrupted : 1;
24}; 25};
25 26
26/* Sessions */ 27/* Sessions */