From 7b997e8faaa0e1b71ec4a20b7bed7d87cb047be5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 24 Mar 2021 10:27:52 +0100 Subject: [PATCH] block: simplify partition removal Always look up the first available entry instead of the complicated stateful traversal. Signed-off-by: Christoph Hellwig --- block/blk.h | 1 + block/genhd.c | 7 ++----- block/partitions/core.c | 21 +++++++++++++++++---- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/block/blk.h b/block/blk.h index 3b53e44b967e..07fe6220b9a0 100644 --- a/block/blk.h +++ b/block/blk.h @@ -352,6 +352,7 @@ int bdev_add_partition(struct block_device *bdev, int partno, int bdev_del_partition(struct block_device *bdev, int partno); int bdev_resize_partition(struct block_device *bdev, int partno, sector_t start, sector_t length); +struct block_device *first_partition(struct gendisk *disk); int bio_add_hw_page(struct request_queue *q, struct bio *bio, struct page *page, unsigned int len, unsigned int offset, diff --git a/block/genhd.c b/block/genhd.c index fcc530164b5a..6f94e8fdab30 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -682,7 +682,6 @@ static void invalidate_partition(struct block_device *bdev) */ void del_gendisk(struct gendisk *disk) { - struct disk_part_iter piter; struct block_device *part; might_sleep(); @@ -699,13 +698,11 @@ void del_gendisk(struct gendisk *disk) */ down_write(&bdev_lookup_sem); - /* invalidate stuff */ - disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY); - while ((part = disk_part_iter_next(&piter))) { + while ((part = first_partition(disk))) { invalidate_partition(part); delete_partition(part); + bdput(part); } - disk_part_iter_exit(&piter); invalidate_partition(disk->part0); set_capacity(disk, 0); diff --git a/block/partitions/core.c b/block/partitions/core.c index f3d9ff2cafb6..78eb20862edf 100644 --- a/block/partitions/core.c +++ b/block/partitions/core.c @@ -528,9 +528,22 @@ static bool disk_unlock_native_capacity(struct gendisk *disk) } } +struct block_device *first_partition(struct gendisk *disk) +{ + struct block_device *part; + unsigned long idx = 1; /* 0 is the whole device */ + + rcu_read_lock(); + part = xa_find(&disk->part_tbl, &idx, ULONG_MAX, XA_PRESENT); + if (part && !bdgrab(part)) + part = NULL; + rcu_read_unlock(); + + return part; +} + int blk_drop_partitions(struct block_device *bdev) { - struct disk_part_iter piter; struct block_device *part; if (bdev->bd_part_count) @@ -539,10 +552,10 @@ int blk_drop_partitions(struct block_device *bdev) sync_blockdev(bdev); invalidate_bdev(bdev); - disk_part_iter_init(&piter, bdev->bd_disk, DISK_PITER_INCL_EMPTY); - while ((part = disk_part_iter_next(&piter))) + while ((part = first_partition(bdev->bd_disk))) { delete_partition(part); - disk_part_iter_exit(&piter); + bdput(part); + } return 0; } -- 2.50.1