]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: bch2_btree_iter_peek_upto()
authorKent Overstreet <kent.overstreet@gmail.com>
Fri, 11 Mar 2022 17:31:52 +0000 (12:31 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:27 +0000 (17:09 -0400)
In BTREE_ITER_FILTER_SNAPHOTS mode, we skip over keys in unrelated
snapshots. When we hit the end of an inode, if the next inode(s) are in
a different subvolume, we could potentially have to skip past many keys
before finding a key we can return to the caller, so they can terminate
the iteration.

This adds a peek_upto() variant to solve this problem, to be used when
we know the range we're searching within.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_iter.h
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/dirent.c
fs/bcachefs/fs.c
fs/bcachefs/inode.c
fs/bcachefs/str_hash.h
fs/bcachefs/xattr.c

index b18e4fcc46e55ccb51c3d5e7621260a723823994..317c8066f3fc4fed62ac18706df1cc2ac758e188 100644 (file)
@@ -2346,11 +2346,12 @@ out:
  * bch2_btree_iter_peek: returns first key greater than or equal to iterator's
  * current position
  */
-struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
+struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *iter, struct bpos end)
 {
        struct btree_trans *trans = iter->trans;
        struct bpos search_key = btree_iter_search_key(iter);
        struct bkey_s_c k;
+       struct bpos iter_pos;
        int ret;
 
        if (iter->update_path) {
@@ -2366,6 +2367,24 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
                if (!k.k || bkey_err(k))
                        goto out;
 
+               /*
+                * iter->pos should be mononotically increasing, and always be
+                * equal to the key we just returned - except extents can
+                * straddle iter->pos:
+                */
+               if (!(iter->flags & BTREE_ITER_IS_EXTENTS))
+                       iter_pos = k.k->p;
+               else if (bkey_cmp(bkey_start_pos(k.k), iter->pos) > 0)
+                       iter_pos = bkey_start_pos(k.k);
+               else
+                       iter_pos = iter->pos;
+
+               if (bkey_cmp(iter_pos, end) > 0) {
+                       bch2_btree_iter_set_pos(iter, end);
+                       k = bkey_s_c_null;
+                       goto out;
+               }
+
                if (iter->update_path &&
                    bkey_cmp(iter->update_path->pos, k.k->p)) {
                        bch2_path_put(trans, iter->update_path,
@@ -2419,14 +2438,7 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
                break;
        }
 
-       /*
-        * iter->pos should be mononotically increasing, and always be equal to
-        * the key we just returned - except extents can straddle iter->pos:
-        */
-       if (!(iter->flags & BTREE_ITER_IS_EXTENTS))
-               iter->pos = k.k->p;
-       else if (bkey_cmp(bkey_start_pos(k.k), iter->pos) > 0)
-               iter->pos = bkey_start_pos(k.k);
+       iter->pos = iter_pos;
 
        iter->path = bch2_btree_path_set_pos(trans, iter->path, k.k->p,
                                iter->flags & BTREE_ITER_INTENT);
@@ -2658,9 +2670,13 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
 
                if (iter->flags & BTREE_ITER_INTENT) {
                        struct btree_iter iter2;
+                       struct bpos end = iter->pos;
+
+                       if (iter->flags & BTREE_ITER_IS_EXTENTS)
+                               end.offset = U64_MAX;
 
                        bch2_trans_copy_iter(&iter2, iter);
-                       k = bch2_btree_iter_peek(&iter2);
+                       k = bch2_btree_iter_peek_upto(&iter2, end);
 
                        if (k.k && !bkey_err(k)) {
                                iter->k = iter2.k;
index 1e3172a2885ae03013524d072a301b85b551db7d..27b3b82f7df35fe289f256bcd5d2f2e133c3f74f 100644 (file)
@@ -245,9 +245,14 @@ int __must_check bch2_btree_iter_traverse(struct btree_iter *);
 struct btree *bch2_btree_iter_peek_node(struct btree_iter *);
 struct btree *bch2_btree_iter_next_node(struct btree_iter *);
 
-struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *);
+struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *, struct bpos);
 struct bkey_s_c bch2_btree_iter_next(struct btree_iter *);
 
+static inline struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
+{
+       return bch2_btree_iter_peek_upto(iter, SPOS_MAX);
+}
+
 struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *);
 struct bkey_s_c bch2_btree_iter_prev(struct btree_iter *);
 
@@ -342,13 +347,26 @@ static inline int bkey_err(struct bkey_s_c k)
 }
 
 static inline struct bkey_s_c bch2_btree_iter_peek_type(struct btree_iter *iter,
-                                                    unsigned flags)
+                                                       unsigned flags)
 {
        return flags & BTREE_ITER_SLOTS
                ? bch2_btree_iter_peek_slot(iter)
                : bch2_btree_iter_peek(iter);
 }
 
+static inline struct bkey_s_c bch2_btree_iter_peek_upto_type(struct btree_iter *iter,
+                                                            struct bpos end,
+                                                            unsigned flags)
+{
+       if (!(flags & BTREE_ITER_SLOTS))
+               return bch2_btree_iter_peek_upto(iter, end);
+
+       if (bkey_cmp(iter->pos, end) > 0)
+               return bkey_s_c_null;
+
+       return bch2_btree_iter_peek_slot(iter);
+}
+
 static inline int btree_trans_too_many_iters(struct btree_trans *trans)
 {
        return hweight64(trans->paths_allocated) > BTREE_ITER_MAX / 2
@@ -385,6 +403,14 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
             !((_ret) = bkey_err(_k)) && (_k).k;                        \
             bch2_btree_iter_advance(&(_iter)))
 
+#define for_each_btree_key_upto_norestart(_trans, _iter, _btree_id,    \
+                          _start, _end, _flags, _k, _ret)              \
+       for (bch2_trans_iter_init((_trans), &(_iter), (_btree_id),      \
+                                 (_start), (_flags));                  \
+            (_k) = bch2_btree_iter_peek_upto_type(&(_iter), _end, _flags),\
+            !((_ret) = bkey_err(_k)) && (_k).k;                        \
+            bch2_btree_iter_advance(&(_iter)))
+
 #define for_each_btree_key_continue(_trans, _iter, _flags, _k, _ret)   \
        for (;                                                          \
             (_k) = __bch2_btree_iter_peek_and_restart((_trans), &(_iter), _flags),\
index 9f1ff5f8635d4e348cf7fc2b147854d91a8a618e..c9cddba0f999ff69f28df5b520ba63ba5dfd8af1 100644 (file)
@@ -1286,7 +1286,7 @@ int bch2_trans_update_extent(struct btree_trans *trans,
                             BTREE_ITER_INTENT|
                             BTREE_ITER_WITH_UPDATES|
                             BTREE_ITER_NOT_EXTENTS);
-       k = bch2_btree_iter_peek(&iter);
+       k = bch2_btree_iter_peek_upto(&iter, POS(insert->k.p.inode, U64_MAX));
        if ((ret = bkey_err(k)))
                goto err;
        if (!k.k)
@@ -1405,7 +1405,8 @@ int bch2_trans_update_extent(struct btree_trans *trans,
                        goto out;
                }
 next:
-               k = bch2_btree_iter_next(&iter);
+               bch2_btree_iter_advance(&iter);
+               k = bch2_btree_iter_peek_upto(&iter, POS(insert->k.p.inode, U64_MAX));
                if ((ret = bkey_err(k)))
                        goto err;
                if (!k.k)
index a43a24409d37d627c8f0214acb87157519717de9..760e4f74715feb62459c41c4a054a4f6dd87aa2c 100644 (file)
@@ -470,16 +470,13 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
        if (ret)
                return ret;
 
-       for_each_btree_key_norestart(trans, iter, BTREE_ID_dirents,
-                          SPOS(dir.inum, 0, snapshot), 0, k, ret) {
-               if (k.k->p.inode > dir.inum)
-                       break;
-
+       for_each_btree_key_upto_norestart(trans, iter, BTREE_ID_dirents,
+                          SPOS(dir.inum, 0, snapshot),
+                          POS(dir.inum, U64_MAX), 0, k, ret)
                if (k.k->type == KEY_TYPE_dirent) {
                        ret = -ENOTEMPTY;
                        break;
                }
-       }
        bch2_trans_iter_exit(trans, &iter);
 
        return ret;
@@ -503,11 +500,9 @@ retry:
        if (ret)
                goto err;
 
-       for_each_btree_key_norestart(&trans, iter, BTREE_ID_dirents,
-                          SPOS(inum.inum, ctx->pos, snapshot), 0, k, ret) {
-               if (k.k->p.inode > inum.inum)
-                       break;
-
+       for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_dirents,
+                          SPOS(inum.inum, ctx->pos, snapshot),
+                          POS(inum.inum, U64_MAX), 0, k, ret) {
                if (k.k->type != KEY_TYPE_dirent)
                        continue;
 
index 4c68cee013e3ee60dc3108755ecb48f1da90baa0..afaee020e7e3009cd1526457cc33d65b047d28c0 100644 (file)
@@ -936,9 +936,8 @@ retry:
                             SPOS(ei->v.i_ino, start, snapshot), 0);
 
        while (!(ret = btree_trans_too_many_iters(&trans)) &&
-              (k = bch2_btree_iter_peek(&iter)).k &&
-              !(ret = bkey_err(k)) &&
-              bkey_cmp(iter.pos, end) < 0) {
+              (k = bch2_btree_iter_peek_upto(&iter, end)).k &&
+              !(ret = bkey_err(k))) {
                enum btree_id data_btree = BTREE_ID_extents;
 
                if (!bkey_extent_is_data(k.k) &&
index ee14ba5ee73d03a6ebd03e9765051ecf9536e1bc..3735397ee9c501227fddc9103e549fc5d7666c6e 100644 (file)
@@ -586,12 +586,12 @@ static int bch2_inode_delete_keys(struct btree_trans *trans,
 
                bch2_btree_iter_set_snapshot(&iter, snapshot);
 
-               k = bch2_btree_iter_peek(&iter);
+               k = bch2_btree_iter_peek_upto(&iter, POS(inum.inum, U64_MAX));
                ret = bkey_err(k);
                if (ret)
                        goto err;
 
-               if (!k.k || iter.pos.inode != inum.inum)
+               if (!k.k)
                        break;
 
                bkey_init(&delete.k);
index 57d636740d2f81ffa8a19adf9dd3d3f036746a65..591bbb9f8beb544de1369204ffc666018ef40740 100644 (file)
@@ -163,12 +163,10 @@ bch2_hash_lookup(struct btree_trans *trans,
        if (ret)
                return ret;
 
-       for_each_btree_key_norestart(trans, *iter, desc.btree_id,
+       for_each_btree_key_upto_norestart(trans, *iter, desc.btree_id,
                           SPOS(inum.inum, desc.hash_key(info, key), snapshot),
+                          POS(inum.inum, U64_MAX),
                           BTREE_ITER_SLOTS|flags, k, ret) {
-               if (iter->pos.inode != inum.inum)
-                       break;
-
                if (is_visible_key(desc, inum, k)) {
                        if (!desc.cmp_key(k, key))
                                return 0;
@@ -199,15 +197,12 @@ bch2_hash_hole(struct btree_trans *trans,
        if (ret)
                return ret;
 
-       for_each_btree_key_norestart(trans, *iter, desc.btree_id,
+       for_each_btree_key_upto_norestart(trans, *iter, desc.btree_id,
                           SPOS(inum.inum, desc.hash_key(info, key), snapshot),
-                          BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
-               if (iter->pos.inode != inum.inum)
-                       break;
-
+                          POS(inum.inum, U64_MAX),
+                          BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret)
                if (!is_visible_key(desc, inum, k))
                        return 0;
-       }
        bch2_trans_iter_exit(trans, iter);
 
        return ret ?: -ENOSPC;
@@ -260,14 +255,12 @@ int bch2_hash_set(struct btree_trans *trans,
        if (ret)
                return ret;
 
-       for_each_btree_key_norestart(trans, iter, desc.btree_id,
+       for_each_btree_key_upto_norestart(trans, iter, desc.btree_id,
                           SPOS(inum.inum,
                                desc.hash_bkey(info, bkey_i_to_s_c(insert)),
                                snapshot),
+                          POS(inum.inum, U64_MAX),
                           BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
-               if (iter.pos.inode != inum.inum)
-                       break;
-
                if (is_visible_key(desc, inum, k)) {
                        if (!desc.cmp_bkey(k, bkey_i_to_s_c(insert)))
                                goto found;
index 08b33ab8489fbb9eb9d050766ee265b62b63e1ea..ecce103421262577e4a2ee626b905eeb49681710 100644 (file)
@@ -311,13 +311,9 @@ retry:
        if (ret)
                goto err;
 
-       for_each_btree_key_norestart(&trans, iter, BTREE_ID_xattrs,
-                          SPOS(inum, offset, snapshot), 0, k, ret) {
-               BUG_ON(k.k->p.inode < inum);
-
-               if (k.k->p.inode > inum)
-                       break;
-
+       for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_xattrs,
+                          SPOS(inum, offset, snapshot),
+                          POS(inum, U64_MAX), 0, k, ret) {
                if (k.k->type != KEY_TYPE_xattr)
                        continue;