lkml.org 
[lkml]   [2016]   [Feb]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.10 30/54] nfs: Fix race in __update_open_stateid()
    Date
    3.10-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Andrew Elble <aweits@rit.edu>

    commit 361cad3c89070aeb37560860ea8bfc092d545adc upstream.

    We've seen this in a packet capture - I've intermixed what I
    think was going on. The fix here is to grab the so_lock sooner.

    1964379 -> #1 open (for write) reply seqid=1
    1964393 -> #2 open (for read) reply seqid=2

    __nfs4_close(), state->n_wronly--
    nfs4_state_set_mode_locked(), changes state->state = [R]
    state->flags is [RW]
    state->state is [R], state->n_wronly == 0, state->n_rdonly == 1

    1964398 -> #3 open (for write) call -> because close is already running
    1964399 -> downgrade (to read) call seqid=2 (close of #1)
    1964402 -> #3 open (for write) reply seqid=3

    __update_open_stateid()
    nfs_set_open_stateid_locked(), changes state->flags
    state->flags is [RW]
    state->state is [R], state->n_wronly == 0, state->n_rdonly == 1
    new sequence number is exposed now via nfs4_stateid_copy()

    next step would be update_open_stateflags(), pending so_lock

    1964403 -> downgrade reply seqid=2, fails with OLD_STATEID (close of #1)

    nfs4_close_prepare() gets so_lock and recalcs flags -> send close

    1964405 -> downgrade (to read) call seqid=3 (close of #1 retry)

    __update_open_stateid() gets so_lock
    * update_open_stateflags() updates state->n_wronly.
    nfs4_state_set_mode_locked() updates state->state

    state->flags is [RW]
    state->state is [RW], state->n_wronly == 1, state->n_rdonly == 1

    * should have suppressed the preceding nfs4_close_prepare() from
    sending open_downgrade

    1964406 -> write call
    1964408 -> downgrade (to read) reply seqid=4 (close of #1 retry)

    nfs_clear_open_stateid_locked()
    state->flags is [R]
    state->state is [RW], state->n_wronly == 1, state->n_rdonly == 1

    1964409 -> write reply (fails, openmode)

    Signed-off-by: Andrew Elble <aweits@rit.edu>
    Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/nfs/nfs4proc.c | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    --- a/fs/nfs/nfs4proc.c
    +++ b/fs/nfs/nfs4proc.c
    @@ -1005,6 +1005,7 @@ static void __update_open_stateid(struct
    * Protect the call to nfs4_state_set_mode_locked and
    * serialise the stateid update
    */
    + spin_lock(&state->owner->so_lock);
    write_seqlock(&state->seqlock);
    if (deleg_stateid != NULL) {
    nfs4_stateid_copy(&state->stateid, deleg_stateid);
    @@ -1013,7 +1014,6 @@ static void __update_open_stateid(struct
    if (open_stateid != NULL)
    nfs_set_open_stateid_locked(state, open_stateid, fmode);
    write_sequnlock(&state->seqlock);
    - spin_lock(&state->owner->so_lock);
    update_open_stateflags(state, fmode);
    spin_unlock(&state->owner->so_lock);
    }

    \
     
     \ /
      Last update: 2016-02-24 05:21    [W:3.371 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site