]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: for_each_btree_key_reverse()
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 20 Jul 2022 20:13:27 +0000 (16:13 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:37 +0000 (17:09 -0400)
This adds a new macro, like for_each_btree_key2(), but for iterating in
reverse order.

Also, change for_each_btree_key2() to properly check the return value of
bch2_btree_iter_advance().

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/btree_iter.h

index 79339a6abcd764b516eb62b43b9efb451fe74f67..9a3287da9a120ab96823ee4d933248f10d6943ac 100644 (file)
@@ -371,6 +371,15 @@ static inline int bkey_err(struct bkey_s_c k)
        return PTR_ERR_OR_ZERO(k.k);
 }
 
+static inline struct bkey_s_c bch2_btree_iter_peek_prev_type(struct btree_iter *iter,
+                                                            unsigned flags)
+{
+       BUG_ON(flags & BTREE_ITER_ALL_LEVELS);
+
+       return  flags & BTREE_ITER_SLOTS      ? bch2_btree_iter_peek_slot(iter) :
+                                               bch2_btree_iter_peek_prev(iter);
+}
+
 static inline struct bkey_s_c bch2_btree_iter_peek_type(struct btree_iter *iter,
                                                        unsigned flags)
 {
@@ -477,7 +486,37 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
                        continue;                                       \
                if (_ret)                                               \
                        break;                                          \
-               bch2_btree_iter_advance(&(_iter));                      \
+               if (!bch2_btree_iter_advance(&(_iter)))                 \
+                       break;                                          \
+       }                                                               \
+                                                                       \
+       bch2_trans_iter_exit((_trans), &(_iter));                       \
+       _ret;                                                           \
+})
+
+#define for_each_btree_key_reverse(_trans, _iter, _btree_id,           \
+                                  _start, _flags, _k, _do)             \
+({                                                                     \
+       int _ret = 0;                                                   \
+                                                                       \
+       bch2_trans_iter_init((_trans), &(_iter), (_btree_id),           \
+                            (_start), (_flags));                       \
+                                                                       \
+       while (1) {                                                     \
+               bch2_trans_begin(_trans);                               \
+               (_k) = bch2_btree_iter_peek_prev_type(&(_iter), (_flags));\
+               if (!(_k).k) {                                          \
+                       _ret = 0;                                       \
+                       break;                                          \
+               }                                                       \
+                                                                       \
+               _ret = bkey_err(_k) ?: (_do);                           \
+               if (bch2_err_matches(_ret, BCH_ERR_transaction_restart))\
+                       continue;                                       \
+               if (_ret)                                               \
+                       break;                                          \
+               if (!bch2_btree_iter_rewind(&(_iter)))                  \
+                       break;                                          \
        }                                                               \
                                                                        \
        bch2_trans_iter_exit((_trans), &(_iter));                       \