* [PATCH 0/2][V9] btrfs-progs: allocation_hint disk property
@ 2021-12-17 18:47 Goffredo Baroncelli
2021-12-17 18:47 ` [PATCH 1/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Goffredo Baroncelli @ 2021-12-17 18:47 UTC (permalink / raw)
To: linux-btrfs
Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq,
Goffredo Baroncelli
From: Goffredo Baroncelli <kreijack@inwind.it>
This patches set is the userspace portion of the serie
"[PATCH V9] btrfs: allocation_hint mode".
Look this patches set for further information.
G.Baroncelli
Goffredo Baroncelli (2):
btrfs-progs: new "allocation_hint" property.
Update man page for allocator_hint property.
Documentation/btrfs-property.asciidoc | 17 +++
cmds/property.c | 204 ++++++++++++++++++++++++++
kernel-shared/ctree.h | 13 ++
3 files changed, 234 insertions(+)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 1/2] btrfs-progs: new "allocation_hint" property. 2021-12-17 18:47 [PATCH 0/2][V9] btrfs-progs: allocation_hint disk property Goffredo Baroncelli @ 2021-12-17 18:47 ` Goffredo Baroncelli 2022-01-05 2:29 ` Boris Burkov 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 2 siblings, 1 reply; 8+ messages in thread From: Goffredo Baroncelli @ 2021-12-17 18:47 UTC (permalink / raw) To: linux-btrfs Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq, 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 - 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 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] btrfs-progs: new "allocation_hint" property. 2021-12-17 18:47 ` [PATCH 1/2] btrfs-progs: new "allocation_hint" property Goffredo Baroncelli @ 2022-01-05 2:29 ` Boris Burkov 2022-01-05 9:19 ` Goffredo Baroncelli 0 siblings, 1 reply; 8+ messages in thread From: Boris Burkov @ 2022-01-05 2:29 UTC (permalink / raw) To: Goffredo Baroncelli Cc: linux-btrfs, Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq, Goffredo Baroncelli 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 > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] btrfs-progs: new "allocation_hint" property. 2022-01-05 2:29 ` Boris Burkov @ 2022-01-05 9:19 ` Goffredo Baroncelli 0 siblings, 0 replies; 8+ messages in thread From: Goffredo Baroncelli @ 2022-01-05 9:19 UTC (permalink / raw) To: Boris Burkov Cc: linux-btrfs, Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq, Goffredo Baroncelli On 1/5/22 03:29, Boris Burkov wrote: > 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. It seems that you missed the "failing command". However my guess is that this command fails on the LVM/DM devices, which often are link to the real devices. Further investigation is needed. BR -- gpg @keyserver.linux.it: Goffredo Baroncelli <kreijackATinwind.it> Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] Update man page for allocator_hint property. 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 @ 2021-12-17 18:47 ` 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 2 siblings, 0 replies; 8+ messages in thread From: Goffredo Baroncelli @ 2021-12-17 18:47 UTC (permalink / raw) To: linux-btrfs Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq, 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.asciidoc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/btrfs-property.asciidoc b/Documentation/btrfs-property.asciidoc index b32d000e..d9e9c4b9 100644 --- a/Documentation/btrfs-property.asciidoc +++ b/Documentation/btrfs-property.asciidoc @@ -49,6 +49,23 @@ device as object. For a mounted filesystem, specify a mount point. 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: +- 'PREFERRED_METADATA': 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. +- 'PREFERRED_DATA' (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 'PREFERRED_DATA'; 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] 8+ messages in thread
* Script to test allocation_hint - [Was Re: [PATCH 0/2][V9] btrfs-progs: allocation_hint disk property] 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 2021-12-17 18:47 ` [PATCH 2/2] Update man page for allocator_hint property Goffredo Baroncelli @ 2021-12-17 18:53 ` Goffredo Baroncelli 2021-12-21 5:36 ` Paul Jones 2 siblings, 1 reply; 8+ messages in thread From: Goffredo Baroncelli @ 2021-12-17 18:53 UTC (permalink / raw) To: linux-btrfs Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq On 12/17/21 19:47, Goffredo Baroncelli wrote: > From: Goffredo Baroncelli <kreijack@inwind.it> > > This patches set is the userspace portion of the serie > "[PATCH V9] btrfs: allocation_hint mode". > > Look this patches set for further information. > > G.Baroncelli > > Goffredo Baroncelli (2): > btrfs-progs: new "allocation_hint" property. > Update man page for allocator_hint property. > > Documentation/btrfs-property.asciidoc | 17 +++ > cmds/property.c | 204 ++++++++++++++++++++++++++ > kernel-shared/ctree.h | 13 ++ > 3 files changed, 234 insertions(+) > Below the script that I used to stress this patch. As is is not integrable in xfstest, but for now is better than nothing :-) ----------- #!/bin/bash #size of disk, smaller -> faster MAXSIZE=$((1*1024*1024*1024)) MNT=mnt BTRFS=./btrfs-hint UUID=292afefb-6e8c-4fb3-9d12-8c4ecb1f237c cleanup_all() { umount $MNT losetup -D } raise() { echo 1>&2 "$@" exit 100 } xmount() { #mount -o allocation_hint=1 "$1" "$2" mount "$1" "$2" } create_loops() { [ -n "$1" ] || { cleanup_all raise "Create_loops, missing an argument" } ret="" for i in $(seq "$1"); do disk=disk-$i.img rm -rf $disk truncate -s ${MAXSIZE} $disk losetup /dev/loop$i $disk ret="$ret /dev/loop$i" done echo "$ret" } fill_1_file() { fn=$MNT/giant-file-$1 if [ -n "$2" ]; then size=count=$(($2 / 16 / 1024 / 1024 )) else size= fi dd if=/dev/zero of=$fn bs=16M oflag=direct $size ls -l $fn | awk '{ print $5 }' } dump_bg_data() { $BTRFS fi us -b $MNT | awk ' /^$/ { flag=0 } { if(flag) print $0 } /^Data/ { flag=1 } ' } dump_bg_metadata() { $BTRFS fi us -b $MNT | awk ' /^$/ { flag=0 } { if(flag) print $0 } /^Metadata/ { flag=1 } ' } test_default_raid1() { loops=$(create_loops 4) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') loop2=$(echo $loops | awk '{ print $3 }') loop3=$(echo $loops | awk '{ print $4 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -draid1 -mraid1 $loops xmount $loop0 $MNT size=$(fill_1_file x $(($MAXSIZE / 2)) ) res=$(dump_bg_data) echo $res | egrep $loop0 || raise "Data BG should contains $loop0" echo $res | egrep $loop1 || raise "Data BG should contains $loop1" echo $res | egrep $loop2 || raise "Data BG should contains $loop2" echo $res | egrep $loop3 || raise "Data BG should contains $loop3" size1=$(fill_1_file y ) size=$(($size + $size1)) [ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] || raise "File too small: check mnt/" [ $size -lt $(($MAXSIZE * 2 * 3 / 2 )) ] || raise "File too big: check mnt/" cleanup_all } test_default_single() { loops=$(create_loops 2) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -dsingle -msingle $loops xmount $loop0 $MNT size=$(fill_1_file x $(($MAXSIZE / 2)) ) res=$(dump_bg_data) echo $res | egrep $loop0 || raise "Data BG should contains $loop0" echo $res | egrep $loop1 || raise "Data BG should contains $loop1" size1=$(fill_1_file y ) size=$(($size + $size1)) [ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] || raise "File too small: check mnt/" [ $size -lt $(($MAXSIZE * 2 * 3 / 2 )) ] || raise "File too big: check mnt/" cleanup_all } test_single_preferred_data() { loops=$(create_loops 2) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -dsingle -msingle $loops xmount $loop0 $MNT $BTRFS prop set $loop0 allocation_hint PREFERRED_METADATA $BTRFS prop set $loop1 allocation_hint PREFERRED_DATA $BTRFS balance start --full-balance $MNT size=$(fill_1_file x $(($MAXSIZE / 2)) ) res=$(dump_bg_data) echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0" echo $res | egrep $loop1 &>/dev/null || raise "Data BG should contains $loop3" cleanup_all } test_single_preferred_metadata() { loops=$(create_loops 2) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -dsingle -msingle $loops xmount $loop0 $MNT $BTRFS prop set $loop0 allocation_hint PREFERRED_METADATA $BTRFS prop set $loop1 allocation_hint PREFERRED_DATA $BTRFS balance start --full-balance $MNT fnsize=2048 for i in $(seq $(( $MAXSIZE / $fnsize * 700 / 1000))); do dd if=/dev/zero of=$MNT/fn-$i bs=$fnsize count=1 done #BTRFS fi us $MNT res=$(dump_bg_metadata) echo $res | egrep $loop0 &>/dev/null || raise "Metadata BG should contains $loop0" echo $res | egrep $loop1 &>/dev/null && raise "Metadata BG should contains $loop3" cleanup_all } test_raid1_preferred_data() { loops=$(create_loops 4) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') loop2=$(echo $loops | awk '{ print $3 }') loop3=$(echo $loops | awk '{ print $4 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -draid1 -mraid1 $loops xmount $loop0 $MNT $BTRFS prop set $loop0 allocation_hint PREFERRED_METADATA $BTRFS prop set $loop1 allocation_hint PREFERRED_METADATA $BTRFS prop set $loop2 allocation_hint PREFERRED_DATA $BTRFS prop set $loop3 allocation_hint PREFERRED_DATA $BTRFS balance start --full-balance $MNT size=$(fill_1_file x $(($MAXSIZE / 2)) ) res=$(dump_bg_data) echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0" echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not contains $loop1" echo $res | egrep $loop2 &>/dev/null || raise "Data BG should contains $loop2" echo $res | egrep $loop3 &>/dev/null || raise "Data BG should contains $loop3" cleanup_all } test_raid1_preferred_metadata() { loops=$(create_loops 4) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') loop2=$(echo $loops | awk '{ print $3 }') loop3=$(echo $loops | awk '{ print $4 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -draid1 -mraid1 $loops xmount $loop0 $MNT $BTRFS prop set $loop0 allocation_hint PREFERRED_METADATA $BTRFS prop set $loop1 allocation_hint PREFERRED_METADATA $BTRFS prop set $loop2 allocation_hint PREFERRED_DATA $BTRFS prop set $loop3 allocation_hint PREFERRED_DATA $BTRFS balance start --full-balance $MNT fnsize=2048 for i in $(seq $(( $MAXSIZE / $fnsize * 700 / 1000))); do dd if=/dev/zero of=$MNT/fn-$i bs=$fnsize count=1 done #BTRFS fi us $MNT res=$(dump_bg_metadata) echo $res | egrep $loop0 &>/dev/null || raise "Metadata BG should contains $loop0" echo $res | egrep $loop1 &>/dev/null || raise "Metadata BG should contains $loop1" echo $res | egrep $loop2 &>/dev/null && raise "Metadata BG should contains $loop2" echo $res | egrep $loop3 &>/dev/null && raise "Metadata BG should contains $loop3" cleanup_all } test_raid1_data_only() { loops=$(create_loops 4) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') loop2=$(echo $loops | awk '{ print $3 }') loop3=$(echo $loops | awk '{ print $4 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -draid1 -mraid1 $loops xmount $loop0 $MNT $BTRFS prop set $loop0 allocation_hint METADATA_ONLY $BTRFS prop set $loop1 allocation_hint METADATA_ONLY $BTRFS prop set $loop2 allocation_hint DATA_ONLY $BTRFS prop set $loop3 allocation_hint DATA_ONLY $BTRFS balance start --full-balance $MNT size=$(fill_1_file x ) [ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] && raise "File too big: check mnt/" [ $size -lt $(($MAXSIZE * 2 / 3 )) ] && raise "File too small: check mnt/" res=$(dump_bg_data) echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0" echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not contains $loop1" echo $res | egrep $loop2 &>/dev/null || raise "Data BG should contains $loop2" echo $res | egrep $loop3 &>/dev/null || raise "Data BG should contains $loop3" cleanup_all } test_single_data_only() { loops=$(create_loops 2) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -dsingle -msingle $loops xmount $loop0 $MNT $BTRFS prop set $loop0 allocation_hint METADATA_ONLY $BTRFS prop set $loop1 allocation_hint DATA_ONLY $BTRFS balance start --full-balance $MNT size=$(fill_1_file x ) [ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] && raise "File too big: check mnt/" [ $size -lt $(($MAXSIZE * 2 / 3 )) ] && raise "File too small: check mnt/" res=$(dump_bg_data) echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0" echo $res | egrep $loop1 &>/dev/null || raise "Data BG should contains $loop3" cleanup_all } test_single_data_bouncing() { loops=$(create_loops 2) loop0=$(echo $loops | awk '{ print $1 }') loop1=$(echo $loops | awk '{ print $2 }') $BTRFS dev scan -u mkfs.btrfs -U $UUID -dsingle -msingle $loops xmount $loop0 $MNT $BTRFS prop set $loop0 allocation_hint METADATA_ONLY $BTRFS prop set $loop1 allocation_hint DATA_ONLY $BTRFS balance start --full-balance $MNT size=$(fill_1_file x $(($MAXSIZE * 2 / 4 ))) [ $size -gt $(($MAXSIZE * 2 / 3 )) ] && raise "File too big: check mnt/" [ $size -lt $(($MAXSIZE * 1 / 3 )) ] && raise "File too small: check mnt/" res=$(dump_bg_data) echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0" echo $res | egrep $loop1 &>/dev/null || raise "Data BG should contains $loop1" $BTRFS balance start --full-balance $MNT res=$(dump_bg_data) echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not contains $loop0" echo $res | egrep $loop1 &>/dev/null || raise "Data BG should contains $loop1" $BTRFS prop set $loop1 allocation_hint METADATA_ONLY $BTRFS prop set $loop0 allocation_hint DATA_ONLY $BTRFS balance start --full-balance $MNT res=$(dump_bg_data) echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not contains $loop1" echo $res | egrep $loop0 &>/dev/null || raise "Data BG should contains $loop0" cleanup_all } if [ "$1" = "cleanup" ]; then cleanup_all exit elif [ "$1" = "makeraid1" ]; then loops=$(create_loops 4) loop0=$(echo $loops | awk '{ print $1 }') mkfs.btrfs -U $UUID -draid1 -mraid1 $loops xmount $loop0 $MNT exit fi cleanup_all &>/dev/null cleanup_all &>/dev/null SETV="" SETX="" while true; do if [ "$1" = "-x" ]; then SETX="set -x" shift elif [ "$1" = "-v" ]; then SETV="-v" shift elif [ "$1" = "--list" ]; then declare -F | awk '{ print $3 }' | egrep ^test_ | sort exit else break fi done ARG="$1" $SETX [ -z "$ARG" ] && ARG="." declare -F | awk '{ print $3 }' | egrep ^test_ | sort | egrep $SETV "$ARG" | while read func; do echo -n "TEST '$func' " ( $SETX $func >.out.log 2>.err.log )|| raise "Error !!!; read .out.log, .err.log" echo "OK" done ----------- -- gpg @keyserver.linux.it: Goffredo Baroncelli <kreijackATinwind.it> Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: Script to test allocation_hint - [Was Re: [PATCH 0/2][V9] btrfs-progs: allocation_hint disk property] 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 0 siblings, 1 reply; 8+ messages in thread From: Paul Jones @ 2021-12-21 5:36 UTC (permalink / raw) To: kreijack@inwind.it, linux-btrfs@vger.kernel.org Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq > -----Original Message----- > From: Goffredo Baroncelli <kreijack@libero.it> > Sent: Saturday, 18 December 2021 5:53 AM > To: linux-btrfs@vger.kernel.org > Cc: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>; Josef Bacik > <josef@toxicpanda.com>; David Sterba <dsterba@suse.cz>; Sinnamohideen > Shafeeq <shafeeqs@panasas.com> > Subject: Script to test allocation_hint - [Was Re: [PATCH 0/2][V9] btrfs-progs: > allocation_hint disk property] > > On 12/17/21 19:47, Goffredo Baroncelli wrote: > > From: Goffredo Baroncelli <kreijack@inwind.it> > > > > This patches set is the userspace portion of the serie "[PATCH V9] > > btrfs: allocation_hint mode". > > > > Look this patches set for further information. > > > > G.Baroncelli > > > > Goffredo Baroncelli (2): > > btrfs-progs: new "allocation_hint" property. > > Update man page for allocator_hint property. > > > > Documentation/btrfs-property.asciidoc | 17 +++ > > cmds/property.c | 204 ++++++++++++++++++++++++++ > > kernel-shared/ctree.h | 13 ++ > > 3 files changed, 234 insertions(+) > > > > > Below the script that I used to stress this patch. As is is not integrable in > xfstest, but for now is better than nothing :-) FYI something has broken in 5.15 - Only the first device in a raid set gets allocation_hint set server /media/storage/peejay/linux/btrfs-progs # cat .err.log dd: error writing 'mnt/giant-file-x': No space left on device 110+0 records in 109+0 records out 1828716544 bytes (1.8 GB, 1.7 GiB) copied, 4.4846 s, 408 MB/s File too big: check mnt/ server /media/storage/peejay/linux/btrfs-progs # ./btrfs-hint prop get /dev/loop1 label= devid=1, path=/dev/loop1: allocation_hint=METADATA_ONLY server /media/storage/peejay/linux/btrfs-progs # ./btrfs-hint prop get /dev/loop2 label= server /media/storage/peejay/linux/btrfs-progs # ./btrfs-hint prop get /dev/loop3 label= server /media/storage/peejay/linux/btrfs-progs # ./btrfs-hint prop get /dev/loop4 label= > > ----------- > #!/bin/bash > > #size of disk, smaller -> faster > MAXSIZE=$((1*1024*1024*1024)) > MNT=mnt > BTRFS=./btrfs-hint > UUID=292afefb-6e8c-4fb3-9d12-8c4ecb1f237c > > cleanup_all() { > umount $MNT > losetup -D > } > > raise() { > echo 1>&2 "$@" > exit 100 > } > > xmount() { > #mount -o allocation_hint=1 "$1" "$2" > mount "$1" "$2" > } > > create_loops() { > [ -n "$1" ] || { > cleanup_all > raise "Create_loops, missing an argument" > } > ret="" > for i in $(seq "$1"); do > disk=disk-$i.img > rm -rf $disk > truncate -s ${MAXSIZE} $disk > losetup /dev/loop$i $disk > ret="$ret /dev/loop$i" > done > > echo "$ret" > } > > > fill_1_file() { > fn=$MNT/giant-file-$1 > if [ -n "$2" ]; then > size=count=$(($2 / 16 / 1024 / 1024 )) > else > size= > fi > dd if=/dev/zero of=$fn bs=16M oflag=direct $size > ls -l $fn | awk '{ print $5 }' > } > > dump_bg_data() { > $BTRFS fi us -b $MNT | awk ' > /^$/ { flag=0 } > { if(flag) print $0 } > /^Data/ { flag=1 } > ' > } > > dump_bg_metadata() { > $BTRFS fi us -b $MNT | awk ' > /^$/ { flag=0 } > { if(flag) print $0 } > /^Metadata/ { flag=1 } > ' > } > > test_default_raid1() { > loops=$(create_loops 4) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > loop2=$(echo $loops | awk '{ print $3 }') > loop3=$(echo $loops | awk '{ print $4 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -draid1 -mraid1 $loops > xmount $loop0 $MNT > > size=$(fill_1_file x $(($MAXSIZE / 2)) ) > > res=$(dump_bg_data) > echo $res | egrep $loop0 || raise "Data BG should contains $loop0" > echo $res | egrep $loop1 || raise "Data BG should contains $loop1" > echo $res | egrep $loop2 || raise "Data BG should contains $loop2" > echo $res | egrep $loop3 || raise "Data BG should contains $loop3" > > size1=$(fill_1_file y ) > > size=$(($size + $size1)) > > [ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] || raise "File too small: check > mnt/" > [ $size -lt $(($MAXSIZE * 2 * 3 / 2 )) ] || raise "File too big: check > mnt/" > > cleanup_all > } > > test_default_single() { > loops=$(create_loops 2) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -dsingle -msingle $loops > xmount $loop0 $MNT > > size=$(fill_1_file x $(($MAXSIZE / 2)) ) > > res=$(dump_bg_data) > echo $res | egrep $loop0 || raise "Data BG should contains $loop0" > echo $res | egrep $loop1 || raise "Data BG should contains $loop1" > > size1=$(fill_1_file y ) > > size=$(($size + $size1)) > > [ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] || raise "File too small: check > mnt/" > [ $size -lt $(($MAXSIZE * 2 * 3 / 2 )) ] || raise "File too big: check > mnt/" > > cleanup_all > } > > test_single_preferred_data() { > loops=$(create_loops 2) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -dsingle -msingle $loops > xmount $loop0 $MNT > > $BTRFS prop set $loop0 allocation_hint PREFERRED_METADATA > $BTRFS prop set $loop1 allocation_hint PREFERRED_DATA > > $BTRFS balance start --full-balance $MNT > > size=$(fill_1_file x $(($MAXSIZE / 2)) ) > > res=$(dump_bg_data) > echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not > contains $loop0" > echo $res | egrep $loop1 &>/dev/null || raise "Data BG should > contains $loop3" > > cleanup_all > } > > test_single_preferred_metadata() { > loops=$(create_loops 2) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -dsingle -msingle $loops > xmount $loop0 $MNT > > $BTRFS prop set $loop0 allocation_hint PREFERRED_METADATA > $BTRFS prop set $loop1 allocation_hint PREFERRED_DATA > > $BTRFS balance start --full-balance $MNT > > fnsize=2048 > for i in $(seq $(( $MAXSIZE / $fnsize * 700 / 1000))); do > dd if=/dev/zero of=$MNT/fn-$i bs=$fnsize count=1 > done > > #BTRFS fi us $MNT > > res=$(dump_bg_metadata) > echo $res | egrep $loop0 &>/dev/null || raise "Metadata BG should > contains $loop0" > echo $res | egrep $loop1 &>/dev/null && raise "Metadata BG should > contains $loop3" > > cleanup_all > } > > > > test_raid1_preferred_data() { > loops=$(create_loops 4) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > loop2=$(echo $loops | awk '{ print $3 }') > loop3=$(echo $loops | awk '{ print $4 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -draid1 -mraid1 $loops > xmount $loop0 $MNT > > $BTRFS prop set $loop0 allocation_hint PREFERRED_METADATA > $BTRFS prop set $loop1 allocation_hint PREFERRED_METADATA > $BTRFS prop set $loop2 allocation_hint PREFERRED_DATA > $BTRFS prop set $loop3 allocation_hint PREFERRED_DATA > > $BTRFS balance start --full-balance $MNT > > size=$(fill_1_file x $(($MAXSIZE / 2)) ) > > res=$(dump_bg_data) > echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not > contains $loop0" > echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not > contains $loop1" > echo $res | egrep $loop2 &>/dev/null || raise "Data BG should > contains $loop2" > echo $res | egrep $loop3 &>/dev/null || raise "Data BG should > contains $loop3" > > cleanup_all > } > > test_raid1_preferred_metadata() { > loops=$(create_loops 4) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > loop2=$(echo $loops | awk '{ print $3 }') > loop3=$(echo $loops | awk '{ print $4 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -draid1 -mraid1 $loops > xmount $loop0 $MNT > > $BTRFS prop set $loop0 allocation_hint PREFERRED_METADATA > $BTRFS prop set $loop1 allocation_hint PREFERRED_METADATA > $BTRFS prop set $loop2 allocation_hint PREFERRED_DATA > $BTRFS prop set $loop3 allocation_hint PREFERRED_DATA > > $BTRFS balance start --full-balance $MNT > > fnsize=2048 > for i in $(seq $(( $MAXSIZE / $fnsize * 700 / 1000))); do > dd if=/dev/zero of=$MNT/fn-$i bs=$fnsize count=1 > done > > #BTRFS fi us $MNT > > res=$(dump_bg_metadata) > echo $res | egrep $loop0 &>/dev/null || raise "Metadata BG should > contains $loop0" > echo $res | egrep $loop1 &>/dev/null || raise "Metadata BG should > contains $loop1" > echo $res | egrep $loop2 &>/dev/null && raise "Metadata BG should > contains $loop2" > echo $res | egrep $loop3 &>/dev/null && raise "Metadata BG should > contains $loop3" > > cleanup_all > } > > test_raid1_data_only() { > loops=$(create_loops 4) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > loop2=$(echo $loops | awk '{ print $3 }') > loop3=$(echo $loops | awk '{ print $4 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -draid1 -mraid1 $loops > xmount $loop0 $MNT > > $BTRFS prop set $loop0 allocation_hint METADATA_ONLY > $BTRFS prop set $loop1 allocation_hint METADATA_ONLY > $BTRFS prop set $loop2 allocation_hint DATA_ONLY > $BTRFS prop set $loop3 allocation_hint DATA_ONLY > > $BTRFS balance start --full-balance $MNT > > size=$(fill_1_file x ) > > [ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] && raise "File too big: check > mnt/" > [ $size -lt $(($MAXSIZE * 2 / 3 )) ] && raise "File too small: check mnt/" > > res=$(dump_bg_data) > echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not > contains $loop0" > echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not > contains $loop1" > echo $res | egrep $loop2 &>/dev/null || raise "Data BG should > contains $loop2" > echo $res | egrep $loop3 &>/dev/null || raise "Data BG should > contains $loop3" > > cleanup_all > } > > test_single_data_only() { > loops=$(create_loops 2) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -dsingle -msingle $loops > xmount $loop0 $MNT > > $BTRFS prop set $loop0 allocation_hint METADATA_ONLY > $BTRFS prop set $loop1 allocation_hint DATA_ONLY > > $BTRFS balance start --full-balance $MNT > > size=$(fill_1_file x ) > > [ $size -gt $(($MAXSIZE * 2 * 2 / 3 )) ] && raise "File too big: check > mnt/" > [ $size -lt $(($MAXSIZE * 2 / 3 )) ] && raise "File too small: check mnt/" > > res=$(dump_bg_data) > echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not > contains $loop0" > echo $res | egrep $loop1 &>/dev/null || raise "Data BG should > contains $loop3" > > cleanup_all > } > > > test_single_data_bouncing() { > loops=$(create_loops 2) > loop0=$(echo $loops | awk '{ print $1 }') > loop1=$(echo $loops | awk '{ print $2 }') > $BTRFS dev scan -u > mkfs.btrfs -U $UUID -dsingle -msingle $loops > xmount $loop0 $MNT > > $BTRFS prop set $loop0 allocation_hint METADATA_ONLY > $BTRFS prop set $loop1 allocation_hint DATA_ONLY > > $BTRFS balance start --full-balance $MNT > > size=$(fill_1_file x $(($MAXSIZE * 2 / 4 ))) > > [ $size -gt $(($MAXSIZE * 2 / 3 )) ] && raise "File too big: check mnt/" > [ $size -lt $(($MAXSIZE * 1 / 3 )) ] && raise "File too small: check mnt/" > > res=$(dump_bg_data) > > echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not > contains $loop0" > echo $res | egrep $loop1 &>/dev/null || raise "Data BG should > contains $loop1" > > $BTRFS balance start --full-balance $MNT > > res=$(dump_bg_data) > > echo $res | egrep $loop0 &>/dev/null && raise "Data BG should not > contains $loop0" > echo $res | egrep $loop1 &>/dev/null || raise "Data BG should > contains $loop1" > > > $BTRFS prop set $loop1 allocation_hint METADATA_ONLY > $BTRFS prop set $loop0 allocation_hint DATA_ONLY > > $BTRFS balance start --full-balance $MNT > > res=$(dump_bg_data) > > echo $res | egrep $loop1 &>/dev/null && raise "Data BG should not > contains $loop1" > echo $res | egrep $loop0 &>/dev/null || raise "Data BG should > contains $loop0" > cleanup_all > } > > > > > > > > > if [ "$1" = "cleanup" ]; then > cleanup_all > > exit > elif [ "$1" = "makeraid1" ]; then > loops=$(create_loops 4) > loop0=$(echo $loops | awk '{ print $1 }') > mkfs.btrfs -U $UUID -draid1 -mraid1 $loops > xmount $loop0 $MNT > > exit > fi > > > cleanup_all &>/dev/null > cleanup_all &>/dev/null > > SETV="" > SETX="" > > while true; do > if [ "$1" = "-x" ]; then > SETX="set -x" > shift > elif [ "$1" = "-v" ]; then > SETV="-v" > shift > elif [ "$1" = "--list" ]; then > declare -F | awk '{ print $3 }' | egrep ^test_ | sort > exit > else > break > fi > done > > ARG="$1" > > $SETX > > > [ -z "$ARG" ] && ARG="." > declare -F | awk '{ print $3 }' | egrep ^test_ | sort | > egrep $SETV "$ARG" | while read func; do > > echo -n "TEST '$func' " > ( > $SETX > $func >.out.log 2>.err.log > )|| raise "Error !!!; read .out.log, .err.log" > echo "OK" > done > > ----------- > > > > -- > gpg @keyserver.linux.it: Goffredo Baroncelli <kreijackATinwind.it> Key > fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Script to test allocation_hint - [Was Re: [PATCH 0/2][V9] btrfs-progs: allocation_hint disk property] 2021-12-21 5:36 ` Paul Jones @ 2021-12-21 20:58 ` Goffredo Baroncelli 0 siblings, 0 replies; 8+ messages in thread From: Goffredo Baroncelli @ 2021-12-21 20:58 UTC (permalink / raw) To: Paul Jones Cc: Zygo Blaxell, Josef Bacik, David Sterba, Sinnamohideen Shafeeq, linux-btrfs@vger.kernel.org On 12/21/21 06:36, Paul Jones wrote: > > FYI something has broken in 5.15 - Only the first device in a raid set gets allocation_hint set > > server /media/storage/peejay/linux/btrfs-progs # cat .err.log > dd: error writing 'mnt/giant-file-x': No space left on device > 110+0 records in > 109+0 records out > 1828716544 bytes (1.8 GB, 1.7 GiB) copied, 4.4846 s, 408 MB/s > File too big: check mnt/ > server /media/storage/peejay/linux/btrfs-progs # ./btrfs-hint prop get /dev/loop1 > label= > devid=1, path=/dev/loop1: allocation_hint=METADATA_ONLY > server /media/storage/peejay/linux/btrfs-progs # ./btrfs-hint prop get /dev/loop2 > label= > server /media/storage/peejay/linux/btrfs-progs # ./btrfs-hint prop get /dev/loop3 > label= > server /media/storage/peejay/linux/btrfs-progs # ./btrfs-hint prop get /dev/loop4 > label= > Yes, I can reproduce it. However the strange if I do # sudo ./btrfs prop get /dev/loop1 allocation_hint devid=2, path=/dev/loop1: allocation_hint=DATA_PREFERRED it works; instead if I do (no property name) # sudo ./btrfs prop get /dev/loop1 label= it doesn't work. My suspect is that the guilty is get_label() and how the "global" internal state of btrfs is not re-entrant. Let me to explain what (I think) happens: if you don't pass a property name to "btrfs get prop", btrfs-progs iterates over all the "get" properties handlers. One of these handlers is the manager of the "label" property. This handler check the kind of object passed. If the object is a device (like this case), it assume that the filesystem is not mounted and call get_label_unmounted (otherwise it calls the get_label_mounted, which in turn ask the label using an ioctl). get_label_unmounted() instead calls open_ctree() (anyway I suspect that this is not a good thing on an mounted filesystem). My *suspect* is that open_ctree()/close_ctree() (called by get_label) and btrfs_scan_devices() (called by the allocation_hint handler) interact badly. In fact if I comment the code of get_label_unmounted(), the bug goes away. In conclusion, yes there is a BUG. The bug is raise when "btrfs get prop <obj>" is called without a specific property. It seems not related to the code of the allocation_hint property, but how the internal state of btrfs is handled in general. But a more deeper analysis is needed. BR -- gpg @keyserver.linux.it: Goffredo Baroncelli <kreijackATinwind.it> Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 -- gpg @keyserver.linux.it: Goffredo Baroncelli <kreijackATinwind.it> Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2022-01-05 9:19 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 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
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.