linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2][V11] btrfs-progs: allocation_hint disk property
@ 2022-01-26 20:32 Goffredo Baroncelli
  2022-01-26 20:32 ` [PATCH 1/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli
  2022-01-26 20:32 ` [PATCH 2/2] Update man page for allocator_hint property Goffredo Baroncelli
  0 siblings, 2 replies; 3+ messages in thread
From: Goffredo Baroncelli @ 2022-01-26 20:32 UTC (permalink / raw)
  To: linux-btrfs
  Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq,
	Paul Jones, Boris Burkov, Goffredo Baroncelli

From: Goffredo Baroncelli <kreijack@inwind.it>

This patches set is the userspace portion of the serie
"[PATCH V11] btrfs: allocation_hint".

Look this patches set for further information.

Changelog
V11: 
- find the correct /sys/fs/btrfs/<UUID> directory using the
devinfo/major_minor sysfs file.
- update the man page to the .rst file format

G.Baroncelli

Goffredo Baroncelli (2):
  btrfs-progs: new "allocation_hint" property.
  Update man page for allocator_hint property.

 Documentation/btrfs-property.rst |  21 +++
 cmds/property.c                  | 253 +++++++++++++++++++++++++++++++
 kernel-shared/ctree.h            |  13 ++
 3 files changed, 287 insertions(+)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] btrfs-progs: new "allocation_hint" property.
  2022-01-26 20:32 [PATCH 0/2][V11] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
@ 2022-01-26 20:32 ` Goffredo Baroncelli
  2022-01-26 20:32 ` [PATCH 2/2] Update man page for allocator_hint property Goffredo Baroncelli
  1 sibling, 0 replies; 3+ messages in thread
From: Goffredo Baroncelli @ 2022-01-26 20:32 UTC (permalink / raw)
  To: linux-btrfs
  Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq,
	Paul Jones, Boris Burkov, Goffredo Baroncelli

From: Goffredo Baroncelli <kreijack@inwind.it>

Handle the property allocation_hint of a btrfs device. Below
an example of use:

$ # set a new value
$ sudo btrfs property set /dev/vde allocation_hint DATA_ONLY

$ # get the current value
$ sudo btrfs property get /dev/vde allocation_hint
devid=4, path=/dev/vde: allocation_hint=DATA_ONLY

The following values are availables:
- DATA_ONLY
- DATA_PREFERRED (default)
- METADATA_PREFERRED
- METADATA_ONLY

Root privileges are required.

Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
 cmds/property.c       | 253 ++++++++++++++++++++++++++++++++++++++++++
 kernel-shared/ctree.h |  13 +++
 2 files changed, 266 insertions(+)

diff --git a/cmds/property.c b/cmds/property.c
index b3ccc0ff..a409f4e9 100644
--- a/cmds/property.c
+++ b/cmds/property.c
@@ -22,6 +22,7 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/xattr.h>
+#include <sys/sysmacros.h>
 #include <uuid/uuid.h>
 #include <btrfsutil.h>
 #include "cmds/commands.h"
@@ -232,6 +233,252 @@ out:
 	return ret;
 }
 
+/*
+ * @major, @minor -> device to find
+ * @uuid -> uuid of the filesystem (out)
+ * @devid -> devid (out)
+ *
+ * return -> -ENOTSUP	operation not supported (i.e. btrfs doesn't
+ *			support allocation_hint)
+ *	  -> -ENODEV	operation supported, but device not mounted
+ *	  -> -EACCES	error accessing sysfs
+ *	  -> 0		ok
+ */
+#define BTRFSYSFS "/sys/fs/btrfs/"
+static int btrfs_find_devid_uuid_by_major_minor(int major,
+						  int minor,
+						  u64 *devid,
+						  char *uuid) {
+
+	DIR *dp = NULL, *dp2 = NULL;
+	char path[200];  /* should be enough for
+			  * /sys/btrfs/<uuid>/devices/<devid>/major_minor
+			  */
+	int ret;
+	struct dirent *de;
+	int l;
+
+	strcpy(path, BTRFSYSFS);
+	dp = opendir(path);
+	if (!dp) {
+		ret = -EACCES;
+		goto quit;
+	}
+
+	while ((de = readdir(dp)) != NULL) {
+		if (strlen(de->d_name) != 36)
+			continue;
+
+		strcpy(path + sizeof(BTRFSYSFS) - 1, de->d_name);
+		strcat(path, "/devinfo/");
+
+		dp2 = opendir(path);
+		if (!dp2) {
+			ret = -EACCES;
+			goto quit;
+		}
+
+		l = strlen(path);
+		while ((de = readdir(dp2)) != NULL) {
+			FILE *fp;
+			char buf[100];
+			char *endptr;
+			int r, maj, mnr;
+
+			errno = 0;
+			*devid = strtoull(de->d_name, &endptr, 0);
+
+			/* check for invalid devid */
+			if (errno || *endptr != 0)
+				continue;
+
+
+			strcpy(path + l, de->d_name);
+			strcat(path, "/major_minor");
+
+			fp = fopen(path, "r");
+			if (!fp) {
+				if (errno == -ENOENT)
+					ret = -ENOTSUP;
+				else
+					ret = -EACCES;
+				goto quit;
+			}
+			r = fread(buf, 1, sizeof(buf) - 2, fp);
+			buf[r] = 0;
+			fclose(fp);
+
+			if (!strcmp(buf, "N/A\n"))
+				continue;
+
+			r = sscanf(buf, "%d:%d", &maj, &mnr);
+			if (r != 2) {
+				ret = -EACCES;
+				goto quit;
+			}
+
+			if (maj == major && minor == mnr) {
+				strncpy(uuid,
+					path + sizeof(BTRFSYSFS) - 1,
+					36);
+				uuid[36] = 0;
+				ret = 0;
+				goto quit;
+			}
+		}
+	}
+
+	ret = -ENODEV;
+quit:
+	if (dp)
+		closedir(dp);
+	if (dp2)
+		closedir(dp2);
+	return ret;
+}
+
+/*
+ * @dev -> device to find
+ * @uuid -> uuid of the filesystem (out)
+ * @devid -> devid (out)
+ *
+ * return -> -ENOTSUP	operation not supported (i.e. btrfs doesn't
+ *			support allocation_hint)
+ *	  -> -ENODEV	operation supported, but device not mounted
+ *	  -> -EACCES	error accessing sysfs
+ *	  -> 0		ok
+ */
+static int btrfs_find_devid_uuid_by_dev(const char *dev,
+					u64 *devid,
+					char *uuid)
+{
+	struct stat st;
+	int r;
+
+	r = stat(dev, &st);
+	if (r < 0 && errno == -ENODEV)
+		return -ENODEV;
+	if (r < 0)
+		return -EACCES;
+
+	return btrfs_find_devid_uuid_by_major_minor(major(st.st_rdev),
+						    minor(st.st_rdev),
+						    devid, uuid);
+}
+
+static struct ull_charp_pair_t {
+	u64		value;
+	const char	*descr;
+} allocation_hint_description[] = {
+	{BTRFS_DEV_ALLOCATION_HINT_METADATA_PREFERRED, "METADATA_PREFERRED"},
+	{BTRFS_DEV_ALLOCATION_HINT_METADATA_ONLY, "METADATA_ONLY"},
+	{BTRFS_DEV_ALLOCATION_HINT_DATA_PREFERRED, "DATA_PREFERRED"},
+	{BTRFS_DEV_ALLOCATION_HINT_DATA_ONLY, "DATA_ONLY"},
+	{0, NULL}
+};
+
+static int prop_allocation_hint(enum prop_object_type type,
+				const char *object,
+				const char *name,
+				const char *val,
+				bool force)
+{
+	int ret, fd2 = -1;
+	u64 devid;
+	char sysfs_file[PATH_MAX];
+	int i;
+	u64 v;
+	char buf[1024];
+
+	strcpy(sysfs_file, BTRFSYSFS);
+	ret = btrfs_find_devid_uuid_by_dev(object, &devid,
+		sysfs_file + sizeof(BTRFSYSFS) - 1);
+
+	if (ret)
+		goto out;
+
+	sprintf(sysfs_file + strlen(sysfs_file),
+		"/devinfo/%llu/allocation_hint", devid);
+
+	if (!val) {
+		/* READ */
+		fd2 = open(sysfs_file, O_RDONLY);
+		if (fd2 < 0 && errno == ENOENT) {
+			/* older kernel doesn't have allocation_hint; return nothing */
+			ret = 0;
+			goto out;
+		} else if (fd2 < 0) {
+			error("'allocation_hint' property not available or accessible.");
+			ret = -errno;
+			goto out;
+		}
+
+		ret = read(fd2, buf, sizeof(buf) - 1);
+		if (ret < 0) {
+			error("Unable to read the 'allocation_hint' property.");
+			ret = -errno;
+			goto out;
+		}
+
+		buf[sizeof(buf) - 1] = 0;
+		v = strtoull(buf, NULL, 0);
+
+		for (i = 0 ; allocation_hint_description[i].descr ; i++)
+			if (v == allocation_hint_description[i].value)
+				break;
+
+		if (allocation_hint_description[i].descr)
+			printf("allocation_hint=%s\n",
+				allocation_hint_description[i].descr);
+		else
+			printf("allocation_hint=unknown:%llu\n", v);
+		ret = 0;
+	} else {
+		/* WRITE */
+		for (i = 0 ; allocation_hint_description[i].descr ; i++)
+			if (!strcmp(val, allocation_hint_description[i].descr))
+				break;
+
+		if (allocation_hint_description[i].descr) {
+			v = allocation_hint_description[i].value;
+		} else if (sscanf(val, "%llu", &v) != 1) {
+			error("Invalid value '%s'\n", val);
+			ret = -3;
+			goto out;
+		}
+		if (v & ~BTRFS_DEV_ALLOCATION_HINT_MASK) {
+			error("Invalid value '%s'\n", val);
+			ret = -3;
+			goto out;
+		}
+
+		fd2 = open(sysfs_file, O_RDWR);
+		if (fd2 < 0) {
+			error("'allocation_hint' property not available or accessible for updating.");
+			ret = -errno;
+			goto out;
+		}
+
+		sprintf(buf, "%llu", v);
+
+		ret = write(fd2, buf, strlen(buf));
+
+		if (ret != strlen(buf)) {
+			error("Unable to update 'allocation_hint' property.");
+			ret = -errno;
+			goto out;
+		}
+
+	}
+
+	ret = 0;
+out:
+	if (fd2 >= 0)
+		close(fd2);
+
+	return ret;
+}
+
 const struct prop_handler prop_handlers[] = {
 	{
 		.name ="ro",
@@ -254,6 +501,12 @@ const struct prop_handler prop_handlers[] = {
 		.types = prop_object_inode,
 		.handler = prop_compression
 	},
+	{
+		.name = "allocation_hint",
+		.desc = "hint to store the data/metadata chunks",
+		.types = prop_object_dev,
+		.handler = prop_allocation_hint
+	},
 	{NULL, NULL, 0, 0, NULL}
 };
 
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index ab2aaed6..628539c0 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -216,6 +216,19 @@ struct btrfs_mapping_tree {
 	struct cache_tree cache_tree;
 };
 
+/* btrfs chunk allocation hints */
+#define BTRFS_DEV_ALLOCATION_HINT_BIT_COUNT    2
+#define BTRFS_DEV_ALLOCATION_HINT_MASK ((1ULL << \
+	       BTRFS_DEV_ALLOCATION_HINT_BIT_COUNT) - 1)
+/* preferred metadata chunk, but data chunk allowed */
+#define BTRFS_DEV_ALLOCATION_HINT_METADATA_PREFERRED        (1ULL)
+/* only metadata chunk are allowed */
+#define BTRFS_DEV_ALLOCATION_HINT_METADATA_ONLY     (2ULL)
+/* only data chunk allowed */
+#define BTRFS_DEV_ALLOCATION_HINT_DATA_ONLY         (3ULL)
+/* preferred data chunk, but metadata chunk allowed */
+#define BTRFS_DEV_ALLOCATION_HINT_DATA_PREFERRED    (0ULL)
+
 #define BTRFS_UUID_SIZE 16
 struct btrfs_dev_item {
 	/* the internal btrfs device id */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] Update man page for allocator_hint property.
  2022-01-26 20:32 [PATCH 0/2][V11] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
  2022-01-26 20:32 ` [PATCH 1/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli
@ 2022-01-26 20:32 ` Goffredo Baroncelli
  1 sibling, 0 replies; 3+ messages in thread
From: Goffredo Baroncelli @ 2022-01-26 20:32 UTC (permalink / raw)
  To: linux-btrfs
  Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq,
	Paul Jones, Boris Burkov, Goffredo Baroncelli

From: Goffredo Baroncelli <kreijack@inwind.it>

Update the man page of the btrfs property subcommand to show the use
of the device property "allocation_hint".

Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
 Documentation/btrfs-property.rst | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/Documentation/btrfs-property.rst b/Documentation/btrfs-property.rst
index 5896faa2..155839fe 100644
--- a/Documentation/btrfs-property.rst
+++ b/Documentation/btrfs-property.rst
@@ -48,6 +48,27 @@ get [-t <type>] <object> [<name>]
         compression
                 compression algorithm set for an inode, possible values: *lzo*, *zlib*, *zstd*.
                 To disable compression use "" (empty string), *no* or *none*.
+        allocation_hint
+                a device property that instructs how and when the allocator should use a
+                block device.
+                Possible values are:
+
+                METADATA_PREFERRED
+                        the device has an higher priority when a new metadata
+                        chunk is allocated. Data chunk is allowed only if there is no other
+                        possibility.
+                METADATA_ONLY
+                        the device is used only for metadata chunk.
+                        Data chunk is never allowed.
+                DATA_PREFERRED (default)
+                        the device has an higher priority when a new data
+                        chunk is allocated. Metadata chunk is allowed only if there is no other
+                        possibility.
+                DATA_ONLY
+                        the device is used only for data chunk. Metadata chunk is never allowed.
+
+                The default is 'DATA_PREFERRED'; if all the disks have this setting the
+                allocator uses all of them with the same priority.
 
 list [-t <type>] <object>
         Lists available properties with their descriptions for the given object.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-01-26 20:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-26 20:32 [PATCH 0/2][V11] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
2022-01-26 20:32 ` [PATCH 1/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli
2022-01-26 20:32 ` [PATCH 2/2] Update man page for allocator_hint property Goffredo Baroncelli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).