aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c65
-rw-r--r--include/linux/nfs_xdr.h2
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;
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}
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
1344struct nfs_renamedata { 1345struct 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
1357struct nfs_access_entry; 1359struct nfs_access_entry;