]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: btree_and_journal_iter: don't iterate over too many whiteouts when prefetching
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 17 Nov 2024 19:39:46 +0000 (14:39 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:18 +0000 (01:36 -0500)
To help ameloriate issues with peek operations having to skip over
deletions in the journal - just bail out if all we're doing is
prefetching btree nodes.

Since btree node prefetching runs every time we iterate to a new node,
and has to sequentially scan ahead, this avoids another O(n^2).

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_journal_iter.c
fs/bcachefs/btree_journal_iter.h

index ed74f0655d984e2e7a73f8412a75b92d8a1aa16a..89f9665ce70d9419784651fdc438dbac32666ede 100644 (file)
@@ -825,6 +825,8 @@ static int btree_path_prefetch_j(struct btree_trans *trans, struct btree_path *p
 
        bch2_bkey_buf_init(&tmp);
 
+       jiter->fail_if_too_many_whiteouts = true;
+
        while (nr-- && !ret) {
                if (!bch2_btree_node_relock(trans, path, path->level))
                        break;
index dbc9bc233ccaea6565d370013b7b7a1a289050df..cc7f5fad90c6ddd122c375b8a4a81a20e408bd0d 100644 (file)
@@ -426,6 +426,7 @@ static void btree_and_journal_iter_prefetch(struct btree_and_journal_iter *_iter
                : (level > 1 ? 1 : 16);
 
        iter.prefetch = false;
+       iter.fail_if_too_many_whiteouts = true;
        bch2_bkey_buf_init(&tmp);
 
        while (nr--) {
@@ -444,6 +445,7 @@ static void btree_and_journal_iter_prefetch(struct btree_and_journal_iter *_iter
 struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *iter)
 {
        struct bkey_s_c btree_k, journal_k = bkey_s_c_null, ret;
+       size_t iters = 0;
 
        if (iter->prefetch && iter->journal.level)
                btree_and_journal_iter_prefetch(iter);
@@ -451,6 +453,11 @@ again:
        if (iter->at_end)
                return bkey_s_c_null;
 
+       iters++;
+
+       if (iters > 20 && iter->fail_if_too_many_whiteouts)
+               return bkey_s_c_null;
+
        while ((btree_k = bch2_journal_iter_peek_btree(iter)).k &&
               bpos_lt(btree_k.k->p, iter->pos))
                bch2_journal_iter_advance_btree(iter);
index 118ada4cdd1b1b55913b206372fcdc9f57f6835e..9e8f8ab1c6ffe212fc6e32cf9df85c49d27d6acb 100644 (file)
@@ -26,6 +26,7 @@ struct btree_and_journal_iter {
        struct bpos             pos;
        bool                    at_end;
        bool                    prefetch;
+       bool                    fail_if_too_many_whiteouts;
 };
 
 static inline int __journal_key_btree_cmp(enum btree_id        l_btree_id,