Introduce a regular device for storing metadata and buffer write, zoned
device is used by default if no regular device was set by dmsetup.

The corresponding dmsetup cmd is:
echo "0 $size zoned $regular_device $zoned_device" | dmsetup create 
$dm-zoned-name

Signed-off-by: Bob Liu <bob....@oracle.com>
---
 drivers/md/dm-zoned-target.c | 141 +++++++++++++++++++++++++------------------
 drivers/md/dm-zoned.h        |  50 +++++++++++++--
 2 files changed, 127 insertions(+), 64 deletions(-)

diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c
index 28f4d00..cae4bfe 100644
--- a/drivers/md/dm-zoned-target.c
+++ b/drivers/md/dm-zoned-target.c
@@ -35,38 +35,6 @@ struct dm_chunk_work {
 };
 
 /*
- * Target descriptor.
- */
-struct dmz_target {
-       struct dm_dev           *ddev;
-
-       unsigned long           flags;
-
-       /* Zoned block device information */
-       struct dmz_dev          *zoned_dev;
-
-       /* For metadata handling */
-       struct dmz_metadata     *metadata;
-
-       /* For reclaim */
-       struct dmz_reclaim      *reclaim;
-
-       /* For chunk work */
-       struct radix_tree_root  chunk_rxtree;
-       struct workqueue_struct *chunk_wq;
-       struct mutex            chunk_lock;
-
-       /* For cloned BIOs to zones */
-       struct bio_set          bio_set;
-
-       /* For flush */
-       spinlock_t              flush_lock;
-       struct bio_list         flush_list;
-       struct delayed_work     flush_work;
-       struct workqueue_struct *flush_wq;
-};
-
-/*
  * Flush intervals (seconds).
  */
 #define DMZ_FLUSH_PERIOD       (10 * HZ)
@@ -679,7 +647,7 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
 /*
  * Get zoned device information.
  */
-static int dmz_get_zoned_device(struct dm_target *ti, char *path)
+static int dmz_get_device(struct dm_target *ti, char *path, bool zoned)
 {
        struct dmz_target *dmz = ti->private;
        struct request_queue *q;
@@ -688,11 +656,22 @@ static int dmz_get_zoned_device(struct dm_target *ti, 
char *path)
        int ret;
 
        /* Get the target device */
-       ret = dm_get_device(ti, path, dm_table_get_mode(ti->table), &dmz->ddev);
-       if (ret) {
-               ti->error = "Get target device failed";
-               dmz->ddev = NULL;
-               return ret;
+       if (zoned) {
+               ret = dm_get_device(ti, path, dm_table_get_mode(ti->table),
+                               &dmz->ddev);
+               if (ret) {
+                       ti->error = "Get target device failed";
+                       dmz->ddev = NULL;
+                       return ret;
+               }
+       } else {
+               ret = dm_get_device(ti, path, dm_table_get_mode(ti->table),
+                               &dmz->regu_dm_dev);
+               if (ret) {
+                       ti->error = "Get target device failed";
+                       dmz->regu_dm_dev = NULL;
+                       return ret;
+               }
        }
 
        dev = kzalloc(sizeof(struct dmz_dev), GFP_KERNEL);
@@ -701,39 +680,61 @@ static int dmz_get_zoned_device(struct dm_target *ti, 
char *path)
                goto err;
        }
 
-       dev->bdev = dmz->ddev->bdev;
-       (void)bdevname(dev->bdev, dev->name);
-
-       if (bdev_zoned_model(dev->bdev) == BLK_ZONED_NONE) {
-               ti->error = "Not a zoned block device";
-               ret = -EINVAL;
-               goto err;
+       if (zoned) {
+               dev->bdev = dmz->ddev->bdev;
+               if (bdev_zoned_model(dev->bdev) == BLK_ZONED_NONE) {
+                       ti->error = "Not a zoned block device";
+                       ret = -EINVAL;
+                       goto err;
+               }
        }
+       else
+               dev->bdev = dmz->regu_dm_dev->bdev;
+
+       (void)bdevname(dev->bdev, dev->name);
+       dev->target = dmz;
 
        q = bdev_get_queue(dev->bdev);
        dev->capacity = i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT;
        aligned_capacity = dev->capacity &
                                ~((sector_t)blk_queue_zone_sectors(q) - 1);
-       if (ti->begin ||
-           ((ti->len != dev->capacity) && (ti->len != aligned_capacity))) {
-               ti->error = "Partial mapping not supported";
-               ret = -EINVAL;
-               goto err;
-       }
 
-       dev->zone_nr_sectors = blk_queue_zone_sectors(q);
-       dev->zone_nr_sectors_shift = ilog2(dev->zone_nr_sectors);
+       if (zoned) {
+               if (ti->begin || ((ti->len != dev->capacity) &&
+                                       (ti->len != aligned_capacity))) {
+                       ti->error = "Partial mapping not supported";
+                       ret = -EINVAL;
+                       goto err;
+               }
+               dev->zone_nr_sectors = blk_queue_zone_sectors(q);
+               dev->zone_nr_sectors_shift = ilog2(dev->zone_nr_sectors);
+
+               dev->zone_nr_blocks = dmz_sect2blk(dev->zone_nr_sectors);
+               dev->zone_nr_blocks_shift = ilog2(dev->zone_nr_blocks);
 
-       dev->zone_nr_blocks = dmz_sect2blk(dev->zone_nr_sectors);
-       dev->zone_nr_blocks_shift = ilog2(dev->zone_nr_blocks);
+               dev->nr_zones = blkdev_nr_zones(dev->bdev->bd_disk);
 
-       dev->nr_zones = blkdev_nr_zones(dev->bdev->bd_disk);
+               dmz->zoned_dev = dev;
+       } else {
+               /* Emulate regular device zone info by using the same zone 
size.*/
+               dev->zone_nr_sectors = dmz->zoned_dev->zone_nr_sectors;
+               dev->zone_nr_sectors_shift = ilog2(dev->zone_nr_sectors);
 
-       dmz->zoned_dev = dev;
+               dev->zone_nr_blocks = dmz_sect2blk(dev->zone_nr_sectors);
+               dev->zone_nr_blocks_shift = ilog2(dev->zone_nr_blocks);
+
+               dev->nr_zones = (get_capacity(dev->bdev->bd_disk) >>
+                               ilog2(dev->zone_nr_sectors));
+
+               dmz->regu_dmz_dev = dev;
+       }
 
        return 0;
 err:
-       dm_put_device(ti, dmz->ddev);
+       if (zoned)
+               dm_put_device(ti, dmz->ddev);
+       else
+               dm_put_device(ti, dmz->regu_dm_dev);
        kfree(dev);
 
        return ret;
@@ -746,6 +747,12 @@ static void dmz_put_zoned_device(struct dm_target *ti)
 {
        struct dmz_target *dmz = ti->private;
 
+       if (dmz->regu_dm_dev)
+               dm_put_device(ti, dmz->regu_dm_dev);
+       if (dmz->regu_dmz_dev) {
+               kfree(dmz->regu_dmz_dev);
+               dmz->regu_dmz_dev = NULL;
+       }
        dm_put_device(ti, dmz->ddev);
        kfree(dmz->zoned_dev);
        dmz->zoned_dev = NULL;
@@ -761,7 +768,7 @@ static int dmz_ctr(struct dm_target *ti, unsigned int argc, 
char **argv)
        int ret;
 
        /* Check arguments */
-       if (argc != 1) {
+       if ((argc != 1) && (argc != 2)) {
                ti->error = "Invalid argument count";
                return -EINVAL;
        }
@@ -775,12 +782,25 @@ static int dmz_ctr(struct dm_target *ti, unsigned int 
argc, char **argv)
        ti->private = dmz;
 
        /* Get the target zoned block device */
-       ret = dmz_get_zoned_device(ti, argv[0]);
+       ret = dmz_get_device(ti, argv[0], 1);
        if (ret) {
                dmz->ddev = NULL;
                goto err;
        }
 
+       snprintf(dmz->name, BDEVNAME_SIZE, "%s", dmz->zoned_dev->name);
+       dmz->nr_zones = dmz->zoned_dev->nr_zones;
+       if (argc == 2) {
+               ret = dmz_get_device(ti, argv[1], 0);
+               if (ret) {
+                       dmz->regu_dm_dev = NULL;
+                       goto err;
+               }
+               snprintf(dmz->name, BDEVNAME_SIZE * 2, "%s:%s",
+                               dmz->zoned_dev->name, dmz->regu_dmz_dev->name);
+               dmz->nr_zones += dmz->regu_dmz_dev->nr_zones;
+       }
+
        /* Initialize metadata */
        dev = dmz->zoned_dev;
        ret = dmz_ctr_metadata(dev, &dmz->metadata);
@@ -962,6 +982,7 @@ static int dmz_iterate_devices(struct dm_target *ti,
        struct dmz_dev *dev = dmz->zoned_dev;
        sector_t capacity = dev->capacity & ~(dev->zone_nr_sectors - 1);
 
+       /* Todo: fn(dmz->regu_dm_dev) */
        return fn(ti, dmz->ddev, 0, capacity, data);
 }
 
diff --git a/drivers/md/dm-zoned.h b/drivers/md/dm-zoned.h
index 5b5e493..a3535bc 100644
--- a/drivers/md/dm-zoned.h
+++ b/drivers/md/dm-zoned.h
@@ -46,9 +46,51 @@
 #define dmz_bio_blocks(bio)    dmz_sect2blk(bio_sectors(bio))
 
 /*
+ * Target descriptor.
+ */
+struct dmz_target {
+       struct dm_dev           *ddev;
+       /*
+        * Regular device for store metdata and buffer write, use zoned device
+        * by default if no regular device was set.
+        */
+       struct dm_dev           *regu_dm_dev;
+       struct dmz_dev          *regu_dmz_dev;
+       /* Total nr_zones. */
+       unsigned int            nr_zones;
+       char                    name[BDEVNAME_SIZE * 2];
+
+       unsigned long           flags;
+
+       /* Zoned block device information */
+       struct dmz_dev          *zoned_dev;
+
+       /* For metadata handling */
+       struct dmz_metadata     *metadata;
+
+       /* For reclaim */
+       struct dmz_reclaim      *reclaim;
+
+       /* For chunk work */
+       struct radix_tree_root  chunk_rxtree;
+       struct workqueue_struct *chunk_wq;
+       struct mutex            chunk_lock;
+
+       /* For cloned BIOs to zones */
+       struct bio_set          bio_set;
+
+       /* For flush */
+       spinlock_t              flush_lock;
+       struct bio_list         flush_list;
+       struct delayed_work     flush_work;
+       struct workqueue_struct *flush_wq;
+};
+
+/*
  * Zoned block device information.
  */
 struct dmz_dev {
+       struct dmz_target       *target;
        struct block_device     *bdev;
 
        char                    name[BDEVNAME_SIZE];
@@ -147,16 +189,16 @@ enum {
  * Message functions.
  */
 #define dmz_dev_info(dev, format, args...)     \
-       DMINFO("(%s): " format, (dev)->name, ## args)
+       DMINFO("(%s): " format, (dev)->target->name, ## args)
 
 #define dmz_dev_err(dev, format, args...)      \
-       DMERR("(%s): " format, (dev)->name, ## args)
+       DMERR("(%s): " format, (dev)->target->name, ## args)
 
 #define dmz_dev_warn(dev, format, args...)     \
-       DMWARN("(%s): " format, (dev)->name, ## args)
+       DMWARN("(%s): " format, (dev)->target->name, ## args)
 
 #define dmz_dev_debug(dev, format, args...)    \
-       DMDEBUG("(%s): " format, (dev)->name, ## args)
+       DMDEBUG("(%s): " format, (dev)->target->name, ## args)
 
 struct dmz_metadata;
 struct dmz_reclaim;
-- 
2.9.5


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

Reply via email to