diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 65 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 2 |
2 files changed, 44 insertions, 23 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 288be08bda95..45bce9ed6791 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -77,7 +77,7 @@ struct nfs4_opendata; | |||
77 | static int _nfs4_proc_open(struct nfs4_opendata *data); | 77 | static int _nfs4_proc_open(struct nfs4_opendata *data); |
78 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 78 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
79 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 79 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
80 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 80 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *, long *); |
81 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | 81 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); |
82 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); | 82 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); |
83 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label); | 83 | 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 | |||
314 | kunmap_atomic(start); | 314 | kunmap_atomic(start); |
315 | } | 315 | } |
316 | 316 | ||
317 | static long nfs4_update_delay(long *timeout) | ||
318 | { | ||
319 | long ret; | ||
320 | if (!timeout) | ||
321 | return NFS4_POLL_RETRY_MAX; | ||
322 | if (*timeout <= 0) | ||
323 | *timeout = NFS4_POLL_RETRY_MIN; | ||
324 | if (*timeout > NFS4_POLL_RETRY_MAX) | ||
325 | *timeout = NFS4_POLL_RETRY_MAX; | ||
326 | ret = *timeout; | ||
327 | *timeout <<= 1; | ||
328 | return ret; | ||
329 | } | ||
330 | |||
317 | static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | 331 | static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) |
318 | { | 332 | { |
319 | int res = 0; | 333 | int res = 0; |
320 | 334 | ||
321 | might_sleep(); | 335 | might_sleep(); |
322 | 336 | ||
323 | if (*timeout <= 0) | 337 | freezable_schedule_timeout_killable_unsafe( |
324 | *timeout = NFS4_POLL_RETRY_MIN; | 338 | nfs4_update_delay(timeout)); |
325 | if (*timeout > NFS4_POLL_RETRY_MAX) | ||
326 | *timeout = NFS4_POLL_RETRY_MAX; | ||
327 | freezable_schedule_timeout_killable_unsafe(*timeout); | ||
328 | if (fatal_signal_pending(current)) | 339 | if (fatal_signal_pending(current)) |
329 | res = -ERESTARTSYS; | 340 | res = -ERESTARTSYS; |
330 | *timeout <<= 1; | ||
331 | return res; | 341 | return res; |
332 | } | 342 | } |
333 | 343 | ||
@@ -2583,7 +2593,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2583 | if (calldata->arg.fmode == 0) | 2593 | if (calldata->arg.fmode == 0) |
2584 | break; | 2594 | break; |
2585 | default: | 2595 | default: |
2586 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { | 2596 | if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) { |
2587 | rpc_restart_call_prepare(task); | 2597 | rpc_restart_call_prepare(task); |
2588 | goto out_release; | 2598 | goto out_release; |
2589 | } | 2599 | } |
@@ -3572,7 +3582,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
3572 | 3582 | ||
3573 | if (!nfs4_sequence_done(task, &res->seq_res)) | 3583 | if (!nfs4_sequence_done(task, &res->seq_res)) |
3574 | return 0; | 3584 | return 0; |
3575 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | 3585 | if (nfs4_async_handle_error(task, res->server, NULL, |
3586 | &data->timeout) == -EAGAIN) | ||
3576 | return 0; | 3587 | return 0; |
3577 | update_changeattr(dir, &res->cinfo); | 3588 | update_changeattr(dir, &res->cinfo); |
3578 | return 1; | 3589 | return 1; |
@@ -3605,7 +3616,7 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | |||
3605 | 3616 | ||
3606 | if (!nfs4_sequence_done(task, &res->seq_res)) | 3617 | if (!nfs4_sequence_done(task, &res->seq_res)) |
3607 | return 0; | 3618 | return 0; |
3608 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | 3619 | if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN) |
3609 | return 0; | 3620 | return 0; |
3610 | 3621 | ||
3611 | update_changeattr(old_dir, &res->old_cinfo); | 3622 | 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) | |||
4109 | 4120 | ||
4110 | trace_nfs4_read(hdr, task->tk_status); | 4121 | trace_nfs4_read(hdr, task->tk_status); |
4111 | if (nfs4_async_handle_error(task, server, | 4122 | if (nfs4_async_handle_error(task, server, |
4112 | hdr->args.context->state) == -EAGAIN) { | 4123 | hdr->args.context->state, |
4124 | NULL) == -EAGAIN) { | ||
4113 | rpc_restart_call_prepare(task); | 4125 | rpc_restart_call_prepare(task); |
4114 | return -EAGAIN; | 4126 | return -EAGAIN; |
4115 | } | 4127 | } |
@@ -4177,10 +4189,11 @@ static int nfs4_write_done_cb(struct rpc_task *task, | |||
4177 | struct nfs_pgio_header *hdr) | 4189 | struct nfs_pgio_header *hdr) |
4178 | { | 4190 | { |
4179 | struct inode *inode = hdr->inode; | 4191 | struct inode *inode = hdr->inode; |
4180 | 4192 | ||
4181 | trace_nfs4_write(hdr, task->tk_status); | 4193 | trace_nfs4_write(hdr, task->tk_status); |
4182 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), | 4194 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), |
4183 | hdr->args.context->state) == -EAGAIN) { | 4195 | hdr->args.context->state, |
4196 | NULL) == -EAGAIN) { | ||
4184 | rpc_restart_call_prepare(task); | 4197 | rpc_restart_call_prepare(task); |
4185 | return -EAGAIN; | 4198 | return -EAGAIN; |
4186 | } | 4199 | } |
@@ -4260,7 +4273,8 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *da | |||
4260 | struct inode *inode = data->inode; | 4273 | struct inode *inode = data->inode; |
4261 | 4274 | ||
4262 | trace_nfs4_commit(data, task->tk_status); | 4275 | trace_nfs4_commit(data, task->tk_status); |
4263 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 4276 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), |
4277 | NULL, NULL) == -EAGAIN) { | ||
4264 | rpc_restart_call_prepare(task); | 4278 | rpc_restart_call_prepare(task); |
4265 | return -EAGAIN; | 4279 | return -EAGAIN; |
4266 | } | 4280 | } |
@@ -4813,7 +4827,8 @@ out: | |||
4813 | 4827 | ||
4814 | 4828 | ||
4815 | static int | 4829 | static int |
4816 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | 4830 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, |
4831 | struct nfs4_state *state, long *timeout) | ||
4817 | { | 4832 | { |
4818 | struct nfs_client *clp = server->nfs_client; | 4833 | struct nfs_client *clp = server->nfs_client; |
4819 | 4834 | ||
@@ -4863,6 +4878,8 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
4863 | #endif /* CONFIG_NFS_V4_1 */ | 4878 | #endif /* CONFIG_NFS_V4_1 */ |
4864 | case -NFS4ERR_DELAY: | 4879 | case -NFS4ERR_DELAY: |
4865 | nfs_inc_server_stats(server, NFSIOS_DELAY); | 4880 | nfs_inc_server_stats(server, NFSIOS_DELAY); |
4881 | rpc_delay(task, nfs4_update_delay(timeout)); | ||
4882 | goto restart_call; | ||
4866 | case -NFS4ERR_GRACE: | 4883 | case -NFS4ERR_GRACE: |
4867 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 4884 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
4868 | case -NFS4ERR_RETRY_UNCACHED_REP: | 4885 | case -NFS4ERR_RETRY_UNCACHED_REP: |
@@ -5103,8 +5120,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
5103 | pnfs_roc_set_barrier(data->inode, data->roc_barrier); | 5120 | pnfs_roc_set_barrier(data->inode, data->roc_barrier); |
5104 | break; | 5121 | break; |
5105 | default: | 5122 | default: |
5106 | if (nfs4_async_handle_error(task, data->res.server, NULL) == | 5123 | if (nfs4_async_handle_error(task, data->res.server, |
5107 | -EAGAIN) { | 5124 | NULL, NULL) == -EAGAIN) { |
5108 | rpc_restart_call_prepare(task); | 5125 | rpc_restart_call_prepare(task); |
5109 | return; | 5126 | return; |
5110 | } | 5127 | } |
@@ -5368,7 +5385,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
5368 | case -NFS4ERR_EXPIRED: | 5385 | case -NFS4ERR_EXPIRED: |
5369 | break; | 5386 | break; |
5370 | default: | 5387 | default: |
5371 | if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) | 5388 | if (nfs4_async_handle_error(task, calldata->server, |
5389 | NULL, NULL) == -EAGAIN) | ||
5372 | rpc_restart_call_prepare(task); | 5390 | rpc_restart_call_prepare(task); |
5373 | } | 5391 | } |
5374 | nfs_release_seqid(calldata->arg.seqid); | 5392 | nfs_release_seqid(calldata->arg.seqid); |
@@ -5974,7 +5992,8 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata) | |||
5974 | break; | 5992 | break; |
5975 | case -NFS4ERR_LEASE_MOVED: | 5993 | case -NFS4ERR_LEASE_MOVED: |
5976 | case -NFS4ERR_DELAY: | 5994 | case -NFS4ERR_DELAY: |
5977 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) | 5995 | if (nfs4_async_handle_error(task, server, |
5996 | NULL, NULL) == -EAGAIN) | ||
5978 | rpc_restart_call_prepare(task); | 5997 | rpc_restart_call_prepare(task); |
5979 | } | 5998 | } |
5980 | } | 5999 | } |
@@ -7591,7 +7610,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
7591 | rpc_restart_call_prepare(task); | 7610 | rpc_restart_call_prepare(task); |
7592 | } | 7611 | } |
7593 | } | 7612 | } |
7594 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) | 7613 | if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) |
7595 | rpc_restart_call_prepare(task); | 7614 | rpc_restart_call_prepare(task); |
7596 | out: | 7615 | out: |
7597 | dprintk("<-- %s\n", __func__); | 7616 | dprintk("<-- %s\n", __func__); |
@@ -7751,7 +7770,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
7751 | case 0: | 7770 | case 0: |
7752 | break; | 7771 | break; |
7753 | case -NFS4ERR_DELAY: | 7772 | case -NFS4ERR_DELAY: |
7754 | if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN) | 7773 | if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN) |
7755 | break; | 7774 | break; |
7756 | rpc_restart_call_prepare(task); | 7775 | rpc_restart_call_prepare(task); |
7757 | return; | 7776 | return; |
@@ -7882,7 +7901,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | |||
7882 | case 0: | 7901 | case 0: |
7883 | break; | 7902 | break; |
7884 | default: | 7903 | default: |
7885 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | 7904 | if (nfs4_async_handle_error(task, server, NULL, NULL) == -EAGAIN) { |
7886 | rpc_restart_call_prepare(task); | 7905 | rpc_restart_call_prepare(task); |
7887 | return; | 7906 | return; |
7888 | } | 7907 | } |
@@ -8178,7 +8197,7 @@ static void nfs41_free_stateid_done(struct rpc_task *task, void *calldata) | |||
8178 | 8197 | ||
8179 | switch (task->tk_status) { | 8198 | switch (task->tk_status) { |
8180 | case -NFS4ERR_DELAY: | 8199 | case -NFS4ERR_DELAY: |
8181 | if (nfs4_async_handle_error(task, data->server, NULL) == -EAGAIN) | 8200 | if (nfs4_async_handle_error(task, data->server, NULL, NULL) == -EAGAIN) |
8182 | rpc_restart_call_prepare(task); | 8201 | rpc_restart_call_prepare(task); |
8183 | } | 8202 | } |
8184 | } | 8203 | } |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 7ae249ccb78d..6951c7d9097d 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1339,6 +1339,7 @@ struct nfs_unlinkdata { | |||
1339 | struct inode *dir; | 1339 | struct inode *dir; |
1340 | struct rpc_cred *cred; | 1340 | struct rpc_cred *cred; |
1341 | struct nfs_fattr dir_attr; | 1341 | struct nfs_fattr dir_attr; |
1342 | long timeout; | ||
1342 | }; | 1343 | }; |
1343 | 1344 | ||
1344 | struct nfs_renamedata { | 1345 | struct nfs_renamedata { |
@@ -1352,6 +1353,7 @@ struct nfs_renamedata { | |||
1352 | struct dentry *new_dentry; | 1353 | struct dentry *new_dentry; |
1353 | struct nfs_fattr new_fattr; | 1354 | struct nfs_fattr new_fattr; |
1354 | void (*complete)(struct rpc_task *, struct nfs_renamedata *); | 1355 | void (*complete)(struct rpc_task *, struct nfs_renamedata *); |
1356 | long timeout; | ||
1355 | }; | 1357 | }; |
1356 | 1358 | ||
1357 | struct nfs_access_entry; | 1359 | struct nfs_access_entry; |