Skip to content

Commit

Permalink
NFSv4.1: Deal effectively with interrupted RPC calls.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Dec 15, 2012
1 parent 8e63b6a commit ac20d16
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 9 deletions.
32 changes: 23 additions & 9 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,24 +420,21 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
struct nfs4_session *session;
struct nfs4_slot *slot;
struct nfs_client *clp;
bool interrupted = false;
int ret = 1;

/*
* sr_status remains 1 if an RPC level error occurred. The server
* may or may not have processed the sequence operation..
* Proceed as if the server received and processed the sequence
* operation.
*/
if (res->sr_status == 1)
res->sr_status = NFS_OK;

/* don't increment the sequence number if the task wasn't sent */
if (!RPC_WAS_SENT(task))
goto out;

slot = res->sr_slot;
session = slot->table->session;

if (slot->interrupted) {
slot->interrupted = 0;
interrupted = true;
}

/* Check the SEQUENCE operation status */
switch (res->sr_status) {
case 0:
Expand All @@ -450,6 +447,15 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
nfs4_schedule_lease_recovery(clp);
nfs41_update_target_slotid(slot->table, slot, res);
break;
case 1:
/*
* sr_status remains 1 if an RPC level error occurred.
* The server may or may not have processed the sequence
* operation..
* Mark the slot as having hosted an interrupted RPC call.
*/
slot->interrupted = 1;
goto out;
case -NFS4ERR_DELAY:
/* The server detected a resend of the RPC call and
* returned NFS4ERR_DELAY as per Section 2.10.6.2
Expand All @@ -467,6 +473,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
*/
goto retry_nowait;
case -NFS4ERR_SEQ_MISORDERED:
/*
* Was the last operation on this sequence interrupted?
* If so, retry after bumping the sequence number.
*/
if (interrupted) {
++slot->seq_nr;
goto retry_nowait;
}
/*
* Could this slot have been previously retired?
* If so, then the server may be expecting seq_nr = 1!
Expand Down
1 change: 1 addition & 0 deletions fs/nfs/nfs4session.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ static void nfs4_reset_slot_table(struct nfs4_slot_table *tbl,
p = &tbl->slots;
while (*p) {
(*p)->seq_nr = ivalue;
(*p)->interrupted = 0;
p = &(*p)->next;
}
tbl->highest_used_slotid = NFS4_NO_SLOT;
Expand Down
1 change: 1 addition & 0 deletions fs/nfs/nfs4session.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct nfs4_slot {
unsigned long generation;
u32 slot_nr;
u32 seq_nr;
unsigned int interrupted : 1;
};

/* Sessions */
Expand Down

0 comments on commit ac20d16

Please sign in to comment.