res->sr_slotid = NFS4_MAX_SLOT_TABLE;
 }
 
-static void nfs41_sequence_done(struct nfs4_sequence_res *res)
+static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
 {
        unsigned long timestamp;
        struct nfs4_slot_table *tbl;
        struct nfs4_slot *slot;
+       struct nfs_client *clp;
 
        /*
         * sr_status remains 1 if an RPC level error occurred. The server
        if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
                goto out;
 
+       tbl = &res->sr_session->fc_slot_table;
+       slot = tbl->slots + res->sr_slotid;
+
        /* Check the SEQUENCE operation status */
-       if (res->sr_status == 0) {
-               struct nfs_client *clp = res->sr_session->clp;
-               tbl = &res->sr_session->fc_slot_table;
-               slot = tbl->slots + res->sr_slotid;
+       switch (res->sr_status) {
+       case 0:
                /* Update the slot's sequence and clientid lease timer */
                ++slot->seq_nr;
                timestamp = res->sr_renewal_time;
+               clp = res->sr_session->clp;
                spin_lock(&clp->cl_lock);
                if (time_before(clp->cl_last_renewal, timestamp))
                        clp->cl_last_renewal = timestamp;
                /* Check sequence flags */
                if (atomic_read(&clp->cl_count) > 1)
                        nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
+               break;
+       case -NFS4ERR_DELAY:
+               /* The server detected a resend of the RPC call and
+                * returned NFS4ERR_DELAY as per Section 2.10.6.2
+                * of RFC5661.
+                */
+               dprintk("%s: slot=%d seq=%d: Operation in progress\n",
+                               __func__, res->sr_slotid, slot->seq_nr);
+               goto out_retry;
+       default:
+               /* Just update the slot sequence no. */
+               ++slot->seq_nr;
        }
 out:
        /* The session may be reset by one of the error handlers. */
        dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
        nfs41_sequence_free_slot(res);
+       return 1;
+out_retry:
+       rpc_restart_call(task);
+       /* FIXME: rpc_restart_call() should be made to return success/fail */
+       if (task->tk_action == NULL)
+               goto out;
+       rpc_delay(task, NFS4_POLL_RETRY_MAX);
+       return 0;
 }
 
-static void nfs4_sequence_done(const struct nfs_server *server,
-                              struct nfs4_sequence_res *res, int rpc_status)
+static int nfs4_sequence_done(struct rpc_task *task,
+                              struct nfs4_sequence_res *res)
 {
-       if (res->sr_session != NULL)
-               nfs41_sequence_done(res);
+       if (res->sr_session == NULL)
+               return 1;
+       return nfs41_sequence_done(task, res);
 }
 
 /*
 {
        struct nfs41_call_sync_data *data = calldata;
 
-       nfs41_sequence_done(data->seq_res);
+       nfs41_sequence_done(task, data->seq_res);
 }
 
 struct rpc_call_ops nfs41_call_sync_ops = {
 }
 
 #else
-static void nfs4_sequence_done(const struct nfs_server *server,
-                              struct nfs4_sequence_res *res, int rpc_status)
+static int nfs4_sequence_done(struct rpc_task *task,
+                              struct nfs4_sequence_res *res)
 {
+       return 1;
 }
 #endif /* CONFIG_NFS_V4_1 */
 
 
        data->rpc_status = task->tk_status;
 
-       nfs4_sequence_done(data->o_arg.server, &data->o_res.seq_res,
-                       task->tk_status);
+       if (!nfs4_sequence_done(task, &data->o_res.seq_res))
+               return;
 
        if (RPC_ASSASSINATED(task))
                return;
        struct nfs4_state *state = calldata->state;
        struct nfs_server *server = NFS_SERVER(calldata->inode);
 
-       nfs4_sequence_done(server, &calldata->res.seq_res, task->tk_status);
+       if (!nfs4_sequence_done(task, &calldata->res.seq_res))
+               return;
        if (RPC_ASSASSINATED(task))
                return;
         /* hmm. we are done with the inode, and in the process of freeing
 {
        struct nfs_removeres *res = task->tk_msg.rpc_resp;
 
-       nfs4_sequence_done(res->server, &res->seq_res, task->tk_status);
+       if (!nfs4_sequence_done(task, &res->seq_res))
+               return 0;
        if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
                return 0;
        update_changeattr(dir, &res->cinfo);
 
        dprintk("--> %s\n", __func__);
 
-       nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
+       if (!nfs4_sequence_done(task, &data->res.seq_res))
+               return -EAGAIN;
 
        if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
                nfs_restart_rpc(task, server->nfs_client);
 {
        struct inode *inode = data->inode;
        
-       nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
-                          task->tk_status);
+       if (!nfs4_sequence_done(task, &data->res.seq_res))
+               return -EAGAIN;
 
        if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
                nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
 {
        struct inode *inode = data->inode;
        
-       nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
-                          task->tk_status);
+       if (!nfs4_sequence_done(task, &data->res.seq_res))
+               return -EAGAIN;
+
        if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
                nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
                return -EAGAIN;
 {
        struct nfs4_delegreturndata *data = calldata;
 
-       nfs4_sequence_done(data->res.server, &data->res.seq_res,
-                       task->tk_status);
+       if (!nfs4_sequence_done(task, &data->res.seq_res))
+               return;
 
        switch (task->tk_status) {
        case -NFS4ERR_STALE_STATEID:
 {
        struct nfs4_unlockdata *calldata = data;
 
-       nfs4_sequence_done(calldata->server, &calldata->res.seq_res,
-                          task->tk_status);
+       if (!nfs4_sequence_done(task, &calldata->res.seq_res))
+               return;
        if (RPC_ASSASSINATED(task))
                return;
        switch (task->tk_status) {
 
        dprintk("%s: begin!\n", __func__);
 
-       nfs4_sequence_done(data->server, &data->res.seq_res,
-                       task->tk_status);
+       if (!nfs4_sequence_done(task, &data->res.seq_res))
+               return;
 
        data->rpc_status = task->tk_status;
        if (RPC_ASSASSINATED(task))
                        (struct nfs4_get_lease_time_data *)calldata;
 
        dprintk("--> %s\n", __func__);
-       nfs41_sequence_done(&data->res->lr_seq_res);
+       if (!nfs41_sequence_done(task, &data->res->lr_seq_res))
+               return;
        switch (task->tk_status) {
        case -NFS4ERR_DELAY:
        case -NFS4ERR_GRACE:
        struct nfs4_sequence_data *calldata = data;
        struct nfs_client *clp = calldata->clp;
 
-       nfs41_sequence_done(task->tk_msg.rpc_resp);
+       if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp))
+               return;
 
        if (task->tk_status < 0) {
                dprintk("%s ERROR %d\n", __func__, task->tk_status);
        struct nfs4_sequence_res *res = &calldata->res.seq_res;
 
        dprintk("--> %s\n", __func__);
-       nfs41_sequence_done(res);
+       if (!nfs41_sequence_done(task, res))
+               return;
 
        if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) {
                rpc_restart_call_prepare(task);