Clean up: The logic for dealing with a delegation state ID and an open state ID is now sufficiently distinct that I've refactored nfs41_check_expired_stateid() into two separate functions. Instead of open-coded flag manipulation, use test_bit() and clear_bit() just like all other accessors of the state->flag field. This also eliminates several unnecessary implicit integer type conversions. Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- fs/nfs/nfs4proc.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 files changed, 35 insertions(+), 9 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4bc21a3..f368e37 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1757,19 +1757,46 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta #if defined(CONFIG_NFS_V4_1) /** - * nfs41_check_expired_stateid - does a state ID need recovery? + * nfs41_clear_delegation_stateid - possibly clear revoked delegation state ID + * + * @state: NFSv4 open state for an inode + */ +static void nfs41_clear_delegation_stateid(struct nfs4_state *state) +{ + struct nfs_server *server = NFS_SERVER(state->inode); + nfs4_stateid *stateid = &state->stateid; + + if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) + switch (nfs41_test_stateid(server, stateid)) { + case NFS_OK: + /* delegation still OK, preserve it */ + break; + case -NFS4ERR_ADMIN_REVOKED: + case -NFS4ERR_DELEG_REVOKED: + /* delegation was revoked, must free */ + nfs41_free_stateid(server, stateid); + default: + clear_bit(NFS_DELEGATED_STATE, &state->flags); + } +} + +/** + * nfs41_check_open_stateid - clear open state ID * * @state: NFSv4 open state for an inode * * Returns NFS_OK if recovery for this state ID is now finished. * Otherwise a negative NFS4ERR value is returned. */ -static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *stateid, unsigned int flags) +static int nfs41_check_open_stateid(struct nfs4_state *state) { struct nfs_server *server = NFS_SERVER(state->inode); + nfs4_stateid *stateid = &state->stateid; int status = -NFS4ERR_BAD_STATEID; - if (state->flags & flags) { + if ((test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) || + (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) || + (test_bit(NFS_O_RDWR_STATE, &state->flags) != 0)) { status = nfs41_test_stateid(server, stateid); switch (status) { case NFS_OK: @@ -1781,7 +1808,9 @@ static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *s nfs41_free_stateid(server, stateid); default: /* anything else: just re-open it */ - state->flags &= ~flags; + clear_bit(NFS_O_RDONLY_STATE, &state->flags); + clear_bit(NFS_O_WRONLY_STATE, &state->flags); + clear_bit(NFS_O_RDWR_STATE, &state->flags); } } return status; @@ -1789,13 +1818,10 @@ static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *s static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) { - int deleg_flags = 1 << NFS_DELEGATED_STATE; - int open_flags = (1 << NFS_O_RDONLY_STATE) | (1 << NFS_O_WRONLY_STATE) | (1 << NFS_O_RDWR_STATE); int status; - nfs41_check_expired_stateid(state, &state->stateid, deleg_flags); - status = nfs41_check_expired_stateid(state, &state->open_stateid, - open_flags); + nfs41_clear_delegation_stateid(state); + status = nfs41_check_open_stateid(state); if (status != NFS_OK) status = nfs4_open_expired(sp, state); -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html