forked from luck/tmp_suning_uos_patched
btrfs: Fix deadlock caused by missing memory barrier
Commit06297d8cef
("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:06297d8cef
("btrfs: switch extent_buffer blocking_writers from atomic to int") Tested-by: Johannes Thumshirn <jthumshirn@suse.com> Signed-off-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
373c3b80e4
commit
6e7ca09b58
|
@ -346,9 +346,12 @@ void btrfs_tree_unlock(struct extent_buffer *eb)
|
|||
if (blockers) {
|
||||
btrfs_assert_no_spinning_writers(eb);
|
||||
eb->blocking_writers--;
|
||||
/* Use the lighter barrier after atomic */
|
||||
smp_mb__after_atomic();
|
||||
cond_wake_up_nomb(&eb->write_lock_wq);
|
||||
/*
|
||||
* We need to order modifying blocking_writers above with
|
||||
* actually waking up the sleepers to ensure they see the
|
||||
* updated value of blocking_writers
|
||||
*/
|
||||
cond_wake_up(&eb->write_lock_wq);
|
||||
} else {
|
||||
btrfs_assert_spinning_writers_put(eb);
|
||||
write_unlock(&eb->lock);
|
||||
|
|
Loading…
Reference in New Issue
Block a user