res->sr_slot = NULL;
 }
 
+static void nfs4_slot_sequence_record_sent(struct nfs4_slot *slot,
+               u32 seqnr)
+{
+       if ((s32)(seqnr - slot->seq_nr_highest_sent) > 0)
+               slot->seq_nr_highest_sent = seqnr;
+}
+static void nfs4_slot_sequence_acked(struct nfs4_slot *slot,
+               u32 seqnr)
+{
+       slot->seq_nr_highest_sent = seqnr;
+       slot->seq_nr_last_acked = seqnr;
+}
+
 static int nfs41_sequence_process(struct rpc_task *task,
                struct nfs4_sequence_res *res)
 {
        struct nfs4_session *session;
        struct nfs4_slot *slot = res->sr_slot;
        struct nfs_client *clp;
-       bool interrupted = false;
        int ret = 1;
 
        if (slot == NULL)
 
        session = slot->table->session;
 
-       if (slot->interrupted) {
-               if (res->sr_status != -NFS4ERR_DELAY)
-                       slot->interrupted = 0;
-               interrupted = true;
-       }
-
        trace_nfs4_sequence_done(session, res);
        /* Check the SEQUENCE operation status */
        switch (res->sr_status) {
        case 0:
+               /* Mark this sequence number as having been acked */
+               nfs4_slot_sequence_acked(slot, slot->seq_nr);
                /* Update the slot's sequence and clientid lease timer */
                slot->seq_done = 1;
                clp = session->clp;
                 * 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;
+               nfs4_slot_sequence_record_sent(slot, slot->seq_nr);
+               slot->seq_done = 1;
                goto out;
        case -NFS4ERR_DELAY:
                /* The server detected a resend of the RPC call and
                        __func__,
                        slot->slot_nr,
                        slot->seq_nr);
+               nfs4_slot_sequence_acked(slot, slot->seq_nr);
                goto out_retry;
        case -NFS4ERR_RETRY_UNCACHED_REP:
        case -NFS4ERR_SEQ_FALSE_RETRY:
                 * The server thinks we tried to replay a request.
                 * Retry the call after bumping the sequence ID.
                 */
+               nfs4_slot_sequence_acked(slot, slot->seq_nr);
                goto retry_new_seq;
        case -NFS4ERR_BADSLOT:
                /*
                        goto session_recover;
                goto retry_nowait;
        case -NFS4ERR_SEQ_MISORDERED:
+               nfs4_slot_sequence_record_sent(slot, slot->seq_nr);
                /*
-                * Was the last operation on this sequence interrupted?
-                * If so, retry after bumping the sequence number.
+                * Were one or more calls using this slot interrupted?
+                * If the server never received the request, then our
+                * transmitted slot sequence number may be too high.
                 */
-               if (interrupted)
-                       goto retry_new_seq;
-               /*
-                * Could this slot have been previously retired?
-                * If so, then the server may be expecting seq_nr = 1!
-                */
-               if (slot->seq_nr != 1) {
-                       slot->seq_nr = 1;
+               if ((s32)(slot->seq_nr - slot->seq_nr_last_acked) > 1) {
+                       slot->seq_nr--;
                        goto retry_nowait;
                }
-               goto session_recover;
+               /*
+                * RFC5661:
+                * A retry might be sent while the original request is
+                * still in progress on the replier. The replier SHOULD
+                * deal with the issue by returning NFS4ERR_DELAY as the
+                * reply to SEQUENCE or CB_SEQUENCE operation, but
+                * implementations MAY return NFS4ERR_SEQ_MISORDERED.
+                *
+                * Restart the search after a delay.
+                */
+               slot->seq_nr = slot->seq_nr_highest_sent;
+               goto out_retry;
        default:
                /* Just update the slot sequence no. */
                slot->seq_done = 1;
        .rpc_call_done = nfs41_call_sync_done,
 };
 
-static void
-nfs4_sequence_process_interrupted(struct nfs_client *client,
-               struct nfs4_slot *slot, const struct cred *cred)
-{
-       struct rpc_task *task;
-
-       task = _nfs41_proc_sequence(client, cred, slot, true);
-       if (!IS_ERR(task))
-               rpc_put_task_async(task);
-}
-
 #else  /* !CONFIG_NFS_V4_1 */
 
 static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res)
 }
 EXPORT_SYMBOL_GPL(nfs4_sequence_done);
 
-static void
-nfs4_sequence_process_interrupted(struct nfs_client *client,
-               struct nfs4_slot *slot, const struct cred *cred)
-{
-       WARN_ON_ONCE(1);
-       slot->interrupted = 0;
-}
-
 #endif /* !CONFIG_NFS_V4_1 */
 
 static
                task->tk_timeout = 0;
        }
 
-       for (;;) {
-               spin_lock(&tbl->slot_tbl_lock);
-               /* The state manager will wait until the slot table is empty */
-               if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged)
-                       goto out_sleep;
-
-               slot = nfs4_alloc_slot(tbl);
-               if (IS_ERR(slot)) {
-                       /* Try again in 1/4 second */
-                       if (slot == ERR_PTR(-ENOMEM))
-                               task->tk_timeout = HZ >> 2;
-                       goto out_sleep;
-               }
-               spin_unlock(&tbl->slot_tbl_lock);
+       spin_lock(&tbl->slot_tbl_lock);
+       /* The state manager will wait until the slot table is empty */
+       if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged)
+               goto out_sleep;
 
-               if (likely(!slot->interrupted))
-                       break;
-               nfs4_sequence_process_interrupted(client,
-                               slot, task->tk_msg.rpc_cred);
+       slot = nfs4_alloc_slot(tbl);
+       if (IS_ERR(slot)) {
+               /* Try again in 1/4 second */
+               if (slot == ERR_PTR(-ENOMEM))
+                       task->tk_timeout = HZ >> 2;
+               goto out_sleep;
        }
+       spin_unlock(&tbl->slot_tbl_lock);
 
        nfs4_sequence_attach_slot(args, res, slot);