diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 136 |
1 files changed, 56 insertions, 80 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 0422d77b73c7..5aa55c132aa2 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 | ||
@@ -1307,15 +1317,13 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | |||
1307 | int ret = -EAGAIN; | 1317 | int ret = -EAGAIN; |
1308 | 1318 | ||
1309 | for (;;) { | 1319 | for (;;) { |
1320 | spin_lock(&state->owner->so_lock); | ||
1310 | if (can_open_cached(state, fmode, open_mode)) { | 1321 | if (can_open_cached(state, fmode, open_mode)) { |
1311 | spin_lock(&state->owner->so_lock); | 1322 | update_open_stateflags(state, fmode); |
1312 | if (can_open_cached(state, fmode, open_mode)) { | ||
1313 | update_open_stateflags(state, fmode); | ||
1314 | spin_unlock(&state->owner->so_lock); | ||
1315 | goto out_return_state; | ||
1316 | } | ||
1317 | spin_unlock(&state->owner->so_lock); | 1323 | spin_unlock(&state->owner->so_lock); |
1324 | goto out_return_state; | ||
1318 | } | 1325 | } |
1326 | spin_unlock(&state->owner->so_lock); | ||
1319 | rcu_read_lock(); | 1327 | rcu_read_lock(); |
1320 | delegation = rcu_dereference(nfsi->delegation); | 1328 | delegation = rcu_dereference(nfsi->delegation); |
1321 | if (!can_open_delegated(delegation, fmode)) { | 1329 | if (!can_open_delegated(delegation, fmode)) { |
@@ -2589,7 +2597,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2589 | if (calldata->arg.fmode == 0) | 2597 | if (calldata->arg.fmode == 0) |
2590 | break; | 2598 | break; |
2591 | default: | 2599 | default: |
2592 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { | 2600 | if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) { |
2593 | rpc_restart_call_prepare(task); | 2601 | rpc_restart_call_prepare(task); |
2594 | goto out_release; | 2602 | goto out_release; |
2595 | } | 2603 | } |
@@ -3217,7 +3225,9 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
3217 | struct nfs4_label *label = NULL; | 3225 | struct nfs4_label *label = NULL; |
3218 | int status; | 3226 | int status; |
3219 | 3227 | ||
3220 | if (pnfs_ld_layoutret_on_setattr(inode)) | 3228 | if (pnfs_ld_layoutret_on_setattr(inode) && |
3229 | sattr->ia_valid & ATTR_SIZE && | ||
3230 | sattr->ia_size < i_size_read(inode)) | ||
3221 | pnfs_commit_and_return_layout(inode); | 3231 | pnfs_commit_and_return_layout(inode); |
3222 | 3232 | ||
3223 | nfs_fattr_init(fattr); | 3233 | nfs_fattr_init(fattr); |
@@ -3576,7 +3586,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
3576 | 3586 | ||
3577 | if (!nfs4_sequence_done(task, &res->seq_res)) | 3587 | if (!nfs4_sequence_done(task, &res->seq_res)) |
3578 | return 0; | 3588 | return 0; |
3579 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | 3589 | if (nfs4_async_handle_error(task, res->server, NULL, |
3590 | &data->timeout) == -EAGAIN) | ||
3580 | return 0; | 3591 | return 0; |
3581 | update_changeattr(dir, &res->cinfo); | 3592 | update_changeattr(dir, &res->cinfo); |
3582 | return 1; | 3593 | return 1; |
@@ -3609,7 +3620,7 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | |||
3609 | 3620 | ||
3610 | if (!nfs4_sequence_done(task, &res->seq_res)) | 3621 | if (!nfs4_sequence_done(task, &res->seq_res)) |
3611 | return 0; | 3622 | return 0; |
3612 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | 3623 | if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN) |
3613 | return 0; | 3624 | return 0; |
3614 | 3625 | ||
3615 | update_changeattr(old_dir, &res->old_cinfo); | 3626 | update_changeattr(old_dir, &res->old_cinfo); |
@@ -4113,7 +4124,8 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_header *hdr) | |||
4113 | 4124 | ||
4114 | trace_nfs4_read(hdr, task->tk_status); | 4125 | trace_nfs4_read(hdr, task->tk_status); |
4115 | if (nfs4_async_handle_error(task, server, | 4126 | if (nfs4_async_handle_error(task, server, |
4116 | hdr->args.context->state) == -EAGAIN) { | 4127 | hdr->args.context->state, |
4128 | NULL) == -EAGAIN) { | ||
4117 | rpc_restart_call_prepare(task); | 4129 | rpc_restart_call_prepare(task); |
4118 | return -EAGAIN; | 4130 | return -EAGAIN; |
4119 | } | 4131 | } |
@@ -4181,10 +4193,11 @@ static int nfs4_write_done_cb(struct rpc_task *task, | |||
4181 | struct nfs_pgio_header *hdr) | 4193 | struct nfs_pgio_header *hdr) |
4182 | { | 4194 | { |
4183 | struct inode *inode = hdr->inode; | 4195 | struct inode *inode = hdr->inode; |
4184 | 4196 | ||
4185 | trace_nfs4_write(hdr, task->tk_status); | 4197 | trace_nfs4_write(hdr, task->tk_status); |
4186 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), | 4198 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), |
4187 | hdr->args.context->state) == -EAGAIN) { | 4199 | hdr->args.context->state, |
4200 | NULL) == -EAGAIN) { | ||
4188 | rpc_restart_call_prepare(task); | 4201 | rpc_restart_call_prepare(task); |
4189 | return -EAGAIN; | 4202 | return -EAGAIN; |
4190 | } | 4203 | } |
@@ -4264,7 +4277,8 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *da | |||
4264 | struct inode *inode = data->inode; | 4277 | struct inode *inode = data->inode; |
4265 | 4278 | ||
4266 | trace_nfs4_commit(data, task->tk_status); | 4279 | trace_nfs4_commit(data, task->tk_status); |
4267 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 4280 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), |
4281 | NULL, NULL) == -EAGAIN) { | ||
4268 | rpc_restart_call_prepare(task); | 4282 | rpc_restart_call_prepare(task); |
4269 | return -EAGAIN; | 4283 | return -EAGAIN; |
4270 | } | 4284 | } |
@@ -4817,7 +4831,8 @@ out: | |||
4817 | 4831 | ||
4818 | 4832 | ||
4819 | static int | 4833 | static int |
4820 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | 4834 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, |
4835 | struct nfs4_state *state, long *timeout) | ||
4821 | { | 4836 | { |
4822 | struct nfs_client *clp = server->nfs_client; | 4837 | struct nfs_client *clp = server->nfs_client; |
4823 | 4838 | ||
@@ -4867,6 +4882,8 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
4867 | #endif /* CONFIG_NFS_V4_1 */ | 4882 | #endif /* CONFIG_NFS_V4_1 */ |
4868 | case -NFS4ERR_DELAY: | 4883 | case -NFS4ERR_DELAY: |
4869 | nfs_inc_server_stats(server, NFSIOS_DELAY); | 4884 | nfs_inc_server_stats(server, NFSIOS_DELAY); |
4885 | rpc_delay(task, nfs4_update_delay(timeout)); | ||
4886 | goto restart_call; | ||
4870 | case -NFS4ERR_GRACE: | 4887 | case -NFS4ERR_GRACE: |
4871 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 4888 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
4872 | case -NFS4ERR_RETRY_UNCACHED_REP: | 4889 | case -NFS4ERR_RETRY_UNCACHED_REP: |
@@ -5107,8 +5124,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
5107 | pnfs_roc_set_barrier(data->inode, data->roc_barrier); | 5124 | pnfs_roc_set_barrier(data->inode, data->roc_barrier); |
5108 | break; | 5125 | break; |
5109 | default: | 5126 | default: |
5110 | if (nfs4_async_handle_error(task, data->res.server, NULL) == | 5127 | if (nfs4_async_handle_error(task, data->res.server, |
5111 | -EAGAIN) { | 5128 | NULL, NULL) == -EAGAIN) { |
5112 | rpc_restart_call_prepare(task); | 5129 | rpc_restart_call_prepare(task); |
5113 | return; | 5130 | return; |
5114 | } | 5131 | } |
@@ -5372,7 +5389,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
5372 | case -NFS4ERR_EXPIRED: | 5389 | case -NFS4ERR_EXPIRED: |
5373 | break; | 5390 | break; |
5374 | default: | 5391 | default: |
5375 | if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) | 5392 | if (nfs4_async_handle_error(task, calldata->server, |
5393 | NULL, NULL) == -EAGAIN) | ||
5376 | rpc_restart_call_prepare(task); | 5394 | rpc_restart_call_prepare(task); |
5377 | } | 5395 | } |
5378 | nfs_release_seqid(calldata->arg.seqid); | 5396 | nfs_release_seqid(calldata->arg.seqid); |
@@ -5978,7 +5996,8 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata) | |||
5978 | break; | 5996 | break; |
5979 | case -NFS4ERR_LEASE_MOVED: | 5997 | case -NFS4ERR_LEASE_MOVED: |
5980 | case -NFS4ERR_DELAY: | 5998 | case -NFS4ERR_DELAY: |
5981 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) | 5999 | if (nfs4_async_handle_error(task, server, |
6000 | NULL, NULL) == -EAGAIN) | ||
5982 | rpc_restart_call_prepare(task); | 6001 | rpc_restart_call_prepare(task); |
5983 | } | 6002 | } |
5984 | } | 6003 | } |
@@ -7583,14 +7602,19 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
7583 | } else { | 7602 | } else { |
7584 | LIST_HEAD(head); | 7603 | LIST_HEAD(head); |
7585 | 7604 | ||
7605 | /* | ||
7606 | * Mark the bad layout state as invalid, then retry | ||
7607 | * with the current stateid. | ||
7608 | */ | ||
7586 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); | 7609 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); |
7587 | spin_unlock(&inode->i_lock); | 7610 | spin_unlock(&inode->i_lock); |
7588 | /* Mark the bad layout state as invalid, then | ||
7589 | * retry using the open stateid. */ | ||
7590 | pnfs_free_lseg_list(&head); | 7611 | pnfs_free_lseg_list(&head); |
7612 | |||
7613 | task->tk_status = 0; | ||
7614 | rpc_restart_call_prepare(task); | ||
7591 | } | 7615 | } |
7592 | } | 7616 | } |
7593 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) | 7617 | if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) |
7594 | rpc_restart_call_prepare(task); | 7618 | rpc_restart_call_prepare(task); |
7595 | out: | 7619 | out: |
7596 | dprintk("<-- %s\n", __func__); | 7620 | dprintk("<-- %s\n", __func__); |
@@ -7750,7 +7774,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
7750 | case 0: | 7774 | case 0: |
7751 | break; | 7775 | break; |
7752 | case -NFS4ERR_DELAY: | 7776 | case -NFS4ERR_DELAY: |
7753 | if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN) | 7777 | if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN) |
7754 | break; | 7778 | break; |
7755 | rpc_restart_call_prepare(task); | 7779 | rpc_restart_call_prepare(task); |
7756 | return; | 7780 | return; |
@@ -7809,54 +7833,6 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
7809 | return status; | 7833 | return status; |
7810 | } | 7834 | } |
7811 | 7835 | ||
7812 | /* | ||
7813 | * Retrieve the list of Data Server devices from the MDS. | ||
7814 | */ | ||
7815 | static int _nfs4_getdevicelist(struct nfs_server *server, | ||
7816 | const struct nfs_fh *fh, | ||
7817 | struct pnfs_devicelist *devlist) | ||
7818 | { | ||
7819 | struct nfs4_getdevicelist_args args = { | ||
7820 | .fh = fh, | ||
7821 | .layoutclass = server->pnfs_curr_ld->id, | ||
7822 | }; | ||
7823 | struct nfs4_getdevicelist_res res = { | ||
7824 | .devlist = devlist, | ||
7825 | }; | ||
7826 | struct rpc_message msg = { | ||
7827 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICELIST], | ||
7828 | .rpc_argp = &args, | ||
7829 | .rpc_resp = &res, | ||
7830 | }; | ||
7831 | int status; | ||
7832 | |||
7833 | dprintk("--> %s\n", __func__); | ||
7834 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, | ||
7835 | &res.seq_res, 0); | ||
7836 | dprintk("<-- %s status=%d\n", __func__, status); | ||
7837 | return status; | ||
7838 | } | ||
7839 | |||
7840 | int nfs4_proc_getdevicelist(struct nfs_server *server, | ||
7841 | const struct nfs_fh *fh, | ||
7842 | struct pnfs_devicelist *devlist) | ||
7843 | { | ||
7844 | struct nfs4_exception exception = { }; | ||
7845 | int err; | ||
7846 | |||
7847 | do { | ||
7848 | err = nfs4_handle_exception(server, | ||
7849 | _nfs4_getdevicelist(server, fh, devlist), | ||
7850 | &exception); | ||
7851 | } while (exception.retry); | ||
7852 | |||
7853 | dprintk("%s: err=%d, num_devs=%u\n", __func__, | ||
7854 | err, devlist->num_devs); | ||
7855 | |||
7856 | return err; | ||
7857 | } | ||
7858 | EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist); | ||
7859 | |||
7860 | static int | 7836 | static int |
7861 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, | 7837 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, |
7862 | struct pnfs_device *pdev, | 7838 | struct pnfs_device *pdev, |
@@ -7929,7 +7905,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | |||
7929 | case 0: | 7905 | case 0: |
7930 | break; | 7906 | break; |
7931 | default: | 7907 | default: |
7932 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | 7908 | if (nfs4_async_handle_error(task, server, NULL, NULL) == -EAGAIN) { |
7933 | rpc_restart_call_prepare(task); | 7909 | rpc_restart_call_prepare(task); |
7934 | return; | 7910 | return; |
7935 | } | 7911 | } |
@@ -8225,7 +8201,7 @@ static void nfs41_free_stateid_done(struct rpc_task *task, void *calldata) | |||
8225 | 8201 | ||
8226 | switch (task->tk_status) { | 8202 | switch (task->tk_status) { |
8227 | case -NFS4ERR_DELAY: | 8203 | case -NFS4ERR_DELAY: |
8228 | if (nfs4_async_handle_error(task, data->server, NULL) == -EAGAIN) | 8204 | if (nfs4_async_handle_error(task, data->server, NULL, NULL) == -EAGAIN) |
8229 | rpc_restart_call_prepare(task); | 8205 | rpc_restart_call_prepare(task); |
8230 | } | 8206 | } |
8231 | } | 8207 | } |