Commit 
06297d8cefca ("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: 06297d8cefca ("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>
        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);