Skip to content

Commit 6e7ca09

Browse files
lorddoskiaskdave
authored andcommitted
btrfs: Fix deadlock caused by missing memory barrier
Commit 06297d8 ("btrfs: switch extent_buffer blocking_writers from atomic to int") changed the type of blocking_writers but forgot to adjust relevant code in btrfs_tree_unlock by converting the smp_mb__after_atomic to smp_mb. This opened up the possibility of a deadlock due to re-ordering of setting blocking_writers and checking/waking up the waiter. This particular lockup is explained in a comment above waitqueue_active() function. Fix it by converting the memory barrier to a full smp_mb, accounting for the fact that blocking_writers is a simple integer. Fixes: 06297d8 ("btrfs: switch extent_buffer blocking_writers from atomic to int") Tested-by: Johannes Thumshirn <[email protected]> Signed-off-by: Nikolay Borisov <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 373c3b8 commit 6e7ca09

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

fs/btrfs/locking.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,12 @@ void btrfs_tree_unlock(struct extent_buffer *eb)
346346
if (blockers) {
347347
btrfs_assert_no_spinning_writers(eb);
348348
eb->blocking_writers--;
349-
/* Use the lighter barrier after atomic */
350-
smp_mb__after_atomic();
351-
cond_wake_up_nomb(&eb->write_lock_wq);
349+
/*
350+
* We need to order modifying blocking_writers above with
351+
* actually waking up the sleepers to ensure they see the
352+
* updated value of blocking_writers
353+
*/
354+
cond_wake_up(&eb->write_lock_wq);
352355
} else {
353356
btrfs_assert_spinning_writers_put(eb);
354357
write_unlock(&eb->lock);

0 commit comments

Comments
 (0)