mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 13:51:44 +00:00
NFS client bugfixes for Linux 4.9 part 4
Stable Bugfixes: - Hide array-bounds warning Bugfixes: - Keep a reference on lock states while checking - Handle NFS4ERR_OLD_STATEID in nfs4_reclaim_open_state - Don't call close if the open stateid has already been cleared - Fix CLOSE rases with OPEN - Fix a regression in DELEGRETURN -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJYNhGKAAoJENfLVL+wpUDrGgEP/0okAGQfb7yHVNYjDpMmVh7u 6T1Vh+xbIMsGmuLXPOJH3FRFDnPWCrZO77K+l1y5oMl1fW/hA5h07yt0g0wT94+u if1wunZ6bak6KFeevo4xphpqXCjLhwpe801SbBcJPY6D6YxMckobHR8NcuzTjFab Kc9OAjnpIzS2lJBThaeyavGGnrlhNvH+Le+zEgMv/bSBTiPSymLlpj12a88cuHRF hx2vBao3UuR1vaTaZ5Zdp954DtNXNo7Pikye11cvVJVhesNwpZe37SszcRZ1U6P4 o4LnYf/ImkjDrcRyvFRxc6bu/Q1jLBuAYZjB4oMcx7YQW8rJqcS/UkEpGzOfER3i 3NQXFqacIAGhULfJxF8W0vPGzKM74koa0HRRI34C10qZAPe06Iy8slkdIjM4t2IX ASJI+uyrbIqTQ/x3FObWlqvw4TCOntYFpOsHF6G8M0uj+tX+3iXjpmwDGsJDVyFE y+egnnVn9LmGGfg1SBU2VBKL2945e/VAWfHtDGmJYgEwNDiqtutoIMDn+szESX60 yGLPJdIL3O7pTWmDXdSSpUJZ+wqa90rrU34kGmk3njydaNHeA1SEhcNTi2Ha5ALb NcVD0omnhrZUFE5MRY0OtmHRwhsaa9CYlMyqzb5SEeb46Z3KUm1KX9qEy4I4rZHG C4MlTY5AScHqqNXmT8Pu =YhQv -----END PGP SIGNATURE----- Merge tag 'nfs-for-4.9-4' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client bugfixes from Anna Schumaker: "Most of these fix regressions or races, but there is one patch for stable that Arnd sent me Stable bugfix: - Hide array-bounds warning Bugfixes: - Keep a reference on lock states while checking - Handle NFS4ERR_OLD_STATEID in nfs4_reclaim_open_state - Don't call close if the open stateid has already been cleared - Fix CLOSE rases with OPEN - Fix a regression in DELEGRETURN" * tag 'nfs-for-4.9-4' of git://git.linux-nfs.org/projects/anna/linux-nfs: NFSv4.x: hide array-bounds warning NFSv4.1: Keep a reference on lock states while checking NFSv4.1: Handle NFS4ERR_OLD_STATEID in nfs4_reclaim_open_state NFSv4: Don't call close if the open stateid has already been cleared NFSv4: Fix CLOSE races with OPEN NFSv4.1: Fix a regression in DELEGRETURN
This commit is contained in:
commit
10b9dd5686
@ -197,7 +197,7 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,
|
||||
}
|
||||
|
||||
ret = -EPROTONOSUPPORT;
|
||||
if (minorversion == 0)
|
||||
if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0)
|
||||
ret = nfs4_callback_up_net(serv, net);
|
||||
else if (xprt->ops->bc_up)
|
||||
ret = xprt->ops->bc_up(serv, net);
|
||||
|
@ -542,6 +542,13 @@ static inline bool nfs4_valid_open_stateid(const struct nfs4_state *state)
|
||||
return test_bit(NFS_STATE_RECOVERY_FAILED, &state->flags) == 0;
|
||||
}
|
||||
|
||||
static inline bool nfs4_state_match_open_stateid_other(const struct nfs4_state *state,
|
||||
const nfs4_stateid *stateid)
|
||||
{
|
||||
return test_bit(NFS_OPEN_STATE, &state->flags) &&
|
||||
nfs4_stateid_match_other(&state->open_stateid, stateid);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define nfs4_close_state(a, b) do { } while (0)
|
||||
|
@ -1451,7 +1451,6 @@ static void nfs_resync_open_stateid_locked(struct nfs4_state *state)
|
||||
}
|
||||
|
||||
static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
|
||||
nfs4_stateid *arg_stateid,
|
||||
nfs4_stateid *stateid, fmode_t fmode)
|
||||
{
|
||||
clear_bit(NFS_O_RDWR_STATE, &state->flags);
|
||||
@ -1469,10 +1468,9 @@ static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
|
||||
}
|
||||
if (stateid == NULL)
|
||||
return;
|
||||
/* Handle races with OPEN */
|
||||
if (!nfs4_stateid_match_other(arg_stateid, &state->open_stateid) ||
|
||||
(nfs4_stateid_match_other(stateid, &state->open_stateid) &&
|
||||
!nfs4_stateid_is_newer(stateid, &state->open_stateid))) {
|
||||
/* Handle OPEN+OPEN_DOWNGRADE races */
|
||||
if (nfs4_stateid_match_other(stateid, &state->open_stateid) &&
|
||||
!nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
|
||||
nfs_resync_open_stateid_locked(state);
|
||||
return;
|
||||
}
|
||||
@ -1486,7 +1484,9 @@ static void nfs_clear_open_stateid(struct nfs4_state *state,
|
||||
nfs4_stateid *stateid, fmode_t fmode)
|
||||
{
|
||||
write_seqlock(&state->seqlock);
|
||||
nfs_clear_open_stateid_locked(state, arg_stateid, stateid, fmode);
|
||||
/* Ignore, if the CLOSE argment doesn't match the current stateid */
|
||||
if (nfs4_state_match_open_stateid_other(state, arg_stateid))
|
||||
nfs_clear_open_stateid_locked(state, stateid, fmode);
|
||||
write_sequnlock(&state->seqlock);
|
||||
if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags))
|
||||
nfs4_schedule_state_manager(state->owner->so_server->nfs_client);
|
||||
@ -2564,15 +2564,23 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
|
||||
static int nfs41_check_expired_locks(struct nfs4_state *state)
|
||||
{
|
||||
int status, ret = NFS_OK;
|
||||
struct nfs4_lock_state *lsp;
|
||||
struct nfs4_lock_state *lsp, *prev = NULL;
|
||||
struct nfs_server *server = NFS_SERVER(state->inode);
|
||||
|
||||
if (!test_bit(LK_STATE_IN_USE, &state->flags))
|
||||
goto out;
|
||||
|
||||
spin_lock(&state->state_lock);
|
||||
list_for_each_entry(lsp, &state->lock_states, ls_locks) {
|
||||
if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
|
||||
struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
|
||||
|
||||
atomic_inc(&lsp->ls_count);
|
||||
spin_unlock(&state->state_lock);
|
||||
|
||||
nfs4_put_lock_state(prev);
|
||||
prev = lsp;
|
||||
|
||||
status = nfs41_test_and_free_expired_stateid(server,
|
||||
&lsp->ls_stateid,
|
||||
cred);
|
||||
@ -2585,10 +2593,14 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
|
||||
set_bit(NFS_LOCK_LOST, &lsp->ls_flags);
|
||||
} else if (status != NFS_OK) {
|
||||
ret = status;
|
||||
break;
|
||||
nfs4_put_lock_state(prev);
|
||||
goto out;
|
||||
}
|
||||
spin_lock(&state->state_lock);
|
||||
}
|
||||
};
|
||||
}
|
||||
spin_unlock(&state->state_lock);
|
||||
nfs4_put_lock_state(prev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -3122,7 +3134,8 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
|
||||
} else if (is_rdwr)
|
||||
calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
|
||||
|
||||
if (!nfs4_valid_open_stateid(state))
|
||||
if (!nfs4_valid_open_stateid(state) ||
|
||||
test_bit(NFS_OPEN_STATE, &state->flags) == 0)
|
||||
call_close = 0;
|
||||
spin_unlock(&state->owner->so_lock);
|
||||
|
||||
@ -5569,6 +5582,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
|
||||
switch (task->tk_status) {
|
||||
case 0:
|
||||
renew_lease(data->res.server, data->timestamp);
|
||||
break;
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_DELEG_REVOKED:
|
||||
case -NFS4ERR_EXPIRED:
|
||||
@ -5579,8 +5593,6 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
|
||||
case -NFS4ERR_OLD_STATEID:
|
||||
case -NFS4ERR_STALE_STATEID:
|
||||
task->tk_status = 0;
|
||||
if (data->roc)
|
||||
pnfs_roc_set_barrier(data->inode, data->roc_barrier);
|
||||
break;
|
||||
default:
|
||||
if (nfs4_async_handle_error(task, data->res.server,
|
||||
@ -5590,6 +5602,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
|
||||
}
|
||||
}
|
||||
data->rpc_status = task->tk_status;
|
||||
if (data->roc && data->rpc_status == 0)
|
||||
pnfs_roc_set_barrier(data->inode, data->roc_barrier);
|
||||
}
|
||||
|
||||
static void nfs4_delegreturn_release(void *calldata)
|
||||
|
@ -1547,6 +1547,7 @@ restart:
|
||||
ssleep(1);
|
||||
case -NFS4ERR_ADMIN_REVOKED:
|
||||
case -NFS4ERR_STALE_STATEID:
|
||||
case -NFS4ERR_OLD_STATEID:
|
||||
case -NFS4ERR_BAD_STATEID:
|
||||
case -NFS4ERR_RECLAIM_BAD:
|
||||
case -NFS4ERR_RECLAIM_CONFLICT:
|
||||
|
Loading…
Reference in New Issue
Block a user