diff options
| -rw-r--r-- | fs/nfs/callback.c | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs4_fs.h | 7 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 38 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 1 |
4 files changed, 35 insertions, 13 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 532d8e242d4d..484bebc20bca 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
| @@ -197,7 +197,7 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, | |||
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | ret = -EPROTONOSUPPORT; | 199 | ret = -EPROTONOSUPPORT; |
| 200 | if (minorversion == 0) | 200 | if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0) |
| 201 | ret = nfs4_callback_up_net(serv, net); | 201 | ret = nfs4_callback_up_net(serv, net); |
| 202 | else if (xprt->ops->bc_up) | 202 | else if (xprt->ops->bc_up) |
| 203 | ret = xprt->ops->bc_up(serv, net); | 203 | ret = xprt->ops->bc_up(serv, net); |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 9b3a82abab07..1452177c822d 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -542,6 +542,13 @@ static inline bool nfs4_valid_open_stateid(const struct nfs4_state *state) | |||
| 542 | return test_bit(NFS_STATE_RECOVERY_FAILED, &state->flags) == 0; | 542 | return test_bit(NFS_STATE_RECOVERY_FAILED, &state->flags) == 0; |
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | static inline bool nfs4_state_match_open_stateid_other(const struct nfs4_state *state, | ||
| 546 | const nfs4_stateid *stateid) | ||
| 547 | { | ||
| 548 | return test_bit(NFS_OPEN_STATE, &state->flags) && | ||
| 549 | nfs4_stateid_match_other(&state->open_stateid, stateid); | ||
| 550 | } | ||
| 551 | |||
| 545 | #else | 552 | #else |
| 546 | 553 | ||
| 547 | #define nfs4_close_state(a, b) do { } while (0) | 554 | #define nfs4_close_state(a, b) do { } while (0) |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 7897826d7c51..241da19b7da4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -1451,7 +1451,6 @@ static void nfs_resync_open_stateid_locked(struct nfs4_state *state) | |||
| 1451 | } | 1451 | } |
| 1452 | 1452 | ||
| 1453 | static void nfs_clear_open_stateid_locked(struct nfs4_state *state, | 1453 | static void nfs_clear_open_stateid_locked(struct nfs4_state *state, |
| 1454 | nfs4_stateid *arg_stateid, | ||
| 1455 | nfs4_stateid *stateid, fmode_t fmode) | 1454 | nfs4_stateid *stateid, fmode_t fmode) |
| 1456 | { | 1455 | { |
| 1457 | clear_bit(NFS_O_RDWR_STATE, &state->flags); | 1456 | clear_bit(NFS_O_RDWR_STATE, &state->flags); |
| @@ -1469,10 +1468,9 @@ static void nfs_clear_open_stateid_locked(struct nfs4_state *state, | |||
| 1469 | } | 1468 | } |
| 1470 | if (stateid == NULL) | 1469 | if (stateid == NULL) |
| 1471 | return; | 1470 | return; |
| 1472 | /* Handle races with OPEN */ | 1471 | /* Handle OPEN+OPEN_DOWNGRADE races */ |
| 1473 | if (!nfs4_stateid_match_other(arg_stateid, &state->open_stateid) || | 1472 | if (nfs4_stateid_match_other(stateid, &state->open_stateid) && |
| 1474 | (nfs4_stateid_match_other(stateid, &state->open_stateid) && | 1473 | !nfs4_stateid_is_newer(stateid, &state->open_stateid)) { |
| 1475 | !nfs4_stateid_is_newer(stateid, &state->open_stateid))) { | ||
| 1476 | nfs_resync_open_stateid_locked(state); | 1474 | nfs_resync_open_stateid_locked(state); |
| 1477 | return; | 1475 | return; |
| 1478 | } | 1476 | } |
| @@ -1486,7 +1484,9 @@ static void nfs_clear_open_stateid(struct nfs4_state *state, | |||
| 1486 | nfs4_stateid *stateid, fmode_t fmode) | 1484 | nfs4_stateid *stateid, fmode_t fmode) |
| 1487 | { | 1485 | { |
| 1488 | write_seqlock(&state->seqlock); | 1486 | write_seqlock(&state->seqlock); |
| 1489 | nfs_clear_open_stateid_locked(state, arg_stateid, stateid, fmode); | 1487 | /* Ignore, if the CLOSE argment doesn't match the current stateid */ |
| 1488 | if (nfs4_state_match_open_stateid_other(state, arg_stateid)) | ||
| 1489 | nfs_clear_open_stateid_locked(state, stateid, fmode); | ||
| 1490 | write_sequnlock(&state->seqlock); | 1490 | write_sequnlock(&state->seqlock); |
| 1491 | if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags)) | 1491 | if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags)) |
| 1492 | nfs4_schedule_state_manager(state->owner->so_server->nfs_client); | 1492 | nfs4_schedule_state_manager(state->owner->so_server->nfs_client); |
| @@ -2564,15 +2564,23 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state) | |||
| 2564 | static int nfs41_check_expired_locks(struct nfs4_state *state) | 2564 | static int nfs41_check_expired_locks(struct nfs4_state *state) |
| 2565 | { | 2565 | { |
| 2566 | int status, ret = NFS_OK; | 2566 | int status, ret = NFS_OK; |
| 2567 | struct nfs4_lock_state *lsp; | 2567 | struct nfs4_lock_state *lsp, *prev = NULL; |
| 2568 | struct nfs_server *server = NFS_SERVER(state->inode); | 2568 | struct nfs_server *server = NFS_SERVER(state->inode); |
| 2569 | 2569 | ||
| 2570 | if (!test_bit(LK_STATE_IN_USE, &state->flags)) | 2570 | if (!test_bit(LK_STATE_IN_USE, &state->flags)) |
| 2571 | goto out; | 2571 | goto out; |
| 2572 | |||
| 2573 | spin_lock(&state->state_lock); | ||
| 2572 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { | 2574 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { |
| 2573 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { | 2575 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { |
| 2574 | struct rpc_cred *cred = lsp->ls_state->owner->so_cred; | 2576 | struct rpc_cred *cred = lsp->ls_state->owner->so_cred; |
| 2575 | 2577 | ||
| 2578 | atomic_inc(&lsp->ls_count); | ||
| 2579 | spin_unlock(&state->state_lock); | ||
| 2580 | |||
| 2581 | nfs4_put_lock_state(prev); | ||
| 2582 | prev = lsp; | ||
| 2583 | |||
| 2576 | status = nfs41_test_and_free_expired_stateid(server, | 2584 | status = nfs41_test_and_free_expired_stateid(server, |
| 2577 | &lsp->ls_stateid, | 2585 | &lsp->ls_stateid, |
| 2578 | cred); | 2586 | cred); |
| @@ -2585,10 +2593,14 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
| 2585 | set_bit(NFS_LOCK_LOST, &lsp->ls_flags); | 2593 | set_bit(NFS_LOCK_LOST, &lsp->ls_flags); |
| 2586 | } else if (status != NFS_OK) { | 2594 | } else if (status != NFS_OK) { |
| 2587 | ret = status; | 2595 | ret = status; |
| 2588 | break; | 2596 | nfs4_put_lock_state(prev); |
| 2597 | goto out; | ||
| 2589 | } | 2598 | } |
| 2599 | spin_lock(&state->state_lock); | ||
| 2590 | } | 2600 | } |
| 2591 | }; | 2601 | } |
| 2602 | spin_unlock(&state->state_lock); | ||
| 2603 | nfs4_put_lock_state(prev); | ||
| 2592 | out: | 2604 | out: |
| 2593 | return ret; | 2605 | return ret; |
| 2594 | } | 2606 | } |
| @@ -3122,7 +3134,8 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
| 3122 | } else if (is_rdwr) | 3134 | } else if (is_rdwr) |
| 3123 | calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; | 3135 | calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; |
| 3124 | 3136 | ||
| 3125 | if (!nfs4_valid_open_stateid(state)) | 3137 | if (!nfs4_valid_open_stateid(state) || |
| 3138 | test_bit(NFS_OPEN_STATE, &state->flags) == 0) | ||
| 3126 | call_close = 0; | 3139 | call_close = 0; |
| 3127 | spin_unlock(&state->owner->so_lock); | 3140 | spin_unlock(&state->owner->so_lock); |
| 3128 | 3141 | ||
| @@ -5569,6 +5582,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
| 5569 | switch (task->tk_status) { | 5582 | switch (task->tk_status) { |
| 5570 | case 0: | 5583 | case 0: |
| 5571 | renew_lease(data->res.server, data->timestamp); | 5584 | renew_lease(data->res.server, data->timestamp); |
| 5585 | break; | ||
| 5572 | case -NFS4ERR_ADMIN_REVOKED: | 5586 | case -NFS4ERR_ADMIN_REVOKED: |
| 5573 | case -NFS4ERR_DELEG_REVOKED: | 5587 | case -NFS4ERR_DELEG_REVOKED: |
| 5574 | case -NFS4ERR_EXPIRED: | 5588 | case -NFS4ERR_EXPIRED: |
| @@ -5579,8 +5593,6 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
| 5579 | case -NFS4ERR_OLD_STATEID: | 5593 | case -NFS4ERR_OLD_STATEID: |
| 5580 | case -NFS4ERR_STALE_STATEID: | 5594 | case -NFS4ERR_STALE_STATEID: |
| 5581 | task->tk_status = 0; | 5595 | task->tk_status = 0; |
| 5582 | if (data->roc) | ||
| 5583 | pnfs_roc_set_barrier(data->inode, data->roc_barrier); | ||
| 5584 | break; | 5596 | break; |
| 5585 | default: | 5597 | default: |
| 5586 | if (nfs4_async_handle_error(task, data->res.server, | 5598 | if (nfs4_async_handle_error(task, data->res.server, |
| @@ -5590,6 +5602,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
| 5590 | } | 5602 | } |
| 5591 | } | 5603 | } |
| 5592 | data->rpc_status = task->tk_status; | 5604 | data->rpc_status = task->tk_status; |
| 5605 | if (data->roc && data->rpc_status == 0) | ||
| 5606 | pnfs_roc_set_barrier(data->inode, data->roc_barrier); | ||
| 5593 | } | 5607 | } |
| 5594 | 5608 | ||
| 5595 | static void nfs4_delegreturn_release(void *calldata) | 5609 | static void nfs4_delegreturn_release(void *calldata) |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 5f4281ec5f72..0959c9661662 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -1547,6 +1547,7 @@ restart: | |||
| 1547 | ssleep(1); | 1547 | ssleep(1); |
| 1548 | case -NFS4ERR_ADMIN_REVOKED: | 1548 | case -NFS4ERR_ADMIN_REVOKED: |
| 1549 | case -NFS4ERR_STALE_STATEID: | 1549 | case -NFS4ERR_STALE_STATEID: |
| 1550 | case -NFS4ERR_OLD_STATEID: | ||
| 1550 | case -NFS4ERR_BAD_STATEID: | 1551 | case -NFS4ERR_BAD_STATEID: |
| 1551 | case -NFS4ERR_RECLAIM_BAD: | 1552 | case -NFS4ERR_RECLAIM_BAD: |
| 1552 | case -NFS4ERR_RECLAIM_CONFLICT: | 1553 | case -NFS4ERR_RECLAIM_CONFLICT: |
