All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] btrfs: fix waitqueue_active without memory barrier in btrfs
@ 2015-10-09  0:35 Kosuke Tatsukawa
  2015-10-09  4:32 ` Josef Bacik
  2015-10-09 14:21 ` David Sterba
  0 siblings, 2 replies; 5+ messages in thread
From: Kosuke Tatsukawa @ 2015-10-09  0:35 UTC (permalink / raw)
  To: Chris Mason, Josef Bacik, David Sterba
  Cc: linux-btrfs@vger.kernel.org, linux-kernel@vger.kernel.org

btrfs_bio_counter_sub() seems to be missing a memory barrier which might
cause the waker to not notice the waiter and miss sending a wake_up as
in the following figure.

	btrfs_bio_counter_sub			btrfs_rm_dev_replace_blocked
------------------------------------------------------------------------
if (waitqueue_active(&fs_info->replace_wait))
/* The CPU might reorder the test for
   the waitqueue up here, before
   prior writes complete */
					/* wait_event */
					 /* __wait_event */
					  /* ___wait_event */
					  long __int = prepare_to_wait_event(&wq,
					    &__wait, state);
					  if (!percpu_counter_sum(&fs_info->bio_counter))
percpu_counter_sub(&fs_info->bio_counter,
  amount);
					  schedule()
------------------------------------------------------------------------

This patch removes the call to waitqueue_active() leaving just wake_up()
behind.  This fixes the problem because the call to spin_lock_irqsave()
in wake_up() will be an ACQUIRE operation.

I found this issue when I was looking through the linux source code
for places calling waitqueue_active() before wake_up*(), but without
preceding memory barriers, after sending a patch to fix a similar
issue in drivers/tty/n_tty.c  (Details about the original issue can be
found here: https://lkml.org/lkml/2015/9/28/849).

Signed-off-by: Kosuke Tatsukawa <tatsu@ab.jp.nec.com>
---
 fs/btrfs/dev-replace.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index e54dd59..ecb3e71 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -918,9 +918,7 @@ void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info)
 void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount)
 {
 	percpu_counter_sub(&fs_info->bio_counter, amount);
-
-	if (waitqueue_active(&fs_info->replace_wait))
-		wake_up(&fs_info->replace_wait);
+	wake_up(&fs_info->replace_wait);
 }
 
 void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-10-10  5:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-09  0:35 [PATCH] btrfs: fix waitqueue_active without memory barrier in btrfs Kosuke Tatsukawa
2015-10-09  4:32 ` Josef Bacik
2015-10-09  4:50   ` Kosuke Tatsukawa
2015-10-09 14:21 ` David Sterba
2015-10-10  5:03   ` Kosuke Tatsukawa

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.