]> rtime.felk.cvut.cz Git - linux-imx.git/commitdiff
NFSv4.1: Deal effectively with interrupted RPC calls.
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Sat, 15 Dec 2012 20:36:07 +0000 (15:36 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Sat, 15 Dec 2012 20:39:59 +0000 (15:39 -0500)
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>
fs/nfs/nfs4proc.c
fs/nfs/nfs4session.c
fs/nfs/nfs4session.h

index afb428e63b52a7090efe24c19d160e007051ba70..493f0f41c5547d94eecf12de33bc8acf1545c2f7 100644 (file)
@@ -420,17 +420,9 @@ 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;
@@ -438,6 +430,11 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
        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:
@@ -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
@@ -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!
index 0e1cc1f4e51aa826aefb8f56e0fccdfeb0da86b3..ebda5f4a031b74d2c890d4c1e6cf932d869e8f2b 100644 (file)
@@ -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;
index d17b08091d4b809daf4325a9b80263d932586956..6f3cb39386d4e400d509e6526924fa0b5233ed74 100644 (file)
@@ -21,6 +21,7 @@ struct nfs4_slot {
        unsigned long           generation;
        u32                     slot_nr;
        u32                     seq_nr;
+       unsigned int            interrupted : 1;
 };
 
 /* Sessions */