diff options
author | David Sterba <dsterba@suse.com> | 2024-03-13 21:25:20 +0100 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2024-03-16 18:08:38 +0100 |
commit | a223764093b1d78403b55787028b8a01fef2f023 (patch) | |
tree | 071231ebb2684e8d06ada7bfec18835d31592425 | |
parent | 4ab1159db08e2e265f337ded0d49db88da93b6b0 (diff) | |
download | btrfs-progs-a223764093b1d78403b55787028b8a01fef2f023.tar.gz |
btrfs-progs: add API for selecting tree search support and ioctl
Add wrappers around v1 and v2 of TREE_SEARCH ioctl so it can be
transparently used by code. The structures partially overlap but due to
the buffer size the v2 is offset and also needs a filler to expand the
flexible buffer.
Usage:
- define struct btrfs_tree_search_args, all zeros
- btrfs_tree_search_sk() reads offset of the search key within the
structures
- btrfs_tree_search_ioctl() detect support and call the highest
supported ioctl version, v2 has been supported since 3.14 but we want
to keep backward compatibility
- btrfs_tree_search_data() read data from the buffer previously filled
by ioctl, a sequence of (search header, data)
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | common/fsfeatures.c | 24 | ||||
-rw-r--r-- | common/tree-search.h | 33 |
2 files changed, 57 insertions, 0 deletions
diff --git a/common/fsfeatures.c b/common/fsfeatures.c index 2ce11327..2c43eae5 100644 --- a/common/fsfeatures.c +++ b/common/fsfeatures.c @@ -31,6 +31,7 @@ #include "common/string-utils.h" #include "common/sysfs-utils.h" #include "common/messages.h" +#include "common/tree-search.h" /* * Insert a root item for temporary tree root @@ -680,6 +681,29 @@ int btrfs_check_features(const struct btrfs_mkfs_features *features, return 0; } +static bool tree_search_v2_supported = false; +static bool tree_search_v2_initialized = false; + +/* + * Call the highest supported TREE_SEARCH ioctl version, autodetect support. + */ +int btrfs_tree_search_ioctl(int fd, struct btrfs_tree_search_args *sa) +{ + /* On first use check the supported status and save it. */ + if (!tree_search_v2_initialized) { + if (btrfs_tree_search2_ioctl_supported(fd) == 1) + tree_search_v2_supported = true; + tree_search_v2_initialized = true; + } + sa->use_v2 = tree_search_v2_supported; + + if (sa->use_v2) { + sa->args2.buf_size = BTRFS_TREE_SEARCH_V2_BUF_SIZE; + return ioctl(fd, BTRFS_IOC_TREE_SEARCH_V2, &sa->args2); + } + return ioctl(fd, BTRFS_IOC_TREE_SEARCH, &sa->args1); +} + /* * Check if the BTRFS_IOC_TREE_SEARCH_V2 ioctl is supported on a given * filesystem, opened at fd diff --git a/common/tree-search.h b/common/tree-search.h new file mode 100644 index 00000000..5a9c917a --- /dev/null +++ b/common/tree-search.h @@ -0,0 +1,33 @@ +#ifndef __COMMON_TREE_SEARCH_H__ +#define __COMMON_TREE_SEARCH_H__ + +#include "kernel-shared/uapi/btrfs_tree.h" +#include "kernel-shared/uapi/btrfs.h" + +#define BTRFS_TREE_SEARCH_V2_BUF_SIZE 65536 + +struct btrfs_tree_search_args { + union { + struct btrfs_ioctl_search_args args1; + struct btrfs_ioctl_search_args_v2 args2; + u8 filler[sizeof(struct btrfs_ioctl_search_args_v2) + + BTRFS_TREE_SEARCH_V2_BUF_SIZE]; + }; + bool use_v2; +}; + +int btrfs_tree_search_ioctl(int fd, struct btrfs_tree_search_args *sa); + +static inline struct btrfs_ioctl_search_key *btrfs_tree_search_sk(struct btrfs_tree_search_args *sa) +{ + /* Same offset for v1 and v2. */ + return &sa->args1.key; +} + +static inline void *btrfs_tree_search_data(struct btrfs_tree_search_args *sa, unsigned long offset) { + if (sa->use_v2) + return (void *)(sa->args2.buf + offset); + return (void *)(sa->args1.buf + offset); +} + +#endif |