aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-09-18 02:09:27 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-09-24 23:22:47 -0400
commit8478eaa16e701ecfe054b62ec764bc1291b79e19 (patch)
treea9cfe8c31443d372d1fe7ac8ad876152be94026f /fs/nfs
parent3dedbb5ca10ef13f25055776d2f6d9499d9ca1ba (diff)
NFSv4: use exponential retry on NFS4ERR_DELAY for async requests.
Currently asynchronous NFSv4 request will be retried with exponential timeout (from 1/10 to 15 seconds), but async requests will always use a 15second retry. Some "async" requests are really synchronous though. The async mechanism is used to allow the request to continue if the requesting process is killed. In those cases, an exponential retry is appropriate. For example, if two different clients both open a file and get a READ delegation, and one client then unlinks the file (while still holding an open file descriptor), that unlink will used the "silly-rename" handling which is async. The first rename will result in NFS4ERR_DELAY while the delegation is reclaimed from the other client. The rename will not be retried for 15 seconds, causing an unlink to take 15 seconds rather than 100msec. This patch only added exponential timeout for async unlink and async rename. Other async calls, such as 'close' are sometimes waited for so they might benefit from exponential timeout too. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c65
1 files changed, 42 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;
77static int _nfs4_proc_open(struct nfs4_opendata *data); 77static int _nfs4_proc_open(struct nfs4_opendata *data);
78static int _nfs4_recover_proc_open(struct nfs4_opendata *data); 78static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
79static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); 79static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
80static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); 80static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *, long *);
81static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); 81static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
82static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); 82static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label);
83static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label); 83static 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
317static 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
317static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) 331static 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
4815static int 4829static int
4816nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) 4830nfs4_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);
7596out: 7615out:
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}