Commit 7a5428dc authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

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 8e141f9e 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: 8e141f9e ("block: drain file system I/O on del_gendisk")
Reported-by: default avatarMarkus Blöchl <markus.bloechl@ipetronik.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarSagi Grimberg <sagi@grimberg.me>
Link: https://lore.kernel.org/r/20220217075231.1140-1-hch@lst.de


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent cc8f7fe1
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -284,13 +284,6 @@ void blk_queue_start_drain(struct request_queue *q)
	wake_up_all(&q->mq_freeze_wq);
}

void blk_set_queue_dying(struct request_queue *q)
{
	blk_queue_flag_set(QUEUE_FLAG_DYING, q);
	blk_queue_start_drain(q);
}
EXPORT_SYMBOL_GPL(blk_set_queue_dying);

/**
 * blk_cleanup_queue - shutdown a request queue
 * @q: request queue to shutdown
@@ -308,7 +301,8 @@ void blk_cleanup_queue(struct request_queue *q)
	WARN_ON_ONCE(blk_queue_registered(q));

	/* mark @q DYING, no new request or merges will be allowed afterwards */
	blk_set_queue_dying(q);
	blk_queue_flag_set(QUEUE_FLAG_DYING, q);
	blk_queue_start_drain(q);

	blk_queue_flag_set(QUEUE_FLAG_NOMERGES, q);
	blk_queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
+14 −0
Original line number Diff line number Diff line
@@ -548,6 +548,20 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
}
EXPORT_SYMBOL(device_add_disk);

/**
 * blk_mark_disk_dead - mark a disk as dead
 * @disk: disk to mark as dead
 *
 * Mark as disk as dead (e.g. surprise removed) and don't accept any new I/O
 * to this disk.
 */
void blk_mark_disk_dead(struct gendisk *disk)
{
	set_bit(GD_DEAD, &disk->state);
	blk_queue_start_drain(disk->queue);
}
EXPORT_SYMBOL_GPL(blk_mark_disk_dead);

/**
 * del_gendisk - remove the gendisk
 * @disk: the struct gendisk to remove
+1 −1
Original line number Diff line number Diff line
@@ -4112,7 +4112,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
			"Completion workers still active!\n");
	}

	blk_set_queue_dying(dd->queue);
	blk_mark_disk_dead(dd->disk);
	set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);

	/* Clean up the block layer. */
+1 −1
Original line number Diff line number Diff line
@@ -7185,7 +7185,7 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
		 * IO to complete/fail.
		 */
		blk_mq_freeze_queue(rbd_dev->disk->queue);
		blk_set_queue_dying(rbd_dev->disk->queue);
		blk_mark_disk_dead(rbd_dev->disk);
	}

	del_gendisk(rbd_dev->disk);
+1 −1
Original line number Diff line number Diff line
@@ -2126,7 +2126,7 @@ static void blkfront_closing(struct blkfront_info *info)

	/* No more blkif_request(). */
	blk_mq_stop_hw_queues(info->rq);
	blk_set_queue_dying(info->rq);
	blk_mark_disk_dead(info->gd);
	set_capacity(info->gd, 0);

	for_each_rinfo(info, rinfo, i) {
Loading