Re: [PATCH] dm: Validate zoned model of devices built with zoned targets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2023/12/01 11:03, Damien Le Moal wrote:
> Using dm-linear or dm-error, a user can craft a DM device using
> host-managed SMR disks by mapping only conventional zones. Currently,
> such DM device will be reported also as being host-managed, despite the
> fact that this zoned model mandated sequential-write-required zone are
> not present. This breaks the host-managed model and may confuse some
> applications, potentially resulting in unexpected behavior or bugs.
> 
> A simple solution for such case is to expose a DM device built only
> using an SMR host managed disk conventional zones as a regular device.
> This is acceptable and possible because read and write accesses to
> conventional zones do not have any restrictions and can cross zone
> boundaries.
> 
> This commit introduces the function dm_validate_zoned_model() to detect
> if a zoned DM device contains only conventional zones. If it does, this
> function calls disk_set_zoned() to change the DM device queue zoned
> model to BLK_ZONED_NONE, clearing in the process also the queue limits
> associated with zoned block devices (e.g. chunk_sectors for the zone
> size, number of zones, etc). dm_validate_zoned_model() is called from
> dm_table_set_restrictions() when the DM device request queue is set up.
> 
> With this change, dm-linear and dm-error devices built using
> conventional zones are now exposed as regular block devices.
> 
> Signed-off-by: Damien Le Moal <dlemoal@xxxxxxxxxx>

Mike,

Ping ? I do not see this queued in DM tree for-next branch.

Thanks !

> ---
>  drivers/md/dm-table.c | 13 +++++++++
>  drivers/md/dm-zone.c  | 63 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/md/dm.h       |  1 +
>  3 files changed, 77 insertions(+)
> 
> diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
> index 198d38b53322..9c7547da6171 100644
> --- a/drivers/md/dm-table.c
> +++ b/drivers/md/dm-table.c
> @@ -2034,6 +2034,19 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
>  	    dm_table_any_dev_attr(t, device_is_not_random, NULL))
>  		blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
>  
> +	/*
> +	 * A zoned target may contain only conventional zones, in which case
> +	 * we must set the device queue zoned model to BLK_ZONED_NONE to
> +	 * expose the target as a regular block device, and thus avoiding
> +	 * breaking the host-managed zoned model as it mandates the presence
> +	 * of sequential write required zones.
> +	 */
> +	if (blk_queue_is_zoned(q)) {
> +		r = dm_validate_zoned_model(t, q);
> +		if (r)
> +			return r;
> +	}
> +
>  	/*
>  	 * For a zoned target, setup the zones related queue attributes
>  	 * and resources necessary for zone append emulation if necessary.
> diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c
> index eb9832b22b14..452a59bfdc10 100644
> --- a/drivers/md/dm-zone.c
> +++ b/drivers/md/dm-zone.c
> @@ -174,6 +174,69 @@ static unsigned int dm_get_zone_wp_offset(struct blk_zone *zone)
>  	}
>  }
>  
> +struct dm_zone_count {
> +	unsigned long nr_conv;
> +	unsigned long nr_seq;
> +};
> +
> +static int dm_validate_zoned_model_cb(struct blk_zone *zone, unsigned int idx,
> +				      void *data)
> +{
> +	struct dm_zone_count *zc = data;
> +
> +	switch (zone->type) {
> +	case BLK_ZONE_TYPE_CONVENTIONAL:
> +		zc->nr_conv++;
> +		break;
> +	case BLK_ZONE_TYPE_SEQWRITE_REQ:
> +	case BLK_ZONE_TYPE_SEQWRITE_PREF:
> +		zc->nr_seq++;
> +		break;
> +	default:
> +		DMERR("Invalid zone type 0x%x at sectors %llu",
> +		      (int)zone->type, zone->start);
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Validate the queue zoned model by counting the conventional and
> + * sequential zones of the target. If no sequential zones are present, modify
> + * the device queue to expose it as a regular block device.
> + */
> +int dm_validate_zoned_model(struct dm_table *t, struct request_queue *q)
> +{
> +	struct mapped_device *md = t->md;
> +	struct gendisk *disk = md->disk;
> +	unsigned int nr_zones = bdev_nr_zones(disk->part0);
> +	struct dm_zone_count zc = { };
> +	unsigned int noio_flag;
> +	int ret;
> +
> +	/* Count conventional and sequential zones */
> +	noio_flag = memalloc_noio_save();
> +	ret = dm_blk_do_report_zones(md, t, 0, nr_zones,
> +				     dm_validate_zoned_model_cb, &zc);
> +	memalloc_noio_restore(noio_flag);
> +	if (ret != nr_zones ||
> +	    zc.nr_conv + zc.nr_seq != nr_zones)
> +		ret = -EIO;
> +	if (ret < 0)
> +		goto err;
> +
> +	if (!zc.nr_seq)
> +		disk_set_zoned(disk, BLK_ZONED_NONE);
> +
> +	return 0;
> +
> +err:
> +	DMERR("Validate zoned model failed %d", ret);
> +	dm_cleanup_zoned_dev(md);
> +	return ret;
> +}
> +
>  static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx,
>  				 void *data)
>  {
> diff --git a/drivers/md/dm.h b/drivers/md/dm.h
> index 7f1acbf6bd9e..c3e6afed3910 100644
> --- a/drivers/md/dm.h
> +++ b/drivers/md/dm.h
> @@ -101,6 +101,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t);
>  /*
>   * Zoned targets related functions.
>   */
> +int dm_validate_zoned_model(struct dm_table *t, struct request_queue *q);
>  int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q);
>  void dm_zone_endio(struct dm_io *io, struct bio *clone);
>  #ifdef CONFIG_BLK_DEV_ZONED

-- 
Damien Le Moal
Western Digital Research





[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux