From: Goffredo Baroncelli <kreijack@libero.it>
To: linux-btrfs@vger.kernel.org
Cc: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>,
Josef Bacik <josef@toxicpanda.com>,
Goffredo Baroncelli <kreijack@inwind.it>
Subject: [PATCH 2/2] btrfs-progs: new "allocation_hint" property.
Date: Mon, 1 Feb 2021 22:28:29 +0100 [thread overview]
Message-ID: <20210201212829.64966-3-kreijack@libero.it> (raw)
In-Reply-To: <20210201212829.64966-1-kreijack@libero.it>
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: dedicated_metadata=DATA_ONLY
The following properties are availables:
- DATA_ONLY
- PREFERRED_DATA (default)
- PREFERRED_METADATA
- METADATA_ONLY
Root privileges are required.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
kernel-shared/ctree.h | 15 ++++
props.c | 170 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 185 insertions(+)
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 7683b8bb..844df9ce 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -219,6 +219,21 @@ struct btrfs_mapping_tree {
struct cache_tree cache_tree;
};
+/* btrfs chunk allocation hints */
+#define BTRFS_DEV_ALLOCATION_MASK_BIT_COUNT 3
+#define BTRFS_DEV_ALLOCATION_MASK ((1ULL << \
+ BTRFS_DEV_ALLOCATION_MASK_BIT_COUNT) -1)
+/* preferred metadata chunk, but data chunk allowed */
+#define BTRFS_DEV_ALLOCATION_PREFERRED_METADATA (1ULL)
+/* only metadata chunk are allowed */
+#define BTRFS_DEV_ALLOCATION_METADATA_ONLY (2ULL)
+/* only data chunk allowed */
+#define BTRFS_DEV_ALLOCATION_DATA_ONLY (3ULL)
+/* preferred data chunk, but metadata chunk allowed */
+#define BTRFS_DEV_ALLOCATION_PREFERRED_DATA (0ULL)
+/* 5..7 are unused values */
+
+
#define BTRFS_UUID_SIZE 16
struct btrfs_dev_item {
/* the internal btrfs device id */
diff --git a/props.c b/props.c
index 0cfc358d..2f5f6482 100644
--- a/props.c
+++ b/props.c
@@ -20,6 +20,7 @@
#include <sys/xattr.h>
#include <fcntl.h>
#include <unistd.h>
+#include <sys/sysmacros.h>
#include <btrfsutil.h>
@@ -166,6 +167,169 @@ out:
return ret;
}
+static int btrfs_find_devid_and_mnt(const char *devpath, int *devid,
+ char *path, int maxpath)
+{
+ int ret, i, fd;
+ DIR *dir;
+ struct stat stdevpath;
+ struct btrfs_ioctl_fs_info_args fi_args;
+ struct btrfs_ioctl_dev_info_args dev_info;
+
+ ret = get_btrfs_mount(devpath, path, maxpath);
+ if (ret)
+ return ret;
+
+ fd = btrfs_open_dir(path, &dir, 1);
+ if (fd < 0)
+ return fd;
+
+ ret = stat(devpath, &stdevpath);
+ if (ret) {
+ error("cannot stat '%s'", devpath);
+ goto out;
+ }
+
+ ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
+ if (ret < 0) {
+ if (errno == EPERM)
+ return -errno;
+ error("cannot get filesystem info: %m");
+ ret = -10;
+ goto out;
+ }
+
+ for (i = 0 ; i <= fi_args.max_id ; i++) {
+ struct stat st;
+ memset(&dev_info, 0, sizeof(dev_info));
+ ret = get_device_info(fd, i, &dev_info);
+ if (ret == -ENODEV)
+ continue;
+ if (ret) {
+ error("cannot get info about device devid=%d", i);
+ goto out;
+ }
+
+ if (!dev_info.path)
+ /* missing devices */
+ continue;
+
+ ret = stat((char*)dev_info.path, &st);
+ if (ret) {
+ error("cannot stat '%s'", devpath);
+ goto out;
+ }
+
+ if (major(st.st_rdev) == major(stdevpath.st_rdev) &&
+ minor(st.st_rdev) == minor(stdevpath.st_rdev)) {
+ *devid = dev_info.devid;
+ ret = 0;
+ goto out;
+ }
+ }
+
+ ret = -12;
+
+out:
+ close_file_or_dir(fd, dir);
+ return ret;
+}
+
+static struct ull_charp_pair_t {
+ u64 value;
+ const char *descr;
+} allocation_hint_description[] = {
+ {BTRFS_DEV_ALLOCATION_PREFERRED_METADATA, "PREFERRED_METADATA"},
+ {BTRFS_DEV_ALLOCATION_METADATA_ONLY, "METADATA_ONLY"},
+ {BTRFS_DEV_ALLOCATION_PREFERRED_DATA, "PREFERRED_DATA"},
+ {BTRFS_DEV_ALLOCATION_DATA_ONLY, "DATA_ONLY"},
+ {0, NULL}
+};
+
+
+static int prop_allocation_hint(enum prop_object_type type,
+ const char *object,
+ const char *name,
+ const char *value)
+{
+ int ret, devid, fd;
+ char path[PATH_MAX];
+ DIR *dir;
+ struct btrfs_ioctl_dev_properties props;
+ int i;
+ u64 v;
+
+ ret = btrfs_find_devid_and_mnt(object, &devid, path, sizeof(path));
+ if (ret)
+ return -5;
+
+ fd = btrfs_open_dir(path, &dir, 1);
+ if (fd < 0)
+ return fd;
+
+ memset(&props, 0, sizeof(props));
+ props.devid = devid;
+ props.properties = BTRFS_DEV_PROPERTY_TYPE|BTRFS_DEV_PROPERTY_READ;
+ ret = ioctl(fd, BTRFS_IOC_DEV_PROPERTIES, &props);
+ if (ret < 0) {
+ error("Cannot perform BTRFS_IOC_DEV_PROPERTIES ioctl on '%s'",
+ path);
+ ret = -1;
+ goto out;
+ }
+
+ if (!value) {
+ v = props.type & BTRFS_DEV_ALLOCATION_MASK;
+ for (i = 0 ; allocation_hint_description[i].descr ; i++)
+ if (v == allocation_hint_description[i].value)
+ break;
+ if (allocation_hint_description[i].descr)
+ printf("devid=%d, path=%s: allocation_hint=%s\n",
+ devid, object,
+ allocation_hint_description[i].descr);
+ else
+ printf("devid=%d, path=%s: allocation_hint=unknow:%llu\n",
+ devid, object,
+ v);
+ ret = 0;
+ goto out;
+ }
+
+ for (i = 0 ; allocation_hint_description[i].descr ; i++)
+ if (!strcmp(value, allocation_hint_description[i].descr))
+ break;
+
+ if (allocation_hint_description[i].descr) {
+ v = allocation_hint_description[i].value;
+ } else if (sscanf(value, "%llu", &v) != 1) {
+ error("Invalid value '%s'\n", value);
+ ret = -3;
+ goto out;
+ } else if (v & ~BTRFS_DEV_ALLOCATION_MASK) {
+ error("Invalid value '%s'\n", value);
+ ret = -3;
+ goto out;
+ }
+
+ props.type &= ~BTRFS_DEV_ALLOCATION_MASK;
+ props.type |= (v & BTRFS_DEV_ALLOCATION_MASK);
+
+ props.properties = BTRFS_DEV_PROPERTY_TYPE;
+ props.devid = devid;
+ ret = ioctl(fd, BTRFS_IOC_DEV_PROPERTIES, &props);
+ if (ret < 0) {
+ error("Cannot perform BTRFS_IOC_DEV_PROPERTIES ioctl on '%s'",
+ path);
+ ret = -4;
+ goto out;
+ }
+
+ ret = 0;
+out:
+ close_file_or_dir(fd, dir);
+ return ret;
+}
+
const struct prop_handler prop_handlers[] = {
{
.name ="ro",
@@ -187,5 +351,11 @@ const struct prop_handler prop_handlers[] = {
.read_only = 0,
.types = prop_object_inode, prop_compression
},
+ {
+ .name = "allocation_hint",
+ .desc = "hint to store teh data/metadata chunks",
+ .types = prop_object_dev,
+ .handler = prop_allocation_hint
+ },
{NULL, NULL, 0, 0, NULL}
};
--
2.30.0
next prev parent reply other threads:[~2021-02-01 21:29 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-01 21:28 [RFC][PATCH V5] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
2021-02-01 21:28 ` [PATCH 1/2] btrfs-progs: add ioctl BTRFS_IOC_DEV_PROPERTIES Goffredo Baroncelli
2021-02-01 21:28 ` Goffredo Baroncelli [this message]
-- strict thread matches above, loose matches on Subject: below --
2021-02-22 21:31 [PATCH 0/2] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
2021-02-22 21:31 ` [PATCH 2/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210201212829.64966-3-kreijack@libero.it \
--to=kreijack@libero.it \
--cc=ce3g8jdj@umail.furryterror.org \
--cc=josef@toxicpanda.com \
--cc=kreijack@inwind.it \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox