|
@@ -77,7 +77,7 @@ struct nfs4_opendata;
|
|
static int _nfs4_proc_open(struct nfs4_opendata *data);
|
|
static int _nfs4_proc_open(struct nfs4_opendata *data);
|
|
static int _nfs4_recover_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_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 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 *, 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);
|
|
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
|
|
@@ -314,20 +314,30 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
|
|
kunmap_atomic(start);
|
|
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)
|
|
static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
|
|
{
|
|
{
|
|
int res = 0;
|
|
int res = 0;
|
|
|
|
|
|
might_sleep();
|
|
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))
|
|
if (fatal_signal_pending(current))
|
|
res = -ERESTARTSYS;
|
|
res = -ERESTARTSYS;
|
|
- *timeout <<= 1;
|
|
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2583,7 +2593,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
|
|
if (calldata->arg.fmode == 0)
|
|
if (calldata->arg.fmode == 0)
|
|
break;
|
|
break;
|
|
default:
|
|
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);
|
|
rpc_restart_call_prepare(task);
|
|
goto out_release;
|
|
goto out_release;
|
|
}
|
|
}
|
|
@@ -3572,7 +3582,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
|
|
|
|
|
|
if (!nfs4_sequence_done(task, &res->seq_res))
|
|
if (!nfs4_sequence_done(task, &res->seq_res))
|
|
return 0;
|
|
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;
|
|
return 0;
|
|
update_changeattr(dir, &res->cinfo);
|
|
update_changeattr(dir, &res->cinfo);
|
|
return 1;
|
|
return 1;
|
|
@@ -3605,7 +3616,7 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
|
|
|
|
|
|
if (!nfs4_sequence_done(task, &res->seq_res))
|
|
if (!nfs4_sequence_done(task, &res->seq_res))
|
|
return 0;
|
|
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;
|
|
return 0;
|
|
|
|
|
|
update_changeattr(old_dir, &res->old_cinfo);
|
|
update_changeattr(old_dir, &res->old_cinfo);
|
|
@@ -4109,7 +4120,8 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_header *hdr)
|
|
|
|
|
|
trace_nfs4_read(hdr, task->tk_status);
|
|
trace_nfs4_read(hdr, task->tk_status);
|
|
if (nfs4_async_handle_error(task, server,
|
|
if (nfs4_async_handle_error(task, server,
|
|
- hdr->args.context->state) == -EAGAIN) {
|
|
|
|
|
|
+ hdr->args.context->state,
|
|
|
|
+ NULL) == -EAGAIN) {
|
|
rpc_restart_call_prepare(task);
|
|
rpc_restart_call_prepare(task);
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
}
|
|
}
|
|
@@ -4177,10 +4189,11 @@ static int nfs4_write_done_cb(struct rpc_task *task,
|
|
struct nfs_pgio_header *hdr)
|
|
struct nfs_pgio_header *hdr)
|
|
{
|
|
{
|
|
struct inode *inode = hdr->inode;
|
|
struct inode *inode = hdr->inode;
|
|
-
|
|
|
|
|
|
+
|
|
trace_nfs4_write(hdr, task->tk_status);
|
|
trace_nfs4_write(hdr, task->tk_status);
|
|
if (nfs4_async_handle_error(task, NFS_SERVER(inode),
|
|
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);
|
|
rpc_restart_call_prepare(task);
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
}
|
|
}
|
|
@@ -4260,7 +4273,8 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *da
|
|
struct inode *inode = data->inode;
|
|
struct inode *inode = data->inode;
|
|
|
|
|
|
trace_nfs4_commit(data, task->tk_status);
|
|
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);
|
|
rpc_restart_call_prepare(task);
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
}
|
|
}
|
|
@@ -4813,7 +4827,8 @@ out:
|
|
|
|
|
|
|
|
|
|
static int
|
|
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;
|
|
struct nfs_client *clp = server->nfs_client;
|
|
|
|
|
|
@@ -4863,6 +4878,8 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
|
|
#endif /* CONFIG_NFS_V4_1 */
|
|
#endif /* CONFIG_NFS_V4_1 */
|
|
case -NFS4ERR_DELAY:
|
|
case -NFS4ERR_DELAY:
|
|
nfs_inc_server_stats(server, NFSIOS_DELAY);
|
|
nfs_inc_server_stats(server, NFSIOS_DELAY);
|
|
|
|
+ rpc_delay(task, nfs4_update_delay(timeout));
|
|
|
|
+ goto restart_call;
|
|
case -NFS4ERR_GRACE:
|
|
case -NFS4ERR_GRACE:
|
|
rpc_delay(task, NFS4_POLL_RETRY_MAX);
|
|
rpc_delay(task, NFS4_POLL_RETRY_MAX);
|
|
case -NFS4ERR_RETRY_UNCACHED_REP:
|
|
case -NFS4ERR_RETRY_UNCACHED_REP:
|
|
@@ -5103,8 +5120,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
|
|
pnfs_roc_set_barrier(data->inode, data->roc_barrier);
|
|
pnfs_roc_set_barrier(data->inode, data->roc_barrier);
|
|
break;
|
|
break;
|
|
default:
|
|
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);
|
|
rpc_restart_call_prepare(task);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -5368,7 +5385,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
|
|
case -NFS4ERR_EXPIRED:
|
|
case -NFS4ERR_EXPIRED:
|
|
break;
|
|
break;
|
|
default:
|
|
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);
|
|
rpc_restart_call_prepare(task);
|
|
}
|
|
}
|
|
nfs_release_seqid(calldata->arg.seqid);
|
|
nfs_release_seqid(calldata->arg.seqid);
|
|
@@ -5974,7 +5992,8 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata)
|
|
break;
|
|
break;
|
|
case -NFS4ERR_LEASE_MOVED:
|
|
case -NFS4ERR_LEASE_MOVED:
|
|
case -NFS4ERR_DELAY:
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -7591,7 +7610,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
|
|
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);
|
|
rpc_restart_call_prepare(task);
|
|
out:
|
|
out:
|
|
dprintk("<-- %s\n", __func__);
|
|
dprintk("<-- %s\n", __func__);
|
|
@@ -7751,7 +7770,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
|
|
case 0:
|
|
case 0:
|
|
break;
|
|
break;
|
|
case -NFS4ERR_DELAY:
|
|
case -NFS4ERR_DELAY:
|
|
- if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN)
|
|
|
|
|
|
+ if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
|
|
break;
|
|
break;
|
|
rpc_restart_call_prepare(task);
|
|
rpc_restart_call_prepare(task);
|
|
return;
|
|
return;
|
|
@@ -7882,7 +7901,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
|
|
case 0:
|
|
case 0:
|
|
break;
|
|
break;
|
|
default:
|
|
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);
|
|
rpc_restart_call_prepare(task);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -8178,7 +8197,7 @@ static void nfs41_free_stateid_done(struct rpc_task *task, void *calldata)
|
|
|
|
|
|
switch (task->tk_status) {
|
|
switch (task->tk_status) {
|
|
case -NFS4ERR_DELAY:
|
|
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);
|
|
rpc_restart_call_prepare(task);
|
|
}
|
|
}
|
|
}
|
|
}
|