summaryrefslogtreecommitdiff
path: root/block/blk-core.c
diff options
context:
space:
mode:
authorMing Lei <tom.leiming@gmail.com>2017-03-27 20:06:56 +0800
committerJens Axboe <axboe@fb.com>2017-03-29 08:03:42 -0600
commit5ed61d3f08d44937859dc537c5362ca293c98b04 (patch)
tree02802c310ece8ac247bb016c5d58555612eea76e /block/blk-core.c
parentd9d149a39690184f63d74e3425c1e90b1d7e67d6 (diff)
block: add a read barrier in blk_queue_enter()
Without the barrier, reading DEAD flag of .q_usage_counter and reading .mq_freeze_depth may be reordered, then the following wait_event_interruptible() may never return. Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Ming Lei <tom.leiming@gmail.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/blk-core.c')
-rw-r--r--block/blk-core.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 4234332aa23c..6373febc7716 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -669,6 +669,15 @@ int blk_queue_enter(struct request_queue *q, bool nowait)
if (nowait)
return -EBUSY;
+ /*
+ * read pair of barrier in blk_mq_freeze_queue_start(),
+ * we need to order reading __PERCPU_REF_DEAD flag of
+ * .q_usage_counter and reading .mq_freeze_depth,
+ * otherwise the following wait may never return if the
+ * two reads are reordered.
+ */
+ smp_rmb();
+
ret = wait_event_interruptible(q->mq_freeze_wq,
!atomic_read(&q->mq_freeze_depth) ||
blk_queue_dying(q));