diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 32 | ||||
-rw-r--r-- | fs/nfs/nfs4session.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4session.h | 1 |
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 */ |