Skip to content

Commit

Permalink
dm: Check that a zoned table leads to a valid mapped device
Browse files Browse the repository at this point in the history
Using targets such as dm-linear, a mapped device can be created to
contain only conventional zones. Such device should not be treated as
zoned as it does not contain any mandatory sequential write required
zone. Since such device can be randomly written, we can modify
dm_set_zones_restrictions() to set the mapped device zoned queue limit
to false to expose it as a regular block device. The function
dm_check_zoned() does this after counting the number of conventional
zones of the mapped device and comparing it to the total number of zones
reported. The special dm_check_zoned_cb() report zones callback function
is used to count conventional zones.

Signed-off-by: Damien Le Moal <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
damien-lemoal authored and axboe committed May 1, 2024
1 parent 6ad0d7e commit 44cccb3
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
3 changes: 2 additions & 1 deletion drivers/md/dm-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -2042,7 +2042,8 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
r = dm_set_zones_restrictions(t, q);
if (r)
return r;
if (!static_key_enabled(&zoned_enabled.key))
if (blk_queue_is_zoned(q) &&
!static_key_enabled(&zoned_enabled.key))
static_branch_enable(&zoned_enabled);
}

Expand Down
57 changes: 57 additions & 0 deletions drivers/md/dm-zone.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,52 @@ bool dm_is_zone_write(struct mapped_device *md, struct bio *bio)
}
}

/*
* Count conventional zones of a mapped zoned device. If the device
* only has conventional zones, do not expose it as zoned.
*/
static int dm_check_zoned_cb(struct blk_zone *zone, unsigned int idx,
void *data)
{
unsigned int *nr_conv_zones = data;

if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
(*nr_conv_zones)++;

return 0;
}

static int dm_check_zoned(struct mapped_device *md, struct dm_table *t)
{
struct gendisk *disk = md->disk;
unsigned int nr_conv_zones = 0;
int ret;

/* Count conventional zones */
md->zone_revalidate_map = t;
ret = dm_blk_report_zones(disk, 0, UINT_MAX,
dm_check_zoned_cb, &nr_conv_zones);
md->zone_revalidate_map = NULL;
if (ret < 0) {
DMERR("Check zoned failed %d", ret);
return ret;
}

/*
* If we only have conventional zones, expose the mapped device as
* a regular device.
*/
if (nr_conv_zones >= ret) {
disk->queue->limits.max_open_zones = 0;
disk->queue->limits.max_active_zones = 0;
disk->queue->limits.zoned = false;
clear_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
disk->nr_zones = 0;
}

return 0;
}

/*
* Revalidate the zones of a mapped device to initialize resource necessary
* for zone append emulation. Note that we cannot simply use the block layer
Expand Down Expand Up @@ -208,6 +254,7 @@ static bool dm_table_supports_zone_append(struct dm_table *t)
int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q)
{
struct mapped_device *md = t->md;
int ret;

/*
* Check if zone append is natively supported, and if not, set the
Expand All @@ -224,6 +271,16 @@ int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q)
if (!get_capacity(md->disk))
return 0;

/*
* Check that the mapped device will indeed be zoned, that is, that it
* has sequential write required zones.
*/
ret = dm_check_zoned(md, t);
if (ret)
return ret;
if (!blk_queue_is_zoned(q))
return 0;

if (!md->disk->nr_zones) {
DMINFO("%s using %s zone append",
md->disk->disk_name,
Expand Down

0 comments on commit 44cccb3

Please sign in to comment.