Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

block: fix surprise removal for drivers calling blk_set_queue_dying

Various block drivers call blk_set_queue_dying to mark a disk as dead due
to surprise removal events, but since commit 8e141f9eb803 that doesn't
work given that the GD_DEAD flag needs to be set to stop I/O.

Replace the driver calls to blk_set_queue_dying with a new (and properly
documented) blk_mark_disk_dead API, and fold blk_set_queue_dying into the
only remaining caller.

Fixes: 8e141f9eb803 ("block: drain file system I/O on del_gendisk")
Reported-by: Markus Blöchl <markus.bloechl@ipetronik.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Link: https://lore.kernel.org/r/20220217075231.1140-1-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
7a5428dc cc8f7fe1

+24 -15
+2 -8
block/blk-core.c
··· 284 284 wake_up_all(&q->mq_freeze_wq); 285 285 } 286 286 287 - void blk_set_queue_dying(struct request_queue *q) 288 - { 289 - blk_queue_flag_set(QUEUE_FLAG_DYING, q); 290 - blk_queue_start_drain(q); 291 - } 292 - EXPORT_SYMBOL_GPL(blk_set_queue_dying); 293 - 294 287 /** 295 288 * blk_cleanup_queue - shutdown a request queue 296 289 * @q: request queue to shutdown ··· 301 308 WARN_ON_ONCE(blk_queue_registered(q)); 302 309 303 310 /* mark @q DYING, no new request or merges will be allowed afterwards */ 304 - blk_set_queue_dying(q); 311 + blk_queue_flag_set(QUEUE_FLAG_DYING, q); 312 + blk_queue_start_drain(q); 305 313 306 314 blk_queue_flag_set(QUEUE_FLAG_NOMERGES, q); 307 315 blk_queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
+14
block/genhd.c
··· 549 549 EXPORT_SYMBOL(device_add_disk); 550 550 551 551 /** 552 + * blk_mark_disk_dead - mark a disk as dead 553 + * @disk: disk to mark as dead 554 + * 555 + * Mark as disk as dead (e.g. surprise removed) and don't accept any new I/O 556 + * to this disk. 557 + */ 558 + void blk_mark_disk_dead(struct gendisk *disk) 559 + { 560 + set_bit(GD_DEAD, &disk->state); 561 + blk_queue_start_drain(disk->queue); 562 + } 563 + EXPORT_SYMBOL_GPL(blk_mark_disk_dead); 564 + 565 + /** 552 566 * del_gendisk - remove the gendisk 553 567 * @disk: the struct gendisk to remove 554 568 *
+1 -1
drivers/block/mtip32xx/mtip32xx.c
··· 4112 4112 "Completion workers still active!\n"); 4113 4113 } 4114 4114 4115 - blk_set_queue_dying(dd->queue); 4115 + blk_mark_disk_dead(dd->disk); 4116 4116 set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); 4117 4117 4118 4118 /* Clean up the block layer. */
+1 -1
drivers/block/rbd.c
··· 7185 7185 * IO to complete/fail. 7186 7186 */ 7187 7187 blk_mq_freeze_queue(rbd_dev->disk->queue); 7188 - blk_set_queue_dying(rbd_dev->disk->queue); 7188 + blk_mark_disk_dead(rbd_dev->disk); 7189 7189 } 7190 7190 7191 7191 del_gendisk(rbd_dev->disk);
+1 -1
drivers/block/xen-blkfront.c
··· 2126 2126 2127 2127 /* No more blkif_request(). */ 2128 2128 blk_mq_stop_hw_queues(info->rq); 2129 - blk_set_queue_dying(info->rq); 2129 + blk_mark_disk_dead(info->gd); 2130 2130 set_capacity(info->gd, 0); 2131 2131 2132 2132 for_each_rinfo(info, rinfo, i) {
+1 -1
drivers/md/dm.c
··· 2077 2077 set_bit(DMF_FREEING, &md->flags); 2078 2078 spin_unlock(&_minor_lock); 2079 2079 2080 - blk_set_queue_dying(md->queue); 2080 + blk_mark_disk_dead(md->disk); 2081 2081 2082 2082 /* 2083 2083 * Take suspend_lock so that presuspend and postsuspend methods
+1 -1
drivers/nvme/host/core.c
··· 4574 4574 if (test_and_set_bit(NVME_NS_DEAD, &ns->flags)) 4575 4575 return; 4576 4576 4577 - blk_set_queue_dying(ns->queue); 4577 + blk_mark_disk_dead(ns->disk); 4578 4578 nvme_start_ns_queue(ns); 4579 4579 4580 4580 set_capacity_and_notify(ns->disk, 0);
+1 -1
drivers/nvme/host/multipath.c
··· 848 848 { 849 849 if (!head->disk) 850 850 return; 851 - blk_set_queue_dying(head->disk->queue); 851 + blk_mark_disk_dead(head->disk); 852 852 /* make sure all pending bios are cleaned up */ 853 853 kblockd_schedule_work(&head->requeue_work); 854 854 flush_work(&head->requeue_work);
+2 -1
include/linux/blkdev.h
··· 748 748 749 749 bool __must_check blk_get_queue(struct request_queue *); 750 750 extern void blk_put_queue(struct request_queue *); 751 - extern void blk_set_queue_dying(struct request_queue *); 751 + 752 + void blk_mark_disk_dead(struct gendisk *disk); 752 753 753 754 #ifdef CONFIG_BLOCK 754 755 /*