From: Boris Burkov <boris@bur.io>
To: Goffredo Baroncelli <kreijack@libero.it>
Cc: linux-btrfs@vger.kernel.org,
Zygo Blaxell <ce3g8jdj@umail.furryterror.org>,
Josef Bacik <josef@toxicpanda.com>,
David Sterba <dsterba@suse.cz>,
Sinnamohideen Shafeeq <shafeeqs@panasas.com>,
Goffredo Baroncelli <kreijack@inwind.it>
Subject: Re: [PATCH 1/2] btrfs-progs: new "allocation_hint" property.
Date: Tue, 4 Jan 2022 18:29:49 -0800 [thread overview]
Message-ID: <YdUChLjZz80FS5u4@zen> (raw)
In-Reply-To: <21fcdf5d4186555b743190e62ad3011c08aaad9b.1639766708.git.kreijack@inwind.it>
On Fri, Dec 17, 2021 at 07:47:04PM +0100, Goffredo Baroncelli wrote:
> 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
I applied this patchset to the master branch of
git://github.com/kdave/btrfs-progs.git
and this command failed with something like "not a btrfs object".
However, it worked fine as:
$ sudo btrfs property set -t device /dev/DEV allocation_hint DATA_ONLY
I can't think of a reason I would hit this error and you wouldn't, since
that check is relatively old, but figured I would mention it.
>
> $ # 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
> - PREFERRED_DATA (default)
> - PREFERRED_METADATA
> - METADATA_ONLY
>
> Root privileges are required.
>
> Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
> ---
> cmds/property.c | 204 ++++++++++++++++++++++++++++++++++++++++++
> kernel-shared/ctree.h | 13 +++
> 2 files changed, 217 insertions(+)
>
> diff --git a/cmds/property.c b/cmds/property.c
> index 59ef997c..e6a38ee1 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"
> @@ -30,6 +31,7 @@
> #include "common/open-utils.h"
> #include "common/utils.h"
> #include "common/help.h"
> +#include "common/path-utils.h"
>
> #define XATTR_BTRFS_PREFIX "btrfs."
> #define XATTR_BTRFS_PREFIX_LEN (sizeof(XATTR_BTRFS_PREFIX) - 1)
> @@ -232,6 +234,202 @@ 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_HINT_PREFERRED_METADATA, "PREFERRED_METADATA"},
> + {BTRFS_DEV_ALLOCATION_HINT_METADATA_ONLY, "METADATA_ONLY"},
> + {BTRFS_DEV_ALLOCATION_HINT_PREFERRED_DATA, "PREFERRED_DATA"},
> + {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 *value,
> + bool force)
> +{
> + int ret, devid, fd, fd2;
> + char path[PATH_MAX];
> + DIR *dir;
> + u8 fsid[BTRFS_UUID_SIZE];
> + char fsid_str[BTRFS_UUID_UNPARSED_SIZE];
> + char sysfs_file[PATH_MAX];
> + char filename[PATH_MAX];
> + int i;
> + u64 v, devtype;
> + char buf[1024];
> +
> + 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;
> +
> + ret = get_fsid_fd(fd, fsid);
> + if (ret < 0)
> + goto out;
> +
> + uuid_unparse(fsid, fsid_str);
> + sprintf(filename, "devinfo/%d/allocation_hint", devid);
> +
> + /* build /sys/fs/btrfs/<UUID>/devinfo/<DEVID>/type */
> + ret = path_cat3_out(sysfs_file, "/sys/fs/btrfs", fsid_str, filename);
> + if (ret < 0)
> + goto out;
> +
> + fd2 = open(sysfs_file, O_RDONLY);
> + if (fd2 < 0) {
> + error("'allocation_hint' property not available or accessible.");
> + ret = -errno;
> + goto out;
> + }
> +
> + ret = read(fd2, buf, sizeof(buf) - 1);
> + close(fd2);
> + if (ret < 0) {
> + error("Unable to read the 'allocation_hint' property.");
> + ret = -errno;
> + goto out;
> + }
> +
> + buf[sizeof(buf) - 1] = 0;
> + devtype = strtoull(buf, NULL, 0);
> +
> + if (!value) {
> + /* READ */
> + for (i = 0 ; allocation_hint_description[i].descr ; i++)
> + if (devtype == 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=unknown:%llu\n",
> + devid, object,
> + devtype);
> + ret = 0;
> + } else {
> + /* WRITE */
> + 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;
> + }
> + if (v & ~BTRFS_DEV_ALLOCATION_HINT_MASK) {
> + error("Invalid value '%s'\n", value);
> + ret = -3;
> + goto out;
> + }
> +
> + devtype &= ~BTRFS_DEV_ALLOCATION_HINT_MASK;
> + devtype |= (v & BTRFS_DEV_ALLOCATION_HINT_MASK);
> +
> + 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", devtype);
> +
> + ret = write(fd2, buf, strlen(buf));
> + close(fd2);
> + if (ret < 0) {
> + error("Unable to update 'allocation_hint' property.");
> + ret = -errno;
> + goto out;
> + }
> +
> + }
> +
> + ret = 0;
> +out:
> + close_file_or_dir(fd, dir);
> + return ret;
> +}
> +
> const struct prop_handler prop_handlers[] = {
> {
> .name ="ro",
> @@ -254,6 +452,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 966490d3..adc869fe 100644
> --- a/kernel-shared/ctree.h
> +++ b/kernel-shared/ctree.h
> @@ -213,6 +213,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_PREFERRED_METADATA (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_PREFERRED_DATA (0ULL)
> +
> #define BTRFS_UUID_SIZE 16
> struct btrfs_dev_item {
> /* the internal btrfs device id */
> --
> 2.34.1
>
next prev parent reply other threads:[~2022-01-05 2:29 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-17 18:47 [PATCH 0/2][V9] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
2021-12-17 18:47 ` [PATCH 1/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli
2022-01-05 2:29 ` Boris Burkov [this message]
2022-01-05 9:19 ` Goffredo Baroncelli
2021-12-17 18:47 ` [PATCH 2/2] Update man page for allocator_hint property Goffredo Baroncelli
2021-12-17 18:53 ` Script to test allocation_hint - [Was Re: [PATCH 0/2][V9] btrfs-progs: allocation_hint disk property] Goffredo Baroncelli
2021-12-21 5:36 ` Paul Jones
2021-12-21 20:58 ` Goffredo Baroncelli
-- strict thread matches above, loose matches on Subject: below --
2022-03-06 18:15 [PATCH 0/2][V12] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
2022-03-06 18:15 ` [PATCH 1/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli
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-06 17:49 [PATCH 0/2][V10] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
2022-01-06 17:49 ` [PATCH 1/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli
2021-10-24 15:31 [PATCH 0/2][V8] btrfs-progs: allocation_hint disk property Goffredo Baroncelli
2021-10-24 15:31 ` [PATCH 1/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=YdUChLjZz80FS5u4@zen \
--to=boris@bur.io \
--cc=ce3g8jdj@umail.furryterror.org \
--cc=dsterba@suse.cz \
--cc=josef@toxicpanda.com \
--cc=kreijack@inwind.it \
--cc=kreijack@libero.it \
--cc=linux-btrfs@vger.kernel.org \
--cc=shafeeqs@panasas.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.