Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm table: Fix zoned model check and zone sectors check

Commit 24f6b6036c9e ("dm table: fix zoned iterate_devices based device
capability checks") triggered dm table load failure when dm-zoned device
is set up for zoned block devices and a regular device for cache.

The commit inverted logic of two callback functions for iterate_devices:
device_is_zoned_model() and device_matches_zone_sectors(). The logic of
device_is_zoned_model() was inverted then all destination devices of all
targets in dm table are required to have the expected zoned model. This
is fine for dm-linear, dm-flakey and dm-crypt on zoned block devices
since each target has only one destination device. However, this results
in failure for dm-zoned with regular cache device since that target has
both regular block device and zoned block devices.

As for device_matches_zone_sectors(), the commit inverted the logic to
require all zoned block devices in each target have the specified
zone_sectors. This check also fails for regular block device which does
not have zones.

To avoid the check failures, fix the zone model check and the zone
sectors check. For zone model check, introduce the new feature flag
DM_TARGET_MIXED_ZONED_MODEL, and set it to dm-zoned target. When the
target has this flag, allow it to have destination devices with any
zoned model. For zone sectors check, skip the check if the destination
device is not a zoned block device. Also add comments and improve an
error message to clarify expectations to the two checks.

Fixes: 24f6b6036c9e ("dm table: fix zoned iterate_devices based device capability checks")
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>

authored by

Shin'ichiro Kawasaki and committed by
Mike Snitzer
2d669ceb 160f99db

+40 -10
+25 -8
drivers/md/dm-table.c
··· 1594 1594 return blk_queue_zoned_model(q) != *zoned_model; 1595 1595 } 1596 1596 1597 + /* 1598 + * Check the device zoned model based on the target feature flag. If the target 1599 + * has the DM_TARGET_ZONED_HM feature flag set, host-managed zoned devices are 1600 + * also accepted but all devices must have the same zoned model. If the target 1601 + * has the DM_TARGET_MIXED_ZONED_MODEL feature set, the devices can have any 1602 + * zoned model with all zoned devices having the same zone size. 1603 + */ 1597 1604 static bool dm_table_supports_zoned_model(struct dm_table *t, 1598 1605 enum blk_zoned_model zoned_model) 1599 1606 { ··· 1610 1603 for (i = 0; i < dm_table_get_num_targets(t); i++) { 1611 1604 ti = dm_table_get_target(t, i); 1612 1605 1613 - if (zoned_model == BLK_ZONED_HM && 1614 - !dm_target_supports_zoned_hm(ti->type)) 1615 - return false; 1616 - 1617 - if (!ti->type->iterate_devices || 1618 - ti->type->iterate_devices(ti, device_not_zoned_model, &zoned_model)) 1619 - return false; 1606 + if (dm_target_supports_zoned_hm(ti->type)) { 1607 + if (!ti->type->iterate_devices || 1608 + ti->type->iterate_devices(ti, device_not_zoned_model, 1609 + &zoned_model)) 1610 + return false; 1611 + } else if (!dm_target_supports_mixed_zoned_model(ti->type)) { 1612 + if (zoned_model == BLK_ZONED_HM) 1613 + return false; 1614 + } 1620 1615 } 1621 1616 1622 1617 return true; ··· 1630 1621 struct request_queue *q = bdev_get_queue(dev->bdev); 1631 1622 unsigned int *zone_sectors = data; 1632 1623 1624 + if (!blk_queue_is_zoned(q)) 1625 + return 0; 1626 + 1633 1627 return blk_queue_zone_sectors(q) != *zone_sectors; 1634 1628 } 1635 1629 1630 + /* 1631 + * Check consistency of zoned model and zone sectors across all targets. For 1632 + * zone sectors, if the destination device is a zoned block device, it shall 1633 + * have the specified zone_sectors. 1634 + */ 1636 1635 static int validate_hardware_zoned_model(struct dm_table *table, 1637 1636 enum blk_zoned_model zoned_model, 1638 1637 unsigned int zone_sectors) ··· 1659 1642 return -EINVAL; 1660 1643 1661 1644 if (dm_table_any_dev_attr(table, device_not_matches_zone_sectors, &zone_sectors)) { 1662 - DMERR("%s: zone sectors is not consistent across all devices", 1645 + DMERR("%s: zone sectors is not consistent across all zoned devices", 1663 1646 dm_device_name(table->md)); 1664 1647 return -EINVAL; 1665 1648 }
+1 -1
drivers/md/dm-zoned-target.c
··· 1143 1143 static struct target_type dmz_type = { 1144 1144 .name = "zoned", 1145 1145 .version = {2, 0, 0}, 1146 - .features = DM_TARGET_SINGLETON | DM_TARGET_ZONED_HM, 1146 + .features = DM_TARGET_SINGLETON | DM_TARGET_MIXED_ZONED_MODEL, 1147 1147 .module = THIS_MODULE, 1148 1148 .ctr = dmz_ctr, 1149 1149 .dtr = dmz_dtr,
+14 -1
include/linux/device-mapper.h
··· 253 253 #define dm_target_passes_integrity(type) ((type)->features & DM_TARGET_PASSES_INTEGRITY) 254 254 255 255 /* 256 - * Indicates that a target supports host-managed zoned block devices. 256 + * Indicates support for zoned block devices: 257 + * - DM_TARGET_ZONED_HM: the target also supports host-managed zoned 258 + * block devices but does not support combining different zoned models. 259 + * - DM_TARGET_MIXED_ZONED_MODEL: the target supports combining multiple 260 + * devices with different zoned models. 257 261 */ 258 262 #ifdef CONFIG_BLK_DEV_ZONED 259 263 #define DM_TARGET_ZONED_HM 0x00000040 ··· 278 274 */ 279 275 #define DM_TARGET_PASSES_CRYPTO 0x00000100 280 276 #define dm_target_passes_crypto(type) ((type)->features & DM_TARGET_PASSES_CRYPTO) 277 + 278 + #ifdef CONFIG_BLK_DEV_ZONED 279 + #define DM_TARGET_MIXED_ZONED_MODEL 0x00000200 280 + #define dm_target_supports_mixed_zoned_model(type) \ 281 + ((type)->features & DM_TARGET_MIXED_ZONED_MODEL) 282 + #else 283 + #define DM_TARGET_MIXED_ZONED_MODEL 0x00000000 284 + #define dm_target_supports_mixed_zoned_model(type) (false) 285 + #endif 281 286 282 287 struct dm_target { 283 288 struct dm_table *table;