Patch "nfs: Fix race in __update_open_stateid()" has been added to the 3.10-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
nfs: Fix race in __update_open_stateid()
to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
nfs-fix-race-in-__update_open_stateid.patch
and it can be found in the queue-3.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
361cad3c89070aeb37560860ea8bfc092d545adcMon Sep 17 00:00:00 2001
From: Andrew Elble <[email protected]>
Date: Wed, 2 Dec 2015 09:20:57 -0500
Subject: nfs: Fix race in __update_open_stateid()
From: Andrew Elble <[email protected]>
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)
--- fs/nfs/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfs/nfs4proc.c +1 -1
@@ -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(structif (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); }
Patches currently in stable-queue which might be from [email protected] are
queue-3.10/nfs-fix-race-in-__update_open_stateid.patch