From b5fd1cdaf6710db54b7d56ce57b82587a6d4905c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 10 Mar 2025 15:17:07 +0000 Subject: [PATCH] Revert "block: Remove zone write plugs when handling native zone append writes" This reverts commit 2f572c42bb4beb5a67f93636a83ace5eb6b08aae which is commit a6aa36e957a1bfb5341986dec32d013d23228fe1 upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: I48f47a48084edfbca1f6e07fdde108f9c164aacf Signed-off-by: Greg Kroah-Hartman --- block/blk-zoned.c | 76 ++++-------------------------------------- include/linux/blkdev.h | 7 ++-- 2 files changed, 10 insertions(+), 73 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index c11db5be2532..767bcbce74fa 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -427,14 +427,13 @@ static bool disk_insert_zone_wplug(struct gendisk *disk, } } hlist_add_head_rcu(&zwplug->node, &disk->zone_wplugs_hash[idx]); - atomic_inc(&disk->nr_zone_wplugs); spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags); return true; } -static struct blk_zone_wplug *disk_get_hashed_zone_wplug(struct gendisk *disk, - sector_t sector) +static struct blk_zone_wplug *disk_get_zone_wplug(struct gendisk *disk, + sector_t sector) { unsigned int zno = disk_zone_no(disk, sector); unsigned int idx = hash_32(zno, disk->zone_wplugs_hash_bits); @@ -455,15 +454,6 @@ static struct blk_zone_wplug *disk_get_hashed_zone_wplug(struct gendisk *disk, return NULL; } -static inline struct blk_zone_wplug *disk_get_zone_wplug(struct gendisk *disk, - sector_t sector) -{ - if (!atomic_read(&disk->nr_zone_wplugs)) - return NULL; - - return disk_get_hashed_zone_wplug(disk, sector); -} - static void disk_free_zone_wplug_rcu(struct rcu_head *rcu_head) { struct blk_zone_wplug *zwplug = @@ -528,7 +518,6 @@ static void disk_remove_zone_wplug(struct gendisk *disk, zwplug->flags |= BLK_ZONE_WPLUG_UNHASHED; spin_lock_irqsave(&disk->zone_wplugs_lock, flags); hlist_del_init_rcu(&zwplug->node); - atomic_dec(&disk->nr_zone_wplugs); spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags); disk_put_zone_wplug(zwplug); } @@ -618,11 +607,6 @@ static void disk_zone_wplug_abort(struct blk_zone_wplug *zwplug) { struct bio *bio; - if (bio_list_empty(&zwplug->bio_list)) - return; - - pr_warn_ratelimited("%s: zone %u: Aborting plugged BIOs\n", - zwplug->disk->disk_name, zwplug->zone_no); while ((bio = bio_list_pop(&zwplug->bio_list))) blk_zone_wplug_bio_io_error(zwplug, bio); } @@ -1071,47 +1055,6 @@ plug: return true; } -static void blk_zone_wplug_handle_native_zone_append(struct bio *bio) -{ - struct gendisk *disk = bio->bi_bdev->bd_disk; - struct blk_zone_wplug *zwplug; - unsigned long flags; - - /* - * We have native support for zone append operations, so we are not - * going to handle @bio through plugging. However, we may already have a - * zone write plug for the target zone if that zone was previously - * partially written using regular writes. In such case, we risk leaving - * the plug in the disk hash table if the zone is fully written using - * zone append operations. Avoid this by removing the zone write plug. - */ - zwplug = disk_get_zone_wplug(disk, bio->bi_iter.bi_sector); - if (likely(!zwplug)) - return; - - spin_lock_irqsave(&zwplug->lock, flags); - - /* - * We are about to remove the zone write plug. But if the user - * (mistakenly) has issued regular writes together with native zone - * append, we must aborts the writes as otherwise the plugged BIOs would - * not be executed by the plug BIO work as disk_get_zone_wplug() will - * return NULL after the plug is removed. Aborting the plugged write - * BIOs is consistent with the fact that these writes will most likely - * fail anyway as there is no ordering guarantees between zone append - * operations and regular write operations. - */ - if (!bio_list_empty(&zwplug->bio_list)) { - pr_warn_ratelimited("%s: zone %u: Invalid mix of zone append and regular writes\n", - disk->disk_name, zwplug->zone_no); - disk_zone_wplug_abort(zwplug); - } - disk_remove_zone_wplug(disk, zwplug); - spin_unlock_irqrestore(&zwplug->lock, flags); - - disk_put_zone_wplug(zwplug); -} - /** * blk_zone_plug_bio - Handle a zone write BIO with zone write plugging * @bio: The BIO being submitted @@ -1168,10 +1111,8 @@ bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs) */ switch (bio_op(bio)) { case REQ_OP_ZONE_APPEND: - if (!bdev_emulates_zone_append(bdev)) { - blk_zone_wplug_handle_native_zone_append(bio); + if (!bdev_emulates_zone_append(bdev)) return false; - } fallthrough; case REQ_OP_WRITE: case REQ_OP_WRITE_ZEROES: @@ -1358,7 +1299,6 @@ static int disk_alloc_zone_resources(struct gendisk *disk, { unsigned int i; - atomic_set(&disk->nr_zone_wplugs, 0); disk->zone_wplugs_hash_bits = min(ilog2(pool_size) + 1, BLK_ZONE_WPLUG_MAX_HASH_BITS); @@ -1413,7 +1353,6 @@ static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk) } } - WARN_ON_ONCE(atomic_read(&disk->nr_zone_wplugs)); kfree(disk->zone_wplugs_hash); disk->zone_wplugs_hash = NULL; disk->zone_wplugs_hash_bits = 0; @@ -1631,12 +1570,11 @@ static int blk_revalidate_seq_zone(struct blk_zone *zone, unsigned int idx, } /* - * If the device needs zone append emulation, we need to track the - * write pointer of all zones that are not empty nor full. So make sure - * we have a zone write plug for such zone if the device has a zone - * write plug hash table. + * We need to track the write pointer of all zones that are not + * empty nor full. So make sure we have a zone write plug for + * such zone if the device has a zone write plug hash table. */ - if (!queue_emulates_zone_append(disk->queue) || !disk->zone_wplugs_hash) + if (!disk->zone_wplugs_hash) return 0; disk_zone_wplug_sync_wp_offset(disk, zone); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 0f17c872a806..1a182cb0333a 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -197,11 +197,10 @@ struct gendisk { unsigned int zone_capacity; unsigned int last_zone_capacity; unsigned long __rcu *conv_zones_bitmap; - unsigned int zone_wplugs_hash_bits; - atomic_t nr_zone_wplugs; - spinlock_t zone_wplugs_lock; + unsigned int zone_wplugs_hash_bits; + spinlock_t zone_wplugs_lock; struct mempool_s *zone_wplugs_pool; - struct hlist_head *zone_wplugs_hash; + struct hlist_head *zone_wplugs_hash; struct workqueue_struct *zone_wplugs_wq; #endif /* CONFIG_BLK_DEV_ZONED */