static int _nfs4_proc_open(struct nfs4_opendata *data);
 static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
-static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
+static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *, long *);
 static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
 static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label);
 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
        kunmap_atomic(start);
 }
 
+static long nfs4_update_delay(long *timeout)
+{
+       long ret;
+       if (!timeout)
+               return NFS4_POLL_RETRY_MAX;
+       if (*timeout <= 0)
+               *timeout = NFS4_POLL_RETRY_MIN;
+       if (*timeout > NFS4_POLL_RETRY_MAX)
+               *timeout = NFS4_POLL_RETRY_MAX;
+       ret = *timeout;
+       *timeout <<= 1;
+       return ret;
+}
+
 static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
 {
        int res = 0;
 
        might_sleep();
 
-       if (*timeout <= 0)
-               *timeout = NFS4_POLL_RETRY_MIN;
-       if (*timeout > NFS4_POLL_RETRY_MAX)
-               *timeout = NFS4_POLL_RETRY_MAX;
-       freezable_schedule_timeout_killable_unsafe(*timeout);
+       freezable_schedule_timeout_killable_unsafe(
+               nfs4_update_delay(timeout));
        if (fatal_signal_pending(current))
                res = -ERESTARTSYS;
-       *timeout <<= 1;
        return res;
 }
 
                        if (calldata->arg.fmode == 0)
                                break;
                default:
-                       if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
+                       if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) {
                                rpc_restart_call_prepare(task);
                                goto out_release;
                        }
 
        if (!nfs4_sequence_done(task, &res->seq_res))
                return 0;
-       if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
+       if (nfs4_async_handle_error(task, res->server, NULL,
+                                   &data->timeout) == -EAGAIN)
                return 0;
        update_changeattr(dir, &res->cinfo);
        return 1;
 
        if (!nfs4_sequence_done(task, &res->seq_res))
                return 0;
-       if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
+       if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN)
                return 0;
 
        update_changeattr(old_dir, &res->old_cinfo);
 
        trace_nfs4_read(hdr, task->tk_status);
        if (nfs4_async_handle_error(task, server,
-                                   hdr->args.context->state) == -EAGAIN) {
+                                   hdr->args.context->state,
+                                   NULL) == -EAGAIN) {
                rpc_restart_call_prepare(task);
                return -EAGAIN;
        }
                              struct nfs_pgio_header *hdr)
 {
        struct inode *inode = hdr->inode;
-       
+
        trace_nfs4_write(hdr, task->tk_status);
        if (nfs4_async_handle_error(task, NFS_SERVER(inode),
-                                   hdr->args.context->state) == -EAGAIN) {
+                                   hdr->args.context->state,
+                                   NULL) == -EAGAIN) {
                rpc_restart_call_prepare(task);
                return -EAGAIN;
        }
        struct inode *inode = data->inode;
 
        trace_nfs4_commit(data, task->tk_status);
-       if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
+       if (nfs4_async_handle_error(task, NFS_SERVER(inode),
+                                   NULL, NULL) == -EAGAIN) {
                rpc_restart_call_prepare(task);
                return -EAGAIN;
        }
 
 
 static int
-nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
+nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
+                       struct nfs4_state *state, long *timeout)
 {
        struct nfs_client *clp = server->nfs_client;
 
 #endif /* CONFIG_NFS_V4_1 */
                case -NFS4ERR_DELAY:
                        nfs_inc_server_stats(server, NFSIOS_DELAY);
+                       rpc_delay(task, nfs4_update_delay(timeout));
+                       goto restart_call;
                case -NFS4ERR_GRACE:
                        rpc_delay(task, NFS4_POLL_RETRY_MAX);
                case -NFS4ERR_RETRY_UNCACHED_REP:
                        pnfs_roc_set_barrier(data->inode, data->roc_barrier);
                break;
        default:
-               if (nfs4_async_handle_error(task, data->res.server, NULL) ==
-                               -EAGAIN) {
+               if (nfs4_async_handle_error(task, data->res.server,
+                                           NULL, NULL) == -EAGAIN) {
                        rpc_restart_call_prepare(task);
                        return;
                }
                case -NFS4ERR_EXPIRED:
                        break;
                default:
-                       if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
+                       if (nfs4_async_handle_error(task, calldata->server,
+                                                   NULL, NULL) == -EAGAIN)
                                rpc_restart_call_prepare(task);
        }
        nfs_release_seqid(calldata->arg.seqid);
                break;
        case -NFS4ERR_LEASE_MOVED:
        case -NFS4ERR_DELAY:
-               if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN)
+               if (nfs4_async_handle_error(task, server,
+                                           NULL, NULL) == -EAGAIN)
                        rpc_restart_call_prepare(task);
        }
 }
                        rpc_restart_call_prepare(task);
                }
        }
-       if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
+       if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN)
                rpc_restart_call_prepare(task);
 out:
        dprintk("<-- %s\n", __func__);
        case 0:
                break;
        case -NFS4ERR_DELAY:
-               if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN)
+               if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
                        break;
                rpc_restart_call_prepare(task);
                return;
        case 0:
                break;
        default:
-               if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
+               if (nfs4_async_handle_error(task, server, NULL, NULL) == -EAGAIN) {
                        rpc_restart_call_prepare(task);
                        return;
                }
 
        switch (task->tk_status) {
        case -NFS4ERR_DELAY:
-               if (nfs4_async_handle_error(task, data->server, NULL) == -EAGAIN)
+               if (nfs4_async_handle_error(task, data->server, NULL, NULL) == -EAGAIN)
                        rpc_restart_call_prepare(task);
        }
 }