blk_mark_disk_dead() reports disk death even when GD_DEAD is already set. For example, NVMe reset failure and subsequent namespace removal can call it twice, repeating holder mark_dead callbacks. Only report disk death when __blk_mark_disk_dead() first sets GD_DEAD. Keep its existing return value for queue drain handling in __del_gendisk(). Fixes: d8530de5a6e8 ("block: call into the file system for bdev_mark_dead") Signed-off-by: Avi Weiss --- block/genhd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 10ca8b4d6eea..a511fc192174 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -657,13 +657,15 @@ static void blk_report_disk_dead(struct gendisk *disk, bool surprise) rcu_read_unlock(); } -static bool __blk_mark_disk_dead(struct gendisk *disk) +static bool __blk_mark_disk_dead(struct gendisk *disk, bool *newly_dead) { /* * Fail any new I/O. */ if (test_and_set_bit(GD_DEAD, &disk->state)) return false; + if (newly_dead) + *newly_dead = true; if (test_bit(GD_OWNS_QUEUE, &disk->state)) blk_queue_flag_set(QUEUE_FLAG_DYING, disk->queue); @@ -688,9 +690,12 @@ static bool __blk_mark_disk_dead(struct gendisk *disk) */ void blk_mark_disk_dead(struct gendisk *disk) { + bool newly_dead = false; + blk_queue_flag_set(QUEUE_FLAG_DYING, disk->queue); - __blk_mark_disk_dead(disk); - blk_report_disk_dead(disk, true); + __blk_mark_disk_dead(disk, &newly_dead); + if (newly_dead) + blk_report_disk_dead(disk, true); } EXPORT_SYMBOL_GPL(blk_mark_disk_dead); @@ -727,7 +732,7 @@ static void __del_gendisk(struct gendisk *disk) * Drop all partitions now that the disk is marked dead. */ mutex_lock(&disk->open_mutex); - start_drain = __blk_mark_disk_dead(disk); + start_drain = __blk_mark_disk_dead(disk, NULL); if (start_drain) blk_freeze_acquire_lock(q); xa_for_each_start(&disk->part_tbl, idx, part, 1) base-commit: 36aad21d50d1af3f6954bb0c988257a908202477 -- 2.43.0