Re: [RFC PATCH v2 3/3] dm zoned: add regular device info to metadata

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

 



On 3/25/20 2:47 PM, Hannes Reinecke wrote:
> On 3/25/20 7:29 AM, Damien Le Moal wrote:
>> On 2020/03/24 20:04, Bob Liu wrote:
>>> This patch implemented metadata support for regular device by:
>>>   - Emulated zone information for regular device.
>>>   - Store metadata at the beginning of regular device.
>>>
>>>       | --- zoned device --- | -- regular device ||
>>>       ^                      ^
>>>       |                      |Metadata
>>> zone 0
>>>
>>> Signed-off-by: Bob Liu <bob.liu@xxxxxxxxxx>
>>> ---
>>>   drivers/md/dm-zoned-metadata.c | 135 +++++++++++++++++++++++++++++++----------
>>>   drivers/md/dm-zoned-target.c   |   6 +-
>>>   drivers/md/dm-zoned.h          |   3 +-
>>>   3 files changed, 108 insertions(+), 36 deletions(-)
>>>
> Having thought about it some more, I think we cannot continue with this 'simple' approach.
> The immediate problem is that we lie about the disk size; clearly the
> metadata cannot be used for regular data, yet we expose a target device with the full size of the underlying device.

The exposed size is "regular dev size + zoned dev size - metadata size - reserved seq zone size".
I didn't see why there is a lie?

> Making me wonder if anybody ever tested a disk-full scenario...
> The other problem is that with two devices we need to be able to stitch them together in an automated fashion, eg via a systemd service or udev rule.
> But for this we need to be able to identify the devices, which means both need to carry metadata, and both need to have unique identifier within the metadata. Which the current metadata doesn't allow to.
> 
> Hence my plan is to implement a v2 metadata, carrying UUIDs for the dmz set _and_ the component device. With that we can update blkid to create links etc so that the devices can be identified in the system.
> Additionally I would be updating dmzadm to write the new metadata.
> 
> And I will add a new command 'start' to dmzadm which will then create the device-mapper device _with the correct size_. It also has the benefit that we can create the device-mapper target with the UUID specified in the metadata, so the persistent device links will be created automatically.
> 
> Bob, can you send me your improvements to dmzadm so that I can include them in my changes?
> 

Attached, but it's a big patch I haven't split them to smaller one.
The dmz_check/repair can't work neither in current stage.
diff --git a/src/dmz.h b/src/dmz.h
index 57741b1..51b5019 100644
--- a/src/dmz.h
+++ b/src/dmz.h
@@ -153,19 +153,33 @@ enum dmz_op {
 	DMZ_OP_REPAIR,
 };
 
+struct dmz_raw_dev {
+	char *path;
+	char *name;
+	int fd;
+	size_t		zone_nr_sectors;
+	size_t		zone_nr_blocks;
+	/* Device info */
+	__u64		capacity;
+	unsigned int nr_zones;
+	struct blk_zone	*zones;
+	struct dmz_dev *pdev;
+};
+
 /*
  * Device descriptor.
  */
 struct dmz_dev {
 
 	/* Device file path and basename */
-	char		*path;
-	char		*name;
+	struct dmz_raw_dev zoned_dev;
+	struct dmz_raw_dev regu_dev;
+
 	int		op;
 	unsigned int	flags;
+	size_t		zone_nr_blocks;
+	int 		has_regular;
 
-	/* Device info */
-	__u64		capacity;
 
 	unsigned int	nr_zones;
 	unsigned int	nr_meta_zones;
@@ -178,11 +192,6 @@ struct dmz_dev {
 	unsigned int	total_nr_meta_zones;
 	unsigned int	nr_rnd_zones;
 
-	struct blk_zone	*zones;
-
-	size_t		zone_nr_sectors;
-	size_t		zone_nr_blocks;
-
 	/* First metadata zone */
 	struct blk_zone	*sb_zone;
 	__u64		sb_block;
@@ -195,10 +204,6 @@ struct dmz_dev {
 	/* Mapping table */
 	unsigned int	nr_map_blocks;
 	__u64		map_block;
-
-	/* Device file descriptor */
-	int		fd;
-
 };
 
 /*
@@ -317,16 +322,16 @@ dmz_zone_cond_str(struct blk_zone *zone)
 
 extern int dmz_open_dev(struct dmz_dev *dev, enum dmz_op op);
 extern void dmz_close_dev(struct dmz_dev *dev);
-extern int dmz_sync_dev(struct dmz_dev *dev);
-extern int dmz_reset_zone(struct dmz_dev *dev, struct blk_zone *zone);
-extern int dmz_reset_zones(struct dmz_dev *dev);
-extern int dmz_write_block(struct dmz_dev *dev, __u64 block, __u8 *buf);
-extern int dmz_read_block(struct dmz_dev *dev, __u64 block, __u8 *buf);
+extern int dmz_sync_dev(struct dmz_raw_dev *dev);
+extern int dmz_reset_zone(struct dmz_raw_dev *dev, struct blk_zone *zone);
+extern int dmz_reset_zones(struct dmz_raw_dev *dev);
+extern int dmz_write_block(struct dmz_raw_dev *dev, __u64 block, __u8 *buf);
+extern int dmz_read_block(struct dmz_raw_dev *dev, __u64 block, __u8 *buf);
 
 extern __u32 dmz_crc32(__u32 crc, const void *address, size_t length);
 
 extern int dmz_locate_metadata(struct dmz_dev *dev);
-extern int dmz_write_super(struct dmz_dev *dev, __u64 gen, __u64 offset);
+extern int dmz_write_super(struct dmz_raw_dev *dev, __u64 gen, __u64 offset);
 extern int dmz_format(struct dmz_dev *dev);
 extern int dmz_check(struct dmz_dev *dev);
 extern int dmz_repair(struct dmz_dev *dev);
diff --git a/src/dmz_check.c b/src/dmz_check.c
index 25ce026..da8c1a5 100644
--- a/src/dmz_check.c
+++ b/src/dmz_check.c
@@ -29,7 +29,7 @@
 #include <linux/fs.h>
 #include <assert.h>
 #include <asm/byteorder.h>
-
+#if 0
 /*
  * Message macro.
  */
@@ -1245,4 +1245,4 @@ int dmz_repair(struct dmz_dev *dev)
 
 	return 0;
 }
-
+#endif
diff --git a/src/dmz_dev.c b/src/dmz_dev.c
index e713ae0..a7a57ac 100644
--- a/src/dmz_dev.c
+++ b/src/dmz_dev.c
@@ -36,7 +36,7 @@
 /*
  * Test if the device is mounted.
  */
-static int dmz_dev_mounted(struct dmz_dev *dev)
+static int dmz_dev_mounted(struct dmz_raw_dev *dev)
 {
 	struct mntent *mnt = NULL;
 	FILE *file = NULL;
@@ -57,7 +57,7 @@ static int dmz_dev_mounted(struct dmz_dev *dev)
 /*
  * Test if the device is already used as a target backend.
  */
-static int dmz_dev_busy(struct dmz_dev *dev)
+static int dmz_dev_busy(struct dmz_raw_dev *dev)
 {
 	char path[128];
 	struct dirent **namelist;
@@ -87,7 +87,7 @@ static int dmz_dev_busy(struct dmz_dev *dev)
 /*
  * Get a zoned block device model (host-aware or howt-managed).
  */
-static int dmz_get_dev_model(struct dmz_dev *dev)
+static int dmz_get_dev_model(struct dmz_raw_dev *dev)
 {
 	char str[PATH_MAX];
 	FILE *file;
@@ -122,9 +122,9 @@ static int dmz_get_dev_model(struct dmz_dev *dev)
 	}
 
 	if (strcmp(str, "host-aware") == 0)
-		dev->flags |= DMZ_ZONED_HA;
+		dev->pdev->flags |= DMZ_ZONED_HA;
 	else if (strcmp(str, "host-managed") == 0)
-		dev->flags |= DMZ_ZONED_HM;
+		dev->pdev->flags |= DMZ_ZONED_HM;
 
 	return 0;
 }
@@ -132,7 +132,7 @@ static int dmz_get_dev_model(struct dmz_dev *dev)
 /*
  * Get device capacity and zone size.
  */
-static int dmz_get_dev_capacity(struct dmz_dev *dev)
+static int dmz_get_dev_capacity(struct dmz_raw_dev *dev, int emulated)
 {
 	char str[128];
 	FILE *file;
@@ -147,26 +147,30 @@ static int dmz_get_dev_capacity(struct dmz_dev *dev)
 	}
 	dev->capacity >>= 9;
 
-	/* Get zone size */
-	snprintf(str, sizeof(str),
-		 "/sys/block/%s/queue/chunk_sectors",
-		 dev->name);
-	file = fopen(str, "r");
-	if (!file) {
-		fprintf(stderr, "Open %s failed\n", str);
-		return -1;
-	}
+	if (emulated) {
+		dev->zone_nr_sectors = emulated;
+	} else {
+		/* Get zone size */
+		snprintf(str, sizeof(str),
+				"/sys/block/%s/queue/chunk_sectors",
+				dev->name);
+		file = fopen(str, "r");
+		if (!file) {
+			fprintf(stderr, "Open %s failed\n", str);
+			return -1;
+		}
 
-	memset(str, 0, sizeof(str));
-	res = fscanf(file, "%s", str);
-	fclose(file);
+		memset(str, 0, sizeof(str));
+		res = fscanf(file, "%s", str);
+		fclose(file);
 
-	if (res != 1) {
-		fprintf(stderr, "Invalid file %s format\n", str);
-		return -1;
-	}
+		if (res != 1) {
+			fprintf(stderr, "Invalid file %s format\n", str);
+			return -1;
+		}
 
-	dev->zone_nr_sectors = atol(str);
+		dev->zone_nr_sectors = atol(str);
+	}
 	if (!dev->zone_nr_sectors ||
 	    (dev->zone_nr_sectors & DMZ_BLOCK_SECTORS_MASK)) {
 		fprintf(stderr,
@@ -182,7 +186,7 @@ static int dmz_get_dev_capacity(struct dmz_dev *dev)
 /*
  * Print a device zone information.
  */
-static void dmz_print_zone(struct dmz_dev *dev,
+static void dmz_print_zone(struct dmz_raw_dev *dev,
 			   struct blk_zone *zone)
 {
 
@@ -230,14 +234,14 @@ static void dmz_print_zone(struct dmz_dev *dev,
 /*
  * Get a device zone configuration.
  */
-static int dmz_get_dev_zones(struct dmz_dev *dev)
+static int dmz_get_dev_zones(struct dmz_raw_dev *dev, int emulate)
 {
 	struct blk_zone_report *rep = NULL;
 	unsigned int rep_max_zones;
 	struct blk_zone *blkz;
 	unsigned int i, nr_zones;
 	__u64 sector;
-	int ret = -1;
+	int ret = 0;
 
 	/* This will ignore an eventual last smaller zone */
 	nr_zones = dev->capacity / dev->zone_nr_sectors;
@@ -263,17 +267,35 @@ static int dmz_get_dev_zones(struct dmz_dev *dev)
 
 	sector = 0;
 	while (sector < dev->capacity) {
-
 		/* Get zone information */
 		memset(rep, 0, DMZ_REPORT_ZONES_BUFSZ);
 		rep->sector = sector;
 		rep->nr_zones = rep_max_zones;
-		ret = ioctl(dev->fd, BLKREPORTZONE, rep);
-		if (ret != 0) {
-			fprintf(stderr,
-				"%s: Get zone information failed %d (%s)\n",
-				dev->name, errno, strerror(errno));
-			goto out;
+		if (emulate) {
+			unsigned int f_sector = sector;
+			rep->nr_zones = ((nr_zones < rep_max_zones) ? nr_zones : rep_max_zones);
+			blkz = (struct blk_zone *)(rep + 1);
+			for (i = 0; i < rep->nr_zones && f_sector < dev->capacity; i++) {
+				//set up fake blkz
+				blkz->start = f_sector;
+				blkz->len = dev->zone_nr_sectors;
+				blkz->wp = blkz->start + blkz->len;
+				blkz->type = BLK_ZONE_TYPE_CONVENTIONAL;
+				blkz->cond = BLK_ZONE_COND_NOT_WP;
+
+				f_sector = dmz_zone_sector(blkz) + dmz_zone_length(blkz);
+				if (f_sector > dev->capacity)
+					blkz->len = dev->capacity - dmz_zone_sector(blkz);
+				blkz++;
+			}
+		} else {
+			ret = ioctl(dev->fd, BLKREPORTZONE, rep);
+			if (ret != 0) {
+				fprintf(stderr,
+						"%s: Get zone information failed %d (%s)\n",
+						dev->name, errno, strerror(errno));
+				goto out;
+			}
 		}
 
 		if (!rep->nr_zones)
@@ -282,7 +304,7 @@ static int dmz_get_dev_zones(struct dmz_dev *dev)
 		blkz = (struct blk_zone *)(rep + 1);
 		for (i = 0; i < rep->nr_zones && sector < dev->capacity; i++) {
 
-			if (dev->flags & DMZ_VVERBOSE)
+			if (dev->pdev->flags & DMZ_VVERBOSE)
 				dmz_print_zone(dev, blkz);
 
 			/* Check zone size */
@@ -337,22 +359,35 @@ out:
 static int dmz_get_dev_info(struct dmz_dev *dev)
 {
 
-	if (dmz_get_dev_model(dev) < 0)
+	if (dmz_get_dev_model(&dev->zoned_dev) < 0)
 		return -1;
 
 	if (!dmz_dev_is_zoned(dev)) {
 		fprintf(stderr,
 			"%s: Not a zoned block device\n",
-			dev->name);
+			dev->zoned_dev.name);
 		return -1;
 	}
 
-	if (dmz_get_dev_capacity(dev) < 0)
+	if (dmz_get_dev_capacity(&dev->zoned_dev, 0) < 0)
 		return -1;
 
-	if (dmz_get_dev_zones(dev) < 0)
+	dev->zone_nr_blocks = dev->zoned_dev.zone_nr_blocks;
+	if (dev->has_regular)
+		if (dmz_get_dev_capacity(&dev->regu_dev, dev->zoned_dev.zone_nr_blocks) < 0)
+			return -1;
+
+	if (dmz_get_dev_zones(&dev->zoned_dev, 0) < 0)
 		return -1;
 
+	if (dev->has_regular)
+		if (dmz_get_dev_zones(&dev->regu_dev, 1) < 0)
+			return -1;
+
+	dev->nr_zones = dev->zoned_dev.nr_zones;
+	if (dev->has_regular)
+		dev->nr_zones += dev->regu_dev.nr_zones;
+
 	return 0;
 }
 
@@ -361,7 +396,7 @@ static int dmz_get_dev_info(struct dmz_dev *dev)
  * Return -1 on error, 0 if something valid is detected on the disk
  * and 1 if the disk appears to be unused.
  */
-static int dmz_check_overwrite(struct dmz_dev *dev)
+static int dmz_check_overwrite(struct dmz_raw_dev *dev)
 {
 	const char *type;
 	blkid_probe pr;
@@ -421,10 +456,7 @@ out:
 	return ret;
 }
 
-/*
- * Open a device.
- */
-int dmz_open_dev(struct dmz_dev *dev, enum dmz_op op)
+int dmz_open_raw_dev(struct dmz_raw_dev *dev, enum dmz_op op, int flags)
 {
 	struct stat st;
 	int ret;
@@ -447,7 +479,7 @@ int dmz_open_dev(struct dmz_dev *dev, enum dmz_op op)
 		return -1;
 	}
 
-	if (op == DMZ_OP_FORMAT && (!(dev->flags & DMZ_OVERWRITE))) {
+	if (op == DMZ_OP_FORMAT && (!(flags & DMZ_OVERWRITE))) {
 		/* Check for existing valid content */
 		ret = dmz_check_overwrite(dev);
 		if (ret <= 0)
@@ -455,16 +487,12 @@ int dmz_open_dev(struct dmz_dev *dev, enum dmz_op op)
 	}
 
 	if (dmz_dev_mounted(dev)) {
-		fprintf(stderr,
-			"%s is mounted\n",
-			dev->path);
+		fprintf(stderr, "%s is mounted\n", dev->path);
 		return -1;
 	}
 
 	if (dmz_dev_busy(dev)) {
-		fprintf(stderr,
-			"%s is in use\n",
-			dev->path);
+		fprintf(stderr, "%s is in use\n", dev->path);
 		return -1;
 	}
 
@@ -478,6 +506,18 @@ int dmz_open_dev(struct dmz_dev *dev, enum dmz_op op)
 		return -1;
 	}
 
+	return 0;
+}
+
+/*
+ * Open a device.
+ */
+int dmz_open_dev(struct dmz_dev *dev, enum dmz_op op)
+{
+	dmz_open_raw_dev(&dev->zoned_dev, op, dev->flags);
+	if (dev->has_regular)
+		dmz_open_raw_dev(&dev->regu_dev, op, dev->flags);
+
 	/* Get device capacity and zone configuration */
 	if (dmz_get_dev_info(dev) < 0) {
 		dmz_close_dev(dev);
@@ -487,10 +527,7 @@ int dmz_open_dev(struct dmz_dev *dev, enum dmz_op op)
 	return 0;
 }
 
-/*
- * Close an open device.
- */
-void dmz_close_dev(struct dmz_dev *dev)
+void dmz_close_raw_dev(struct dmz_raw_dev *dev)
 {
 	if (dev->fd >= 0) {
 		close(dev->fd);
@@ -501,10 +538,20 @@ void dmz_close_dev(struct dmz_dev *dev)
 	dev->zones = NULL;
 }
 
+/*
+ * Close an open device.
+ */
+void dmz_close_dev(struct dmz_dev *dev)
+{
+	dmz_close_raw_dev(&dev->zoned_dev);
+	if (dev->has_regular)
+		dmz_close_raw_dev(&dev->regu_dev);
+}
+
 /*
  * Read a metadata block.
  */
-int dmz_read_block(struct dmz_dev *dev, __u64 block, __u8 *buf)
+int dmz_read_block(struct dmz_raw_dev *dev, __u64 block, __u8 *buf)
 {
 	ssize_t ret;
 
@@ -526,7 +573,7 @@ int dmz_read_block(struct dmz_dev *dev, __u64 block, __u8 *buf)
 /*
  * Write a metadata block.
  */
-int dmz_write_block(struct dmz_dev *dev, __u64 block, __u8 *buf)
+int dmz_write_block(struct dmz_raw_dev *dev, __u64 block, __u8 *buf)
 {
 	ssize_t ret;
 
@@ -547,7 +594,7 @@ int dmz_write_block(struct dmz_dev *dev, __u64 block, __u8 *buf)
 /*
  * Write a metadata block.
  */
-int dmz_sync_dev(struct dmz_dev *dev)
+int dmz_sync_dev(struct dmz_raw_dev *dev)
 {
 
 	printf("Syncing disk\n");
diff --git a/src/dmz_format.c b/src/dmz_format.c
index 62cb03b..30286cb 100644
--- a/src/dmz_format.c
+++ b/src/dmz_format.c
@@ -24,14 +24,14 @@
 
 #include <sys/types.h>
 #include <asm/byteorder.h>
-
 /*
  * Fill and write a super block.
  */
-int dmz_write_super(struct dmz_dev *dev,
+int dmz_write_super(struct dmz_raw_dev *dev,
 		    __u64 gen, __u64 offset)
 {
-	__u64 sb_block = dev->sb_block + offset;
+	struct dmz_dev *pdev = dev->pdev;
+	__u64 sb_block = pdev->sb_block + offset;
 	struct dm_zoned_super *sb;
 	__u32 crc;
 	__u8 *buf;
@@ -52,12 +52,12 @@ int dmz_write_super(struct dmz_dev *dev,
 	sb->gen = __cpu_to_le64(gen);
 
 	sb->sb_block = __cpu_to_le64(sb_block);
-	sb->nr_meta_blocks = __cpu_to_le32(dev->nr_meta_blocks);
-	sb->nr_reserved_seq = __cpu_to_le32(dev->nr_reserved_seq);
-	sb->nr_chunks = __cpu_to_le32(dev->nr_chunks);
+	sb->nr_meta_blocks = __cpu_to_le32(pdev->nr_meta_blocks);
+	sb->nr_reserved_seq = __cpu_to_le32(pdev->nr_reserved_seq);
+	sb->nr_chunks = __cpu_to_le32(pdev->nr_chunks);
 
-	sb->nr_map_blocks = __cpu_to_le32(dev->nr_map_blocks);
-	sb->nr_bitmap_blocks = __cpu_to_le32(dev->nr_bitmap_blocks);
+	sb->nr_map_blocks = __cpu_to_le32(pdev->nr_map_blocks);
+	sb->nr_bitmap_blocks = __cpu_to_le32(pdev->nr_bitmap_blocks);
 
 	crc = dmz_crc32(gen, sb, DMZ_BLOCK_SIZE);
 	sb->crc = __cpu_to_le32(crc);
@@ -77,7 +77,7 @@ int dmz_write_super(struct dmz_dev *dev,
 /*
  * Write mapping table blocks.
  */
-static int dmz_write_mapping(struct dmz_dev *dev,
+static int dmz_write_mapping(struct dmz_raw_dev *dev,
 			     __u64 offset)
 {
 	__u64 map_block;
@@ -102,8 +102,8 @@ static int dmz_write_mapping(struct dmz_dev *dev,
 	}
 
 	/* Write mapping table */
-	map_block = offset + dev->map_block;
-	for (i = 0; i < dev->nr_map_blocks; i++) {
+	map_block = offset + dev->pdev->map_block;
+	for (i = 0; i < dev->pdev->nr_map_blocks; i++) {
 		ret = dmz_write_block(dev, map_block + i, buf);
 		if (ret < 0) {
 			fprintf(stderr,
@@ -122,7 +122,7 @@ static int dmz_write_mapping(struct dmz_dev *dev,
 /*
  * Write zone bitmap blocks.
  */
-static int dmz_write_bitmap(struct dmz_dev *dev,
+static int dmz_write_bitmap(struct dmz_raw_dev *dev,
 			    __u64 offset)
 {
 	__u64 bitmap_block;
@@ -140,8 +140,8 @@ static int dmz_write_bitmap(struct dmz_dev *dev,
 	memset(buf, 0, DMZ_BLOCK_SIZE);
 
 	/* Clear bitmap blocks */
-	bitmap_block = offset + dev->bitmap_block;
-	for (i = 0; i < dev->nr_bitmap_blocks; i++) {
+	bitmap_block = offset + dev->pdev->bitmap_block;
+	for (i = 0; i < dev->pdev->nr_bitmap_blocks; i++) {
 		ret = dmz_write_block(dev, bitmap_block + i, buf);
 		if (ret < 0) {
 			fprintf(stderr,
@@ -160,7 +160,7 @@ static int dmz_write_bitmap(struct dmz_dev *dev,
 /*
  * Write formatted metadata blocks.
  */
-static int dmz_write_meta(struct dmz_dev *dev,
+static int dmz_write_meta(struct dmz_raw_dev *dev,
 			  __u64 offset)
 {
 
@@ -180,11 +180,20 @@ static int dmz_write_meta(struct dmz_dev *dev,
 	return 0;
 }
 
+struct dmz_raw_dev *dmz_metadev(struct dmz_dev *dev)
+{
+	if (dev->has_regular)
+		return &dev->regu_dev;
+	else
+		return &dev->zoned_dev;
+}
+
 /*
  * Format a device.
  */
 int dmz_format(struct dmz_dev *dev)
 {
+	struct dmz_raw_dev *mdev = dmz_metadev(dev);
 
 	/* calculate location of metadata blocks */
 	if (dmz_locate_metadata(dev) < 0)
@@ -199,7 +208,7 @@ int dmz_format(struct dmz_dev *dev)
 		printf("  Primary meta-data set: %u metadata blocks from block %llu (zone %u)\n",
 		       dev->nr_meta_blocks,
 		       dev->sb_block,
-		       dmz_zone_id(dev, dev->sb_zone));
+		       dmz_zone_id(mdev, dev->sb_zone));
 		printf("    Super block at block %llu and %llu\n",
 		       dev->sb_block,
 		       dev->sb_block + (dev->nr_meta_zones * dev->zone_nr_blocks));
@@ -231,25 +240,27 @@ int dmz_format(struct dmz_dev *dev)
 
 	/* Ready to write: first reset all zones */
 	printf("Resetting sequential zones\n");
-	if (dmz_reset_zones(dev) < 0)
+	if (dev->has_regular)
+		if (dmz_reset_zones(&dev->regu_dev) < 0)
+			return -1;
+	if (dmz_reset_zones(&dev->zoned_dev) < 0)
 		return -1;
 
 	/* Write primary metadata set */
 	printf("Writing primary metadata set\n");
-	if (dmz_write_meta(dev, 0) < 0)
+	if (dmz_write_meta(mdev, 0) < 0)
 		return -1;
 
 	/* Write secondary metadata set */
 	printf("Writing secondary metadata set\n");
-	if (dmz_write_meta(dev, dev->zone_nr_blocks * dev->nr_meta_zones) < 0)
+	if (dmz_write_meta(mdev, dev->zone_nr_blocks * dev->nr_meta_zones) < 0)
 		return -1;
 
 	/* Sync */
-	if (dmz_sync_dev(dev) < 0)
+	if (dmz_sync_dev(mdev) < 0)
 		return -1;
 
 	printf("Done.\n");
 
 	return 0;
 }
-
diff --git a/src/dmz_lib.c b/src/dmz_lib.c
index 2df0758..3c1874a 100644
--- a/src/dmz_lib.c
+++ b/src/dmz_lib.c
@@ -44,7 +44,7 @@ __u32 dmz_crc32(__u32 crc, const void *buf, size_t length)
 /*
  * Reset a zone.
  */
-int dmz_reset_zone(struct dmz_dev *dev,
+int dmz_reset_zone(struct dmz_raw_dev *dev,
 		   struct blk_zone *zone)
 {
 	struct blk_zone_range range;
@@ -73,7 +73,7 @@ int dmz_reset_zone(struct dmz_dev *dev,
 /*
  * Reset all zones of a device.
  */
-int dmz_reset_zones(struct dmz_dev *dev)
+int dmz_reset_zones(struct dmz_raw_dev *dev)
 {
 	unsigned int i;
 
@@ -85,21 +85,10 @@ int dmz_reset_zones(struct dmz_dev *dev)
 	return 0;
 }
 
-/*
- * Determine location and amount of metadata blocks.
- */
-int dmz_locate_metadata(struct dmz_dev *dev)
+static void count_useable_zones(struct dmz_raw_dev *dev)
 {
 	struct blk_zone *zone;
 	unsigned int i = 0;
-	unsigned int nr_meta_blocks, nr_map_blocks;
-	unsigned int nr_chunks, nr_meta_zones;
-	unsigned int nr_bitmap_zones;
-
-	dev->nr_useable_zones = 0;
-	dev->max_nr_meta_zones = 0;
-	dev->last_meta_zone = 0;
-	dev->nr_rnd_zones = 0;
 
 	/* Count useable zones */
 	for (i = 0; i < dev->nr_zones; i++) {
@@ -126,21 +115,43 @@ int dmz_locate_metadata(struct dmz_dev *dev)
 			       dmz_zone_id(dev, zone));
 			continue;
 		}
-		dev->nr_useable_zones++;
+		dev->pdev->nr_useable_zones++;
 
 		if (dmz_zone_rnd(zone)) {
-			if (dev->sb_zone == NULL) {
-				dev->sb_zone = zone;
-				dev->last_meta_zone = i;
-				dev->max_nr_meta_zones = 1;
-			} else if (dev->last_meta_zone == (i - 1)) {
-				dev->last_meta_zone = i;
-				dev->max_nr_meta_zones++;
+			if (dev->pdev->sb_zone == NULL) {
+				dev->pdev->sb_zone = zone;
+				dev->pdev->last_meta_zone = i;
+				dev->pdev->max_nr_meta_zones = 1;
+			} else if (dev->pdev->last_meta_zone == (i - 1)) {
+				dev->pdev->last_meta_zone = i;
+				dev->pdev->max_nr_meta_zones++;
 			}
-			dev->nr_rnd_zones++;
+			dev->pdev->nr_rnd_zones++;
 		}
-
 	}
+}
+
+/*
+ * Determine location and amount of metadata blocks.
+ */
+int dmz_locate_metadata(struct dmz_dev *dev)
+{
+	unsigned int nr_meta_blocks, nr_map_blocks;
+	unsigned int nr_chunks, nr_meta_zones;
+	unsigned int nr_bitmap_zones;
+
+	dev->nr_useable_zones = 0;
+	dev->max_nr_meta_zones = 0;
+	dev->last_meta_zone = 0;
+	dev->nr_rnd_zones = 0;
+
+	/*
+	 * Count regular device first, so that metadata zone will be in
+	 * regular device.
+	 */
+	if (dev->has_regular)
+		count_useable_zones(&dev->regu_dev);
+	count_useable_zones(&dev->zoned_dev);
 
 	/*
 	 * Randomly writeable zones are mandatory: at least 3
@@ -148,8 +159,8 @@ int dmz_locate_metadata(struct dmz_dev *dev)
 	 */
 	if (dev->nr_rnd_zones < 3) {
 		fprintf(stderr,
-			"%s: Not enough random zones found\n",
-			dev->name);
+			"%s:%s: Not enough random zones found\n",
+			dev->zoned_dev.name, dev->regu_dev.name);
 		return -1;
 	}
 
@@ -161,8 +172,8 @@ int dmz_locate_metadata(struct dmz_dev *dev)
 		dev->nr_reserved_seq = dev->nr_rnd_zones - 1;
 	if (dev->nr_reserved_seq >= dev->nr_useable_zones) {
 		fprintf(stderr,
-			"%s: Not enough useable zones found\n",
-			dev->name);
+			"%s:%s: Not enough useable zones found\n",
+			dev->zoned_dev.name, dev->regu_dev.name);
 		return -1;
 	}
 
@@ -181,8 +192,8 @@ int dmz_locate_metadata(struct dmz_dev *dev)
 
 	if ((nr_bitmap_zones + dev->nr_reserved_seq) > dev->nr_useable_zones) {
 		fprintf(stderr,
-			"%s: Not enough zones\n",
-			dev->name);
+			"%s:%s: Not enough zones\n",
+			dev->zoned_dev.name, dev->regu_dev.name);
 		return -1;
 	}
 
@@ -208,9 +219,9 @@ int dmz_locate_metadata(struct dmz_dev *dev)
 
 	if (dev->total_nr_meta_zones > dev->nr_rnd_zones) {
 		fprintf(stderr,
-			"%s: Insufficient number of random zones "
+			"%s:%s Insufficient number of random zones "
 			"(need %u, have %u)\n",
-			dev->name,
+			dev->zoned_dev.name, dev->regu_dev.name,
 			dev->total_nr_meta_zones,
 			dev->nr_rnd_zones);
 		return -1;
diff --git a/src/dmzadm.c b/src/dmzadm.c
index 0660d02..ff7e9cc 100644
--- a/src/dmzadm.c
+++ b/src/dmzadm.c
@@ -41,23 +41,55 @@ static void dmzadm_usage(void)
 	       "  --force	: Force overwrite of existing content\n"
 	       "  --seq <num>	: Number of sequential zones reserved\n"
 	       "                  for reclaim. The minimum is 1 and the\n"
-	       "                  default is %d\n",
+	       "                  default is %d\n"
+	       "  --regular <device path>: Use a regular block device\n"
+	       "                  for metadata and buffer writes\n",
 	       DMZ_NR_RESERVED_SEQ);
 }
 
+static void dump_info(struct dmz_raw_dev *dev)
+{
+	unsigned int nr_zones;
+	struct dmz_dev *pdev = dev->pdev;
+
+	printf("%s: %llu 512-byte sectors (%llu GiB)\n",
+	       dev->path,
+	       dev->capacity,
+	       (dev->capacity << 9) / (1024ULL * 1024ULL * 1024ULL));
+	printf("  Host-%s device\n",
+	       (pdev->flags & DMZ_ZONED_HM) ? "managed" : "aware");
+	nr_zones = dev->capacity / dev->zone_nr_sectors;
+	printf("  %u zones of %zu 512-byte sectors (%zu MiB)\n",
+	       nr_zones,
+	       dev->zone_nr_sectors,
+	       (dev->zone_nr_sectors << 9) / (1024 * 1024));
+	if (nr_zones < dev->nr_zones) {
+		size_t runt_sectors = dev->capacity & (dev->zone_nr_sectors - 1);
+
+		printf("  1 runt zone of %zu 512-byte sectors (%zu MiB)\n",
+		       runt_sectors,
+		       (runt_sectors << 9) / (1024 * 1024));
+	}
+	printf("  %zu 4KB data blocks per zone\n",
+	       dev->zone_nr_blocks);
+
+}
+
 /*
  * Main function.
  */
 int main(int argc, char **argv)
 {
-	unsigned int nr_zones;
 	struct dmz_dev dev;
-	int i, ret;
+	int i, ret = 0;
 	enum dmz_op op;
 
 	/* Initialize */
 	memset(&dev, 0, sizeof(dev));
-	dev.fd = -1;
+	dev.zoned_dev.fd = -1;
+	dev.regu_dev.fd = -1;
+	dev.zoned_dev.pdev = &dev;
+	dev.regu_dev.pdev = &dev;
 	dev.nr_reserved_seq = DMZ_NR_RESERVED_SEQ;
 
 	/* Parse operation */
@@ -90,7 +122,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Get device path */
-	dev.path = argv[2];
+	dev.zoned_dev.path = argv[2];
 
 	/* Parse arguments */
 	for (i = 3; i < argc; i++) {
@@ -118,7 +150,15 @@ int main(int argc, char **argv)
 					"Invalid number of sequential zones\n");
 				return 1;
 			}
-
+		} else if (strncmp(argv[i], "--regular=", 10) == 0) {
+			if (op != DMZ_OP_FORMAT) {
+				fprintf(stderr,
+					"--regular option is valid only with the "
+					"format operation\n");
+				return 1;
+			}
+			dev.regu_dev.path = argv[i] + 10;
+			dev.has_regular = 1;
 		} else if (strcmp(argv[i], "--force") == 0) {
 
 			if (op != DMZ_OP_FORMAT) {
@@ -149,26 +189,9 @@ int main(int argc, char **argv)
 	if (dmz_open_dev(&dev, op) < 0)
 		return 1;
 
-	printf("%s: %llu 512-byte sectors (%llu GiB)\n",
-	       dev.path,
-	       dev.capacity,
-	       (dev.capacity << 9) / (1024ULL * 1024ULL * 1024ULL));
-	printf("  Host-%s device\n",
-	       (dev.flags & DMZ_ZONED_HM) ? "managed" : "aware");
-	nr_zones = dev.capacity / dev.zone_nr_sectors;
-	printf("  %u zones of %zu 512-byte sectors (%zu MiB)\n",
-	       nr_zones,
-	       dev.zone_nr_sectors,
-	       (dev.zone_nr_sectors << 9) / (1024 * 1024));
-	if (nr_zones < dev.nr_zones) {
-		size_t runt_sectors = dev.capacity & (dev.zone_nr_sectors - 1);
-
-		printf("  1 runt zone of %zu 512-byte sectors (%zu MiB)\n",
-		       runt_sectors,
-		       (runt_sectors << 9) / (1024 * 1024));
-	}
-	printf("  %zu 4KB data blocks per zone\n",
-	       dev.zone_nr_blocks);
+	dump_info(&dev.zoned_dev);
+	if (dev.has_regular)
+		dump_info(&dev.regu_dev);
 
 	switch (op) {
 
@@ -176,6 +199,7 @@ int main(int argc, char **argv)
 		ret = dmz_format(&dev);
 		break;
 
+#if 0
 	case DMZ_OP_CHECK:
 		ret = dmz_check(&dev);
 		break;
@@ -183,6 +207,7 @@ int main(int argc, char **argv)
 	case DMZ_OP_REPAIR:
 		ret = dmz_repair(&dev);
 		break;
+#endif
 
 	default:
 

[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux