summaryrefslogtreecommitdiff
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorChris Mason <clm@fb.com>2015-10-13 02:24:40 +0300
committerChris Mason <clm@fb.com>2015-10-13 02:24:40 +0300
commit6db4a7335dd701a0e20275440ee057d3db2a7ae3 (patch)
treec0734d7411806ef91bfeb615bf528ffb349938fe /fs/btrfs/transaction.c
parent62fb50ab7c903357c92cef2f7677235b92ac575f (diff)
parentee86395458072760d62e66aad10a5e9e8902b8cf (diff)
downloadlinux-6db4a7335dd701a0e20275440ee057d3db2a7ae3.tar.xz
Merge branch 'fix/waitqueue-barriers' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux into for-linus-4.4
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 76354bb1312c..47fd27031a20 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -82,6 +82,12 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
static void clear_btree_io_tree(struct extent_io_tree *tree)
{
spin_lock(&tree->lock);
+ /*
+ * Do a single barrier for the waitqueue_active check here, the state
+ * of the waitqueue should not change once clear_btree_io_tree is
+ * called.
+ */
+ smp_mb();
while (!RB_EMPTY_ROOT(&tree->state)) {
struct rb_node *node;
struct extent_state *state;
@@ -856,6 +862,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
atomic_dec(&cur_trans->num_writers);
extwriter_counter_dec(cur_trans, trans->type);
+ /*
+ * Make sure counter is updated before we wake up waiters.
+ */
smp_mb();
if (waitqueue_active(&cur_trans->writer_wait))
wake_up(&cur_trans->writer_wait);