bcachefs: for_each_btree_key_in_subvolume_upto()
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 17 Jul 2024 16:59:51 +0000 (12:59 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 9 Sep 2024 13:41:48 +0000 (09:41 -0400)
New helper for looping over keys in a given subvolume

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

index a8299ba..e62f876 100644 (file)
@@ -31,6 +31,51 @@ int bch2_subvolume_get_snapshot(struct btree_trans *, u32, u32 *);
 int bch2_subvol_is_ro_trans(struct btree_trans *, u32);
 int bch2_subvol_is_ro(struct bch_fs *, u32);
 
+static inline struct bkey_s_c
+bch2_btree_iter_peek_in_subvolume_upto_type(struct btree_iter *iter, struct bpos end,
+                                           u32 subvolid, unsigned flags)
+{
+       u32 snapshot;
+       int ret = bch2_subvolume_get_snapshot(iter->trans, subvolid, &snapshot);
+       if (ret)
+               return bkey_s_c_err(ret);
+
+       bch2_btree_iter_set_snapshot(iter, snapshot);
+       return bch2_btree_iter_peek_upto_type(iter, end, flags);
+}
+
+#define for_each_btree_key_in_subvolume_upto_continue(_trans, _iter,           \
+                                        _end, _subvolid, _flags, _k, _do)      \
+({                                                                             \
+       struct bkey_s_c _k;                                                     \
+       int _ret3 = 0;                                                          \
+                                                                               \
+       do {                                                                    \
+               _ret3 = lockrestart_do(_trans, ({                               \
+                       (_k) = bch2_btree_iter_peek_in_subvolume_upto_type(&(_iter),    \
+                                               _end, _subvolid, (_flags));     \
+                       if (!(_k).k)                                            \
+                               break;                                          \
+                                                                               \
+                       bkey_err(_k) ?: (_do);                                  \
+               }));                                                            \
+       } while (!_ret3 && bch2_btree_iter_advance(&(_iter)));                  \
+                                                                               \
+       bch2_trans_iter_exit((_trans), &(_iter));                               \
+       _ret3;                                                                  \
+})
+
+#define for_each_btree_key_in_subvolume_upto(_trans, _iter, _btree_id,         \
+                               _start, _end, _subvolid, _flags, _k, _do)       \
+({                                                                             \
+       struct btree_iter _iter;                                                \
+       bch2_trans_iter_init((_trans), &(_iter), (_btree_id),                   \
+                            (_start), (_flags));                               \
+                                                                               \
+       for_each_btree_key_in_subvolume_upto_continue(_trans, _iter,            \
+                                       _end, _subvolid, _flags, _k, _do);      \
+})
+
 int bch2_delete_dead_snapshots(struct bch_fs *);
 void bch2_delete_dead_snapshots_async(struct bch_fs *);