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.lem...@wdc.com>
Reviewed-by: Johannes Thumshirn <johannes.thumsh...@wdc.com>
Reviewed-by: Hannes Reinecke <h...@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.
  *---------------------------------------------------------------*/
-- 
2.31.1

--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel

Reply via email to