The logic was becoming difficult to follow. Add some comments and local variables to clarify the behavior. Signed-off-by: Benjamin Coddington <bcodding@xxxxxxxxxx> --- fs/nfs/nfs4proc.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9ced7a62c05e..499f978d48aa 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1568,23 +1568,34 @@ static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state) static bool nfs_need_update_open_stateid(struct nfs4_state *state, const nfs4_stateid *stateid) { - if (test_bit(NFS_OPEN_STATE, &state->flags) == 0 || - !nfs4_stateid_match_other(stateid, &state->open_stateid)) { - if (stateid->seqid == cpu_to_be32(1)) { + bool state_matches_other = nfs4_stateid_match_other(stateid, &state->open_stateid); + bool seqid_one = stateid->seqid == cpu_to_be32(1); + + if (test_bit(NFS_OPEN_STATE, &state->flags)) { + /* The common case - we're updating to a new sequence number */ + if (state_matches_other && nfs4_stateid_is_newer(stateid, &state->open_stateid)) { + nfs_state_log_out_of_order_open_stateid(state, stateid); + return true; + } + /* We lost a race with a self-bumping close, do recovery */ + if (!state_matches_other) { + trace_printk("lost race to self-bump close\n"); + return false; + } + } else { + /* The common case, this is the first OPEN */ + if (!state_matches_other && seqid_one) { nfs_state_log_update_open_stateid(state); - } else { - if (!nfs4_stateid_match_other(stateid, &state->open_stateid)) - return false; - else - set_bit(NFS_STATE_CHANGE_WAIT, &state->flags); + return true; + } + /* We lost a race either with a self-bumping close, OR with the first OPEN */ + if (!state_matches_other && !seqid_one) { + trace_printk("lost race to self-bump close OR first OPEN\n"); + set_bit(NFS_STATE_CHANGE_WAIT, &state->flags); + return true; } - return true; - } - - if (nfs4_stateid_is_newer(stateid, &state->open_stateid)) { - nfs_state_log_out_of_order_open_stateid(state, stateid); - return true; } + /* Should be impossible to reach: */ return false; } -- 2.20.1