]> git.hungrycats.org Git - linux/commitdiff
btrfs: introduce BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT to trade latency for accur...
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sun, 22 Mar 2020 20:57:42 +0000 (16:57 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 1 Aug 2020 00:31:53 +0000 (20:31 -0400)
The LOGICAL_INO ioctl is a simple wrapper around an internal btrfs kernel
function which iterates over references to a data extent.  This function
can operate in two modes:

#1 joins the current transaction to get up to date information
on uncommitted references.  LOGICAL_INO can run for a long
time--seconds to minutes on deduped filesystems--and all that
time gets added to the latency of transaction commits. This slows
down other threads writing to the filesystem, as well as reducing
concurrency in LOGICAL_INO itself.

#2 doesn't join a transaction, and just searches commit roots
instead.  This loses access to backref data from uncommitted
references, but doesn't add latency to all other users of the
filesystem while it runs.

Userspace has no mechanism to prevent concurrent changes on the
filesystem, so userspace must tolerate out-of-date backref information
e.g.  looping removing extent refs until LOGICAL_INO gives no more
reachable references.  With a switch from the #1 mode to the #2 mode,
userspace must ensure a commit occurs between loops, either by calling
fssync itself, or by finding something else to do between loop iterations
until a commit occurs naturally.

This is a change in behavior, so we don't do it by default.  Add a new
flag SEARCH_COMMIT_ROOT for LOGICAL_INO_V2 so that users can request
the faster, lower-latency version.

Signed-off-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
(cherry picked from commit f35030f24f09ae428a3c069151ee8aaac5d5d041)
(cherry picked from commit 32c0c08a2c7cb65131c2679add5a302eb24c01f2)
(cherry picked from commit d753020b163b1b2ccba6fc39009a11e2c13633e4)
(cherry picked from commit 6c8b74540686d3096f8f0a85749eb71ae0c5e629)

v2: fixed logic to verify that all flags are supported.
(cherry picked from commit 403cd2651289de590d098dce433671eecc092cad)

fs/btrfs/ioctl.c
include/uapi/linux/btrfs.h

index 4f4b13830b258cbb7f860e9e9d3dd68035c4c810..206325960f5faf039e641818e853af929702f6c6 100644 (file)
@@ -4462,7 +4462,8 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
        struct btrfs_ioctl_logical_ino_args *loi;
        struct btrfs_data_container *inodes = NULL;
        struct btrfs_path *path = NULL;
-       bool ignore_offset;
+       bool ignore_offset = false;
+       bool search_commit_root = false;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -4472,20 +4473,27 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
                return PTR_ERR(loi);
 
        if (version == 1) {
-               ignore_offset = false;
                size = min_t(u32, loi->size, SZ_64K);
        } else {
+               u64 flags = loi->flags;
                /* All reserved bits must be 0 for now */
                if (memchr_inv(loi->reserved, 0, sizeof(loi->reserved))) {
                        ret = -EINVAL;
                        goto out_loi;
                }
+               if (flags & BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET) {
+                       ignore_offset = true;
+                       flags &= ~BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET;
+               }
+               if (flags & BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT) {
+                       search_commit_root = true;
+                       flags &= ~BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT;
+               }
                /* Only accept flags we have defined so far */
-               if (loi->flags & ~(BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET)) {
+               if (flags) {
                        ret = -EINVAL;
                        goto out_loi;
                }
-               ignore_offset = loi->flags & BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET;
                size = min_t(u32, loi->size, SZ_16M);
        }
 
@@ -4494,6 +4502,8 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
                ret = -ENOMEM;
                goto out;
        }
+       path->search_commit_root = search_commit_root;
+       path->skip_locking = search_commit_root;
 
        inodes = init_data_container(size);
        if (IS_ERR(inodes)) {
index 7a8bc8b920f52e767bc78c55630fc5001acd7add..ecb734cc61eea4f6791f6c7487930d6529e20a6d 100644 (file)
@@ -634,7 +634,10 @@ struct btrfs_ioctl_logical_ino_args {
 };
 /* Return every ref to the extent, not just those containing logical block.
  * Requires logical == extent bytenr. */
-#define BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET   (1ULL << 0)
+#define BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET           (1ULL << 0)
+/* Search the commit root instead of joining the current transaction.
+ * Avoids transaction commit latency, but results may be out of date. */
+#define BTRFS_LOGICAL_INO_ARGS_SEARCH_COMMIT_ROOT      (1ULL << 1)
 
 enum btrfs_dev_stat_values {
        /* disk I/O failure stats */