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) |
