From: Yufen Yu yuyufen@huawei.com
hulk inclusion category: bugfix bugzilla: 46860
--------------------------------
Drivers (such as scsi enclosure) will not call blk_register_queue() to do initialize for request_queue. And we rely on driver self to deal with the race in that case when cleanup queue.
But, some self-developed drivers cannot deal the race. To avoid null pointer reference as following, we do quiesce in kernel.
[67760.308034] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 ... [67760.308069] pc : blk_mq_do_dispatch_sched+0x94/0x130 [67760.308072] lr : blk_mq_sched_dispatch_requests+0x128/0x1f0 [67760.308072] sp : ffff0000b2bb3ca0 [67760.308073] x29: ffff0000b2bb3ca0 x28: 0000000000000000 [67760.308075] x27: 0000000000000000 x26: ffff00008128a000 [67760.308076] x25: ffff8042b13e9700 x24: 0000000000000000 [67760.308077] x23: ffff0000b2bb3cf8 x22: ffff8042b2976808 [67760.308078] x21: ffff0000b2bb3d58 x20: ffff00008128a000 [67760.308079] x19: ffff8042b2976800 x18: 0000000000000000 [67760.308080] x17: 0000000000000000 x16: 0000000000000000 [67760.308081] x15: 0000000000000000 x14: 0000000000000000 [67760.308082] x13: 0000000000000000 x12: 0000000000000000 [67760.308084] x11: ffff800040801004 x10: ffff80004080100c [67760.308085] x9 : 0000000000000060 x8 : ffff809e58f7e500 [67760.308087] x7 : 0000000000000000 x6 : 00000000ffffffff [67760.308088] x5 : ffff000080ab7550 x4 : ffff80418e84ec80 [67760.308089] x3 : ffff0000815d7f10 x2 : 94e133dc71839c00 [67760.308090] x1 : 0000000000000000 x0 : ffff00008128a748 [67760.308091] Call trace: [67760.308093] blk_mq_do_dispatch_sched+0x94/0x130 [67760.308095] blk_mq_sched_dispatch_requests+0x128/0x1f0 [67760.308096] __blk_mq_run_hw_queue+0x98/0x138 [67760.308097] blk_mq_run_work_fn+0x28/0x38
Signed-off-by: Yufen Yu yuyufen@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- block/blk-core.c | 7 +++++-- drivers/scsi/scsi_scan.c | 4 ++++ include/linux/blkdev.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c index 1d26f5da4113f..528c53592aa2e 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -791,9 +791,12 @@ void blk_cleanup_queue(struct request_queue *q) * from more than one contexts. * * We rely on driver to deal with the race in case that queue - * initialization isn't done. + * initialization isn't done. If driver cannot deal the race, + * we try to call quiesce in kernel for these drivers that have + * set QUEUE_FLAG_FORECE_QUIESCE flag. */ - if (q->mq_ops && blk_queue_init_done(q)) + if (q->mq_ops && (blk_queue_init_done(q) || + test_bit(QUEUE_FLAG_FORECE_QUIESCE, &q->queue_flags))) blk_mq_quiesce_queue(q);
/* for synchronous bio-based driver finish in-flight integrity i/o */ diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 009a5b2aa3d02..27610816ccb8d 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -844,6 +844,10 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, *bflags |= BLIST_NOREPORTLUN; }
+ if (sdev->type == TYPE_ENCLOSURE) + set_bit(QUEUE_FLAG_FORECE_QUIESCE, + &sdev->request_queue->queue_flags); + /* * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI * spec says: The device server is capable of supporting the diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 0754ad98db1ff..de83f2f96ec87 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -726,6 +726,7 @@ struct request_queue { #define QUEUE_FLAG_SCSI_PASSTHROUGH 27 /* queue supports SCSI commands */ #define QUEUE_FLAG_QUIESCED 28 /* queue has been quiesced */ #define QUEUE_FLAG_RQ_ALLOC_TIME 27 /* record rq->alloc_time_ns */ +#define QUEUE_FLAG_FORECE_QUIESCE 29 /* force quiesce when cleanup queue */
#define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_SAME_COMP) | \