summaryrefslogtreecommitdiff
path: root/block/blk-zoned.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2025-11-05 14:52:14 -0500
committerJens Axboe <axboe@kernel.dk>2025-11-06 16:15:27 -0700
commitc6886cf610f4bb0b8aa6b88ab013a042e317f898 (patch)
treedd7bff32b6df9153ef24671d83410b73af2ec9fa /block/blk-zoned.c
parentba13710ddd1f47884701213a3b6a5e470f6bc81e (diff)
block: don't leak disk->zones_cond for !disk_need_zone_resources
disk->zones_cond is allocated for all zoned devices, but disk_free_zone_resources skips it when the zone write plug hash is not allocated, leaking the allocation for non-mq devices that don't emulate zone append. This is reported by kmemleak-enabled xfstests for various tests that use simple device mapper targets. Fix this by moving all code that requires writes plugs from disk_free_zone_resources into disk_destroy_zone_wplugs_hash_table and executing the rest of the code, including the disk->zones_cond freeing unconditionally. Fixes: 6e945ffb6555 ("block: use zone condition to determine conventional zones") Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-zoned.c')
-rw-r--r--block/blk-zoned.c20
1 files changed, 8 insertions, 12 deletions
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index bba64b427082..a0ce17e2143f 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -1834,6 +1834,14 @@ static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk)
kfree(disk->zone_wplugs_hash);
disk->zone_wplugs_hash = NULL;
disk->zone_wplugs_hash_bits = 0;
+
+ /*
+ * Wait for the zone write plugs to be RCU-freed before destroying the
+ * mempool.
+ */
+ rcu_barrier();
+ mempool_destroy(disk->zone_wplugs_pool);
+ disk->zone_wplugs_pool = NULL;
}
static void disk_set_zones_cond_array(struct gendisk *disk, u8 *zones_cond)
@@ -1850,9 +1858,6 @@ static void disk_set_zones_cond_array(struct gendisk *disk, u8 *zones_cond)
void disk_free_zone_resources(struct gendisk *disk)
{
- if (!disk->zone_wplugs_pool)
- return;
-
if (disk->zone_wplugs_wq) {
destroy_workqueue(disk->zone_wplugs_wq);
disk->zone_wplugs_wq = NULL;
@@ -1860,15 +1865,6 @@ void disk_free_zone_resources(struct gendisk *disk)
disk_destroy_zone_wplugs_hash_table(disk);
- /*
- * Wait for the zone write plugs to be RCU-freed before
- * destorying the mempool.
- */
- rcu_barrier();
-
- mempool_destroy(disk->zone_wplugs_pool);
- disk->zone_wplugs_pool = NULL;
-
disk_set_zones_cond_array(disk, NULL);
disk->zone_capacity = 0;
disk->last_zone_capacity = 0;