[dm-devel] [PATCH v4 06/11] dm: move zone related code to dm-zone.c
Himanshu Madhani
himanshu.madhani at oracle.com
Tue May 25 19:10:56 UTC 2021
On 5/24/21 9:25 PM, Damien Le Moal wrote:
> Move core and table code used for zoned targets and conditionally
> defined with #ifdef CONFIG_BLK_DEV_ZONED to the new file dm-zone.c.
> This file is conditionally compiled depending on CONFIG_BLK_DEV_ZONED.
> The small helper dm_set_zones_restrictions() is introduced to
> initialize a mapped device request queue zone attributes in
> dm_table_set_restrictions().
>
> Signed-off-by: Damien Le Moal <damien.lemoal at wdc.com>
> Reviewed-by: Johannes Thumshirn <johannes.thumshirn at wdc.com>
> Reviewed-by: Hannes Reinecke <hare at suse.de>
> ---
> drivers/md/Makefile | 4 ++
> drivers/md/dm-table.c | 14 ++----
> drivers/md/dm-zone.c | 102 ++++++++++++++++++++++++++++++++++++++++++
> drivers/md/dm.c | 78 --------------------------------
> drivers/md/dm.h | 11 +++++
> 5 files changed, 120 insertions(+), 89 deletions(-)
> create mode 100644 drivers/md/dm-zone.c
>
> diff --git a/drivers/md/Makefile b/drivers/md/Makefile
> index ef7ddc27685c..a74aaf8b1445 100644
> --- a/drivers/md/Makefile
> +++ b/drivers/md/Makefile
> @@ -92,6 +92,10 @@ ifeq ($(CONFIG_DM_UEVENT),y)
> dm-mod-objs += dm-uevent.o
> endif
>
> +ifeq ($(CONFIG_BLK_DEV_ZONED),y)
> +dm-mod-objs += dm-zone.o
> +endif
> +
> ifeq ($(CONFIG_DM_VERITY_FEC),y)
> dm-verity-objs += dm-verity-fec.o
> endif
> diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
> index 21fd9cd4da32..dd9f648ab598 100644
> --- a/drivers/md/dm-table.c
> +++ b/drivers/md/dm-table.c
> @@ -2064,17 +2064,9 @@ void 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);
>
> - /*
> - * For a zoned target, the number of zones should be updated for the
> - * correct value to be exposed in sysfs queue/nr_zones. For a BIO based
> - * target, this is all that is needed.
> - */
> -#ifdef CONFIG_BLK_DEV_ZONED
> - if (blk_queue_is_zoned(q)) {
> - WARN_ON_ONCE(queue_is_mq(q));
> - q->nr_zones = blkdev_nr_zones(t->md->disk);
> - }
> -#endif
> + /* For a zoned target, setup the zones related queue attributes */
> + if (blk_queue_is_zoned(q))
> + dm_set_zones_restrictions(t, q);
>
> dm_update_keyslot_manager(q, t);
> blk_queue_update_readahead(q);
> diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c
> new file mode 100644
> index 000000000000..3243c42b7951
> --- /dev/null
> +++ b/drivers/md/dm-zone.c
> @@ -0,0 +1,102 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2021 Western Digital Corporation or its affiliates.
> + */
> +
> +#include <linux/blkdev.h>
> +
> +#include "dm-core.h"
> +
> +/*
> + * User facing dm device block device report zone operation. This calls the
> + * report_zones operation for each target of a device table. This operation is
> + * generally implemented by targets using dm_report_zones().
> + */
> +int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
> + unsigned int nr_zones, report_zones_cb cb, void *data)
> +{
> + struct mapped_device *md = disk->private_data;
> + struct dm_table *map;
> + int srcu_idx, ret;
> + struct dm_report_zones_args args = {
> + .next_sector = sector,
> + .orig_data = data,
> + .orig_cb = cb,
> + };
> +
> + if (dm_suspended_md(md))
> + return -EAGAIN;
> +
> + map = dm_get_live_table(md, &srcu_idx);
> + if (!map) {
> + ret = -EIO;
> + goto out;
> + }
> +
> + do {
> + struct dm_target *tgt;
> +
> + tgt = dm_table_find_target(map, args.next_sector);
> + if (WARN_ON_ONCE(!tgt->type->report_zones)) {
> + ret = -EIO;
> + goto out;
> + }
> +
> + args.tgt = tgt;
> + ret = tgt->type->report_zones(tgt, &args,
> + nr_zones - args.zone_idx);
> + if (ret < 0)
> + goto out;
> + } while (args.zone_idx < nr_zones &&
> + args.next_sector < get_capacity(disk));
> +
> + ret = args.zone_idx;
> +out:
> + dm_put_live_table(md, srcu_idx);
> + return ret;
> +}
> +
> +int dm_report_zones_cb(struct blk_zone *zone, unsigned int idx, void *data)
> +{
> + struct dm_report_zones_args *args = data;
> + sector_t sector_diff = args->tgt->begin - args->start;
> +
> + /*
> + * Ignore zones beyond the target range.
> + */
> + if (zone->start >= args->start + args->tgt->len)
> + return 0;
> +
> + /*
> + * Remap the start sector and write pointer position of the zone
> + * to match its position in the target range.
> + */
> + zone->start += sector_diff;
> + if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) {
> + if (zone->cond == BLK_ZONE_COND_FULL)
> + zone->wp = zone->start + zone->len;
> + else if (zone->cond == BLK_ZONE_COND_EMPTY)
> + zone->wp = zone->start;
> + else
> + zone->wp += sector_diff;
> + }
> +
> + args->next_sector = zone->start + zone->len;
> + return args->orig_cb(zone, args->zone_idx++, args->orig_data);
> +}
> +EXPORT_SYMBOL_GPL(dm_report_zones_cb);
> +
> +void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q)
> +{
> + if (!blk_queue_is_zoned(q))
> + return;
> +
> + /*
> + * For a zoned target, the number of zones should be updated for the
> + * correct value to be exposed in sysfs queue/nr_zones. For a BIO based
> + * target, this is all that is needed.
> + */
> + WARN_ON_ONCE(queue_is_mq(q));
> + q->nr_zones = blkdev_nr_zones(t->md->disk);
> +}
> +
> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> index a9211575bfed..45d2dc2ee844 100644
> --- a/drivers/md/dm.c
> +++ b/drivers/md/dm.c
> @@ -444,84 +444,6 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
> return dm_get_geometry(md, geo);
> }
>
> -#ifdef CONFIG_BLK_DEV_ZONED
> -int dm_report_zones_cb(struct blk_zone *zone, unsigned int idx, void *data)
> -{
> - struct dm_report_zones_args *args = data;
> - sector_t sector_diff = args->tgt->begin - args->start;
> -
> - /*
> - * Ignore zones beyond the target range.
> - */
> - if (zone->start >= args->start + args->tgt->len)
> - return 0;
> -
> - /*
> - * Remap the start sector and write pointer position of the zone
> - * to match its position in the target range.
> - */
> - zone->start += sector_diff;
> - if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) {
> - if (zone->cond == BLK_ZONE_COND_FULL)
> - zone->wp = zone->start + zone->len;
> - else if (zone->cond == BLK_ZONE_COND_EMPTY)
> - zone->wp = zone->start;
> - else
> - zone->wp += sector_diff;
> - }
> -
> - args->next_sector = zone->start + zone->len;
> - return args->orig_cb(zone, args->zone_idx++, args->orig_data);
> -}
> -EXPORT_SYMBOL_GPL(dm_report_zones_cb);
> -
> -static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
> - unsigned int nr_zones, report_zones_cb cb, void *data)
> -{
> - struct mapped_device *md = disk->private_data;
> - struct dm_table *map;
> - int srcu_idx, ret;
> - struct dm_report_zones_args args = {
> - .next_sector = sector,
> - .orig_data = data,
> - .orig_cb = cb,
> - };
> -
> - if (dm_suspended_md(md))
> - return -EAGAIN;
> -
> - map = dm_get_live_table(md, &srcu_idx);
> - if (!map) {
> - ret = -EIO;
> - goto out;
> - }
> -
> - do {
> - struct dm_target *tgt;
> -
> - tgt = dm_table_find_target(map, args.next_sector);
> - if (WARN_ON_ONCE(!tgt->type->report_zones)) {
> - ret = -EIO;
> - goto out;
> - }
> -
> - args.tgt = tgt;
> - ret = tgt->type->report_zones(tgt, &args,
> - nr_zones - args.zone_idx);
> - if (ret < 0)
> - goto out;
> - } while (args.zone_idx < nr_zones &&
> - args.next_sector < get_capacity(disk));
> -
> - ret = args.zone_idx;
> -out:
> - dm_put_live_table(md, srcu_idx);
> - return ret;
> -}
> -#else
> -#define dm_blk_report_zones NULL
> -#endif /* CONFIG_BLK_DEV_ZONED */
> -
> static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
> struct block_device **bdev)
> {
> diff --git a/drivers/md/dm.h b/drivers/md/dm.h
> index b441ad772c18..fdf1536a4b62 100644
> --- a/drivers/md/dm.h
> +++ b/drivers/md/dm.h
> @@ -100,6 +100,17 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t);
> */
> #define dm_target_hybrid(t) (dm_target_bio_based(t) && dm_target_request_based(t))
>
> +/*
> + * Zoned targets related functions.
> + */
> +void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q);
> +#ifdef CONFIG_BLK_DEV_ZONED
> +int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
> + unsigned int nr_zones, report_zones_cb cb, void *data);
> +#else
> +#define dm_blk_report_zones NULL
> +#endif
> +
> /*-----------------------------------------------------------------
> * A registry of target types.
> *---------------------------------------------------------------*/
>
Reviewed-by: Himanshu Madhani <himanshu.madhani at oracle.com>
--
Himanshu Madhani Oracle Linux Engineering
More information about the dm-devel
mailing list