aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2024-03-13 21:25:20 +0100
committerDavid Sterba <dsterba@suse.com>2024-03-16 18:08:38 +0100
commita223764093b1d78403b55787028b8a01fef2f023 (patch)
tree071231ebb2684e8d06ada7bfec18835d31592425
parent4ab1159db08e2e265f337ded0d49db88da93b6b0 (diff)
downloadbtrfs-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.c24
-rw-r--r--common/tree-search.h33
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