]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/btree_iter.h
Update bcachefs sources to 33a60d9b05 bcachefs: Assorted fixes for clang
[bcachefs-tools-debian] / libbcachefs / btree_iter.h
index 02dd81a1d70416baa5593f75301a2f96d99fad61..c472aa8c58a09b8181aab307cd2ced3508c17545 100644 (file)
@@ -42,14 +42,7 @@ static inline struct btree *btree_path_node(struct btree_path *path,
 static inline bool btree_node_lock_seq_matches(const struct btree_path *path,
                                        const struct btree *b, unsigned level)
 {
-       /*
-        * We don't compare the low bits of the lock sequence numbers because
-        * @path might have taken a write lock on @b, and we don't want to skip
-        * the linked path if the sequence numbers were equal before taking that
-        * write lock. The lock sequence number is incremented by taking and
-        * releasing write locks and is even when unlocked:
-        */
-       return path->l[level].lock_seq >> 1 == b->c.lock.state.seq >> 1;
+       return path->l[level].lock_seq == six_lock_seq(&b->c.lock);
 }
 
 static inline struct btree *btree_node_parent(struct btree_path *path,
@@ -96,6 +89,35 @@ __trans_next_path(struct btree_trans *trans, unsigned idx)
 #define trans_for_each_path(_trans, _path)                             \
        trans_for_each_path_from(_trans, _path, 0)
 
+static inline struct btree_path *
+__trans_next_path_safe(struct btree_trans *trans, unsigned *idx)
+{
+       u64 l;
+
+       if (*idx == BTREE_ITER_MAX)
+               return NULL;
+
+       l = trans->paths_allocated >> *idx;
+       if (!l)
+               return NULL;
+
+       *idx += __ffs64(l);
+       EBUG_ON(*idx >= BTREE_ITER_MAX);
+       return &trans->paths[*idx];
+}
+
+/*
+ * This version is intended to be safe for use on a btree_trans that is owned by
+ * another thread, for bch2_btree_trans_to_text();
+ */
+#define trans_for_each_path_safe_from(_trans, _path, _idx, _start)     \
+       for (_idx = _start;                                             \
+            (_path = __trans_next_path_safe((_trans), &_idx));         \
+            _idx++)
+
+#define trans_for_each_path_safe(_trans, _path, _idx)                  \
+       trans_for_each_path_safe_from(_trans, _path, _idx, 0)
+
 static inline struct btree_path *next_btree_path(struct btree_trans *trans, struct btree_path *path)
 {
        unsigned idx = path ? path->sorted_idx + 1 : 0;
@@ -261,10 +283,10 @@ static inline void bch2_trans_verify_not_in_restart(struct btree_trans *trans)
 }
 
 __always_inline
-static inline int btree_trans_restart_nounlock(struct btree_trans *trans, int err)
+static int btree_trans_restart_nounlock(struct btree_trans *trans, int err)
 {
        BUG_ON(err <= 0);
-       BUG_ON(!bch2_err_matches(err, BCH_ERR_transaction_restart));
+       BUG_ON(!bch2_err_matches(-err, BCH_ERR_transaction_restart));
 
        trans->restarted = err;
        trans->last_restarted_ip = _THIS_IP_;
@@ -272,7 +294,7 @@ static inline int btree_trans_restart_nounlock(struct btree_trans *trans, int er
 }
 
 __always_inline
-static inline int btree_trans_restart(struct btree_trans *trans, int err)
+static int btree_trans_restart(struct btree_trans *trans, int err)
 {
        btree_trans_restart_nounlock(trans, err);
        return -err;
@@ -494,7 +516,7 @@ static inline struct bkey_s_c __bch2_bkey_get_iter(struct btree_trans *trans,
        k = bch2_btree_iter_peek_slot(iter);
 
        if (!bkey_err(k) && type && k.k->type != type)
-               k = bkey_s_c_err(-ENOENT);
+               k = bkey_s_c_err(-BCH_ERR_ENOENT_bkey_type_mismatch);
        if (unlikely(bkey_err(k)))
                bch2_trans_iter_exit(trans, iter);
        return k;
@@ -773,6 +795,14 @@ __bch2_btree_iter_peek_upto_and_restart(struct btree_trans *trans,
                            (_do) ?: bch2_trans_commit(_trans, (_disk_res),\
                                        (_journal_seq), (_commit_flags)))
 
+#define for_each_btree_key_reverse_commit(_trans, _iter, _btree_id,    \
+                                 _start, _iter_flags, _k,              \
+                                 _disk_res, _journal_seq, _commit_flags,\
+                                 _do)                                  \
+       for_each_btree_key_reverse(_trans, _iter, _btree_id, _start, _iter_flags, _k,\
+                           (_do) ?: bch2_trans_commit(_trans, (_disk_res),\
+                                       (_journal_seq), (_commit_flags)))
+
 #define for_each_btree_key_upto_commit(_trans, _iter, _btree_id,       \
                                  _start, _end, _iter_flags, _k,        \
                                  _disk_res, _journal_seq, _commit_flags,\
@@ -832,6 +862,37 @@ __bch2_btree_iter_peek_upto_and_restart(struct btree_trans *trans,
             !((_ret) = bkey_err(_k)) && (_k).k;                                \
             bch2_btree_iter_advance(&(_iter)))
 
+#define drop_locks_do(_trans, _do)                                     \
+({                                                                     \
+       bch2_trans_unlock(_trans);                                      \
+       _do ?: bch2_trans_relock(_trans);                               \
+})
+
+#define allocate_dropping_locks_errcode(_trans, _do)                   \
+({                                                                     \
+       gfp_t _gfp = GFP_NOWAIT|__GFP_NOWARN;                           \
+       int _ret = _do;                                                 \
+                                                                       \
+       if (bch2_err_matches(_ret, ENOMEM)) {                           \
+               _gfp = GFP_KERNEL;                                      \
+               _ret = drop_locks_do(trans, _do);                       \
+       }                                                               \
+       _ret;                                                           \
+})
+
+#define allocate_dropping_locks(_trans, _ret, _do)                     \
+({                                                                     \
+       gfp_t _gfp = GFP_NOWAIT|__GFP_NOWARN;                           \
+       typeof(_do) _p = _do;                                           \
+                                                                       \
+       _ret = 0;                                                       \
+       if (unlikely(!_p)) {                                            \
+               _gfp = GFP_KERNEL;                                      \
+               _ret = drop_locks_do(trans, ((_p = _do), 0));           \
+       }                                                               \
+       _p;                                                             \
+})
+
 /* new multiple iterator interface: */
 
 void bch2_trans_updates_to_text(struct printbuf *, struct btree_trans *);