diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 198d51d17c13..375f0fae2c6a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -249,19 +249,15 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
249 | if (state == NULL) | 249 | if (state == NULL) |
250 | break; | 250 | break; |
251 | nfs4_state_mark_reclaim_nograce(clp, state); | 251 | nfs4_state_mark_reclaim_nograce(clp, state); |
252 | case -NFS4ERR_STALE_CLIENTID: | 252 | goto do_state_recovery; |
253 | case -NFS4ERR_STALE_STATEID: | 253 | case -NFS4ERR_STALE_STATEID: |
254 | case -NFS4ERR_EXPIRED: | 254 | if (state == NULL) |
255 | nfs4_schedule_state_recovery(clp); | ||
256 | ret = nfs4_wait_clnt_recover(clp); | ||
257 | if (ret == 0) | ||
258 | exception->retry = 1; | ||
259 | #if !defined(CONFIG_NFS_V4_1) | ||
260 | break; | ||
261 | #else /* !defined(CONFIG_NFS_V4_1) */ | ||
262 | if (!nfs4_has_session(server->nfs_client)) | ||
263 | break; | 255 | break; |
264 | /* FALLTHROUGH */ | 256 | nfs4_state_mark_reclaim_reboot(clp, state); |
257 | case -NFS4ERR_STALE_CLIENTID: | ||
258 | case -NFS4ERR_EXPIRED: | ||
259 | goto do_state_recovery; | ||
260 | #if defined(CONFIG_NFS_V4_1) | ||
265 | case -NFS4ERR_BADSESSION: | 261 | case -NFS4ERR_BADSESSION: |
266 | case -NFS4ERR_BADSLOT: | 262 | case -NFS4ERR_BADSLOT: |
267 | case -NFS4ERR_BAD_HIGH_SLOT: | 263 | case -NFS4ERR_BAD_HIGH_SLOT: |
@@ -274,7 +270,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
274 | nfs4_schedule_state_recovery(clp); | 270 | nfs4_schedule_state_recovery(clp); |
275 | exception->retry = 1; | 271 | exception->retry = 1; |
276 | break; | 272 | break; |
277 | #endif /* !defined(CONFIG_NFS_V4_1) */ | 273 | #endif /* defined(CONFIG_NFS_V4_1) */ |
278 | case -NFS4ERR_FILE_OPEN: | 274 | case -NFS4ERR_FILE_OPEN: |
279 | if (exception->timeout > HZ) { | 275 | if (exception->timeout > HZ) { |
280 | /* We have retried a decent amount, time to | 276 | /* We have retried a decent amount, time to |
@@ -293,6 +289,12 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
293 | } | 289 | } |
294 | /* We failed to handle the error */ | 290 | /* We failed to handle the error */ |
295 | return nfs4_map_errors(ret); | 291 | return nfs4_map_errors(ret); |
292 | do_state_recovery: | ||
293 | nfs4_schedule_state_recovery(clp); | ||
294 | ret = nfs4_wait_clnt_recover(clp); | ||
295 | if (ret == 0) | ||
296 | exception->retry = 1; | ||
297 | return ret; | ||
296 | } | 298 | } |
297 | 299 | ||
298 | 300 | ||
@@ -1658,6 +1660,8 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in | |||
1658 | status = PTR_ERR(state); | 1660 | status = PTR_ERR(state); |
1659 | if (IS_ERR(state)) | 1661 | if (IS_ERR(state)) |
1660 | goto err_opendata_put; | 1662 | goto err_opendata_put; |
1663 | if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0) | ||
1664 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); | ||
1661 | nfs4_opendata_put(opendata); | 1665 | nfs4_opendata_put(opendata); |
1662 | nfs4_put_state_owner(sp); | 1666 | nfs4_put_state_owner(sp); |
1663 | *res = state; | 1667 | *res = state; |
@@ -3422,15 +3426,14 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3422 | if (state == NULL) | 3426 | if (state == NULL) |
3423 | break; | 3427 | break; |
3424 | nfs4_state_mark_reclaim_nograce(clp, state); | 3428 | nfs4_state_mark_reclaim_nograce(clp, state); |
3425 | case -NFS4ERR_STALE_CLIENTID: | 3429 | goto do_state_recovery; |
3426 | case -NFS4ERR_STALE_STATEID: | 3430 | case -NFS4ERR_STALE_STATEID: |
3431 | if (state == NULL) | ||
3432 | break; | ||
3433 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
3434 | case -NFS4ERR_STALE_CLIENTID: | ||
3427 | case -NFS4ERR_EXPIRED: | 3435 | case -NFS4ERR_EXPIRED: |
3428 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | 3436 | goto do_state_recovery; |
3429 | nfs4_schedule_state_recovery(clp); | ||
3430 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | ||
3431 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | ||
3432 | task->tk_status = 0; | ||
3433 | return -EAGAIN; | ||
3434 | #if defined(CONFIG_NFS_V4_1) | 3437 | #if defined(CONFIG_NFS_V4_1) |
3435 | case -NFS4ERR_BADSESSION: | 3438 | case -NFS4ERR_BADSESSION: |
3436 | case -NFS4ERR_BADSLOT: | 3439 | case -NFS4ERR_BADSLOT: |
@@ -3458,6 +3461,13 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3458 | } | 3461 | } |
3459 | task->tk_status = nfs4_map_errors(task->tk_status); | 3462 | task->tk_status = nfs4_map_errors(task->tk_status); |
3460 | return 0; | 3463 | return 0; |
3464 | do_state_recovery: | ||
3465 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | ||
3466 | nfs4_schedule_state_recovery(clp); | ||
3467 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | ||
3468 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | ||
3469 | task->tk_status = 0; | ||
3470 | return -EAGAIN; | ||
3461 | } | 3471 | } |
3462 | 3472 | ||
3463 | static int | 3473 | static int |
@@ -4088,6 +4098,28 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = { | |||
4088 | .rpc_release = nfs4_lock_release, | 4098 | .rpc_release = nfs4_lock_release, |
4089 | }; | 4099 | }; |
4090 | 4100 | ||
4101 | static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) | ||
4102 | { | ||
4103 | struct nfs_client *clp = server->nfs_client; | ||
4104 | struct nfs4_state *state = lsp->ls_state; | ||
4105 | |||
4106 | switch (error) { | ||
4107 | case -NFS4ERR_ADMIN_REVOKED: | ||
4108 | case -NFS4ERR_BAD_STATEID: | ||
4109 | case -NFS4ERR_EXPIRED: | ||
4110 | if (new_lock_owner != 0 || | ||
4111 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | ||
4112 | nfs4_state_mark_reclaim_nograce(clp, state); | ||
4113 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; | ||
4114 | break; | ||
4115 | case -NFS4ERR_STALE_STATEID: | ||
4116 | if (new_lock_owner != 0 || | ||
4117 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | ||
4118 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
4119 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; | ||
4120 | }; | ||
4121 | } | ||
4122 | |||
4091 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) | 4123 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) |
4092 | { | 4124 | { |
4093 | struct nfs4_lockdata *data; | 4125 | struct nfs4_lockdata *data; |
@@ -4126,6 +4158,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
4126 | ret = nfs4_wait_for_completion_rpc_task(task); | 4158 | ret = nfs4_wait_for_completion_rpc_task(task); |
4127 | if (ret == 0) { | 4159 | if (ret == 0) { |
4128 | ret = data->rpc_status; | 4160 | ret = data->rpc_status; |
4161 | if (ret) | ||
4162 | nfs4_handle_setlk_error(data->server, data->lsp, | ||
4163 | data->arg.new_lock_owner, ret); | ||
4129 | } else | 4164 | } else |
4130 | data->cancelled = 1; | 4165 | data->cancelled = 1; |
4131 | rpc_put_task(task); | 4166 | rpc_put_task(task); |
@@ -4181,8 +4216,11 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock | |||
4181 | { | 4216 | { |
4182 | struct nfs_inode *nfsi = NFS_I(state->inode); | 4217 | struct nfs_inode *nfsi = NFS_I(state->inode); |
4183 | unsigned char fl_flags = request->fl_flags; | 4218 | unsigned char fl_flags = request->fl_flags; |
4184 | int status; | 4219 | int status = -ENOLCK; |
4185 | 4220 | ||
4221 | if ((fl_flags & FL_POSIX) && | ||
4222 | !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags)) | ||
4223 | goto out; | ||
4186 | /* Is this a delegated open? */ | 4224 | /* Is this a delegated open? */ |
4187 | status = nfs4_set_lock_state(state, request); | 4225 | status = nfs4_set_lock_state(state, request); |
4188 | if (status != 0) | 4226 | if (status != 0) |