[v5,06/15] btrfs-progs: load and check zone information
diff mbox series

Message ID 20191204082513.857320-7-naohiro.aota@wdc.com
State New
Headers show
Series
  • btrfs-progs: zoned block device support
Related show

Commit Message

Naohiro Aota Dec. 4, 2019, 8:25 a.m. UTC
This patch checks if a device added to btrfs is a zoned block device. If it
is, load zones information and the zone size for the device.

For a btrfs volume composed of multiple zoned block devices, all devices
must have the same zone size.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
 common/device-scan.c | 15 +++++++++++++++
 common/hmzoned.h     |  2 ++
 volumes.c            | 31 +++++++++++++++++++++++++++++++
 volumes.h            |  4 ++++
 4 files changed, 52 insertions(+)

Patch
diff mbox series

diff --git a/common/device-scan.c b/common/device-scan.c
index 48dbd9e19715..548e1322bb70 100644
--- a/common/device-scan.c
+++ b/common/device-scan.c
@@ -29,6 +29,7 @@ 
 #include "kernel-lib/overflow.h"
 #include "common/path-utils.h"
 #include "common/device-scan.h"
+#include "common/hmzoned.h"
 #include "common/messages.h"
 #include "common/utils.h"
 #include "common-defs.h"
@@ -137,6 +138,19 @@  int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
 		goto out;
 	}
 
+	ret = btrfs_get_zone_info(fd, path, fs_info->fs_devices->hmzoned,
+				  &device->zone_info);
+	if (ret)
+		goto out;
+	if (fs_info->fs_devices->hmzoned) {
+		if (device->zone_info->zone_size !=
+		    fs_info->fs_devices->zone_size) {
+			error("Device zone size differ");
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
 	disk_super = (struct btrfs_super_block *)buf;
 	dev_item = &disk_super->dev_item;
 
@@ -197,6 +211,7 @@  int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
 	return 0;
 
 out:
+	free(device->zone_info);
 	free(device);
 	free(buf);
 	return ret;
diff --git a/common/hmzoned.h b/common/hmzoned.h
index 098952061bfb..d229b946e5ed 100644
--- a/common/hmzoned.h
+++ b/common/hmzoned.h
@@ -18,6 +18,8 @@ 
 #ifndef __BTRFS_HMZONED_H__
 #define __BTRFS_HMZONED_H__
 
+#include <stdbool.h>
+
 #ifdef BTRFS_ZONED
 #include <linux/blkzoned.h>
 #else
diff --git a/volumes.c b/volumes.c
index 8bfffa5586eb..d92052e19330 100644
--- a/volumes.c
+++ b/volumes.c
@@ -27,6 +27,7 @@ 
 #include "transaction.h"
 #include "print-tree.h"
 #include "volumes.h"
+#include "common/hmzoned.h"
 #include "common/utils.h"
 #include "kernel-lib/raid56.h"
 
@@ -214,6 +215,8 @@  static int device_list_add(const char *path,
 	u64 found_transid = btrfs_super_generation(disk_super);
 	bool metadata_uuid = (btrfs_super_incompat_flags(disk_super) &
 		BTRFS_FEATURE_INCOMPAT_METADATA_UUID);
+	bool hmzoned = btrfs_super_incompat_flags(disk_super) &
+		BTRFS_FEATURE_INCOMPAT_HMZONED;
 
 	if (metadata_uuid)
 		fs_devices = find_fsid(disk_super->fsid,
@@ -238,8 +241,18 @@  static int device_list_add(const char *path,
 		fs_devices->latest_devid = devid;
 		fs_devices->latest_trans = found_transid;
 		fs_devices->lowest_devid = (u64)-1;
+		fs_devices->hmzoned = hmzoned;
 		device = NULL;
 	} else {
+		if (fs_devices->hmzoned != hmzoned) {
+			if (hmzoned)
+				error(
+			"Cannot add HMZONED device to non-HMZONED file system");
+			else
+				error(
+			"Cannot add non-HMZONED device to HMZONED file system");
+			return -EINVAL;
+		}
 		device = find_device(fs_devices, devid,
 				       disk_super->dev_item.uuid);
 	}
@@ -335,6 +348,7 @@  again:
 		/* free the memory */
 		free(device->name);
 		free(device->label);
+		free(device->zone_info);
 		free(device);
 	}
 
@@ -373,6 +387,8 @@  int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, int flags)
 	struct btrfs_device *device;
 	int ret;
 
+	fs_devices->zone_size = 0;
+
 	list_for_each_entry(device, &fs_devices->devices, dev_list) {
 		if (!device->name) {
 			printk("no name for device %llu, skip it now\n", device->devid);
@@ -396,6 +412,21 @@  int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, int flags)
 		device->fd = fd;
 		if (flags & O_RDWR)
 			device->writeable = 1;
+
+		ret = btrfs_get_zone_info(fd, device->name, fs_devices->hmzoned,
+					  &device->zone_info);
+		if (ret != 0)
+			goto fail;
+		if (!device->zone_info)
+			continue;
+		if (!fs_devices->zone_size) {
+			fs_devices->zone_size = device->zone_info->zone_size;
+		} else if (device->zone_info->zone_size !=
+			   fs_devices->zone_size) {
+			error("Device zone size differ");
+			ret = -EINVAL;
+			goto fail;
+		}
 	}
 	return 0;
 fail:
diff --git a/volumes.h b/volumes.h
index 41574f21dd23..d52dbcba0410 100644
--- a/volumes.h
+++ b/volumes.h
@@ -28,6 +28,7 @@  struct btrfs_device {
 	struct list_head dev_list;
 	struct btrfs_root *dev_root;
 	struct btrfs_fs_devices *fs_devices;
+	struct btrfs_zoned_device_info *zone_info;
 
 	u64 total_ios;
 
@@ -87,6 +88,9 @@  struct btrfs_fs_devices {
 
 	int seeding;
 	struct btrfs_fs_devices *seed;
+
+	u64 zone_size;
+	bool hmzoned;
 };
 
 struct btrfs_bio_stripe {