linux-next: manual merge of the block tree with the scsi-fixes tree

From: Mark Brown

Date: Thu Sep 17 2026 - 12:09:14 EST


Hi all,

Today's linux-next merge of the block tree got a conflict in:

block/blk-zoned.c

between commit:

7c431d61b69a3 ("scsi: block: Fix zones_cond out-of-bounds write on zone report")

from the scsi-fixes tree and commit:

670a7da6359f2 ("block: refactor disk_revalidate_zone_resources()")

from the block tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

Note that I'm very unconvinced by this merge.

diff --cc block/blk-zoned.c
index 475aa16bc41a5,ec510d66dfe2b..0000000000000
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@@ -2014,46 -2192,18 +2192,20 @@@ struct blk_revalidate_zone_args
sector_t sector;
};

- static int disk_revalidate_zone_resources(struct gendisk *disk,
- struct blk_revalidate_zone_args *args)
+ static int disk_init_revalidate_args(struct gendisk *disk,
+ struct blk_revalidate_zone_args *args)
{
- struct queue_limits *lim = &disk->queue->limits;
- unsigned long long nr_zones;
- unsigned int pool_size;
- int ret = 0;
-
args->disk = disk;
- nr_zones = DIV_ROUND_UP_ULL(get_capacity(disk), lim->chunk_sectors);
- if (nr_zones > UINT_MAX) {
- pr_warn("%s: Too many zones (%llu)\n", disk->disk_name, nr_zones);
+ args->nr_zones = disk_get_nr_zones(disk, args->capacity);
++ if (args->nr_zones > UINT_MAX)
+ return -EINVAL;
- }
- args->nr_zones = nr_zones;

/* Cached zone conditions: 1 byte per zone */
- args->zones_cond = kzalloc(args->nr_zones, GFP_NOIO);
- if (!args->zones_cond)
+ args->zones_state = kzalloc(args->nr_zones, GFP_NOIO);
+ if (!args->zones_state)
return -ENOMEM;

- if (!disk_need_zone_resources(disk))
- return 0;
-
- /*
- * If the device has no limit on the maximum number of open and active
- * zones, use BLK_ZONE_WPLUG_DEFAULT_POOL_SIZE.
- */
- pool_size = max(lim->max_open_zones, lim->max_active_zones);
- if (!pool_size)
- pool_size =
- min(BLK_ZONE_WPLUG_DEFAULT_POOL_SIZE, args->nr_zones);
-
- if (!disk->zone_wplugs_hash) {
- ret = disk_alloc_zone_resources(disk, pool_size);
- if (ret)
- kfree(args->zones_cond);
- }
-
- return ret;
+ return 0;
}

/*
@@@ -2131,48 -2307,54 +2309,47 @@@ unfreeze
return ret;
}

- static int blk_revalidate_zone_cond(struct blk_zone *zone, unsigned int idx,
+ static void disk_drop_zone_wplug(struct blk_zone_wplug *zwplug, void *data)
+ {
+ unsigned long flags;
+
+ spin_lock_irqsave(&zwplug->lock, flags);
+ disk_zone_wplug_abort(zwplug);
+ disk_mark_zone_wplug_dead(zwplug);
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+ }
+
+ static int disk_revalidate_capacity(struct gendisk *disk,
struct blk_revalidate_zone_args *args)
{
- enum blk_zone_cond cond = zone->cond;
- struct queue_limits *lim = &disk->queue->limits;
- sector_t zone_sectors = lim->chunk_sectors;
+ unsigned int nr_zones;
+ int ret = -ENODEV;

- if (idx >= args->nr_zones) {
- pr_warn("%s: Zone report index %u exceeds zone count %u\n",
- args->disk->disk_name, idx, args->nr_zones);
- return -EINVAL;
- /* Checks that the device driver indicated a valid zone size. */
- if (!zone_sectors || !is_power_of_2(zone_sectors)) {
- pr_warn("%s: Invalid non power of two zone size (%llu)\n",
- disk->disk_name, zone_sectors);
- goto drop_all_zwplugs;
- }
-
+ args->capacity = get_capacity(disk);
+ nr_zones = disk_get_nr_zones(disk, args->capacity);
+ if (!args->capacity || !nr_zones)
+ goto drop_all_zwplugs;
++ if (args->capacity >= args->nr_zones)
++ goto drop_all_zwplugs;
+
+ /*
+ * Check if the capacity has changed. If it did, assume that the device
+ * was reformatted and that all sequential zones are now empty. So drop
+ * all zone write plug.
+ */
+ if (disk->nr_zones && disk->nr_zones != nr_zones) {
+ pr_warn("%s: Number of zones changed (%u -> %u)\n",
+ disk->disk_name, disk->nr_zones, nr_zones);
+ ret = 0;
+ goto drop_all_zwplugs;
}

- /* Check that the zone condition is consistent with the zone type. */
- switch (cond) {
- case BLK_ZONE_COND_NOT_WP:
- if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL)
- goto invalid_condition;
- break;
- case BLK_ZONE_COND_IMP_OPEN:
- case BLK_ZONE_COND_EXP_OPEN:
- case BLK_ZONE_COND_CLOSED:
- case BLK_ZONE_COND_EMPTY:
- case BLK_ZONE_COND_FULL:
- case BLK_ZONE_COND_OFFLINE:
- case BLK_ZONE_COND_READONLY:
- if (zone->type != BLK_ZONE_TYPE_SEQWRITE_REQ)
- goto invalid_condition;
- break;
- default:
- pr_warn("%s: Invalid zone condition 0x%X\n",
- args->disk->disk_name, cond);
- return -ENODEV;
- }
-
- blk_zone_set_cond(args->zones_cond, idx, cond);
-
return 0;

- invalid_condition:
- pr_warn("%s: Invalid zone condition 0x%x for type 0x%x\n",
- args->disk->disk_name, cond, zone->type);
+ drop_all_zwplugs:
+ disk_for_all_zone_wplugs(disk, disk_drop_zone_wplug, NULL);

- return -ENODEV;
+ return ret;
}

static int blk_revalidate_conv_zone(struct blk_zone *zone, unsigned int idx,

Attachment: signature.asc
Description: PGP signature