summaryrefslogtreecommitdiff
path: root/fs/bcachefs/btree_iter.h
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-07-20 23:13:27 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:37 +0300
commit4f84b7e30b3aa72ce5de032380799a1a5ba044fd (patch)
tree49da0fdfc152061e411d9cbe4879912a0e849c28 /fs/bcachefs/btree_iter.h
parent1ed0a5d280ef7a1183b42b2fcc13d919925f1b6e (diff)
downloadlinux-4f84b7e30b3aa72ce5de032380799a1a5ba044fd.tar.xz
bcachefs: for_each_btree_key_reverse()
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>
Diffstat (limited to 'fs/bcachefs/btree_iter.h')
-rw-r--r--fs/bcachefs/btree_iter.h41
1 files changed, 40 insertions, 1 deletions
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index 79339a6abcd7..9a3287da9a12 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -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)); \