summaryrefslogtreecommitdiff
path: root/libbcachefs/btree_io.h
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/btree_io.h')
-rw-r--r--libbcachefs/btree_io.h34
1 files changed, 26 insertions, 8 deletions
diff --git a/libbcachefs/btree_io.h b/libbcachefs/btree_io.h
index c8417ac3..66053d53 100644
--- a/libbcachefs/btree_io.h
+++ b/libbcachefs/btree_io.h
@@ -19,7 +19,6 @@ struct btree_read_bio {
};
struct btree_write_bio {
- struct closure *cl;
void *data;
struct work_struct work;
struct bch_write_bio wbio;
@@ -91,22 +90,41 @@ void bch2_btree_complete_write(struct bch_fs *, struct btree *,
void bch2_btree_write_error_work(struct work_struct *);
void __bch2_btree_node_write(struct bch_fs *, struct btree *,
- struct closure *, enum six_lock_type);
+ enum six_lock_type);
bool bch2_btree_post_write_cleanup(struct bch_fs *, struct btree *);
void bch2_btree_node_write(struct bch_fs *, struct btree *,
- struct closure *, enum six_lock_type);
+ enum six_lock_type);
+
+/*
+ * btree_node_dirty() can be cleared with only a read lock,
+ * and for bch2_btree_node_write_cond() we want to set need_write iff it's
+ * still dirty:
+ */
+static inline void set_btree_node_need_write_if_dirty(struct btree *b)
+{
+ unsigned long old, new, v = READ_ONCE(b->flags);
+
+ do {
+ old = new = v;
-#define bch2_btree_node_write_dirty(_c, _b, _cl, cond) \
+ if (!(old & (1 << BTREE_NODE_dirty)))
+ return;
+
+ new |= (1 << BTREE_NODE_need_write);
+ } while ((v = cmpxchg(&b->flags, old, new)) != old);
+}
+
+#define bch2_btree_node_write_cond(_c, _b, cond) \
do { \
while ((_b)->written && btree_node_dirty(_b) && (cond)) { \
- set_btree_node_need_write(_b); \
- \
- if (!btree_node_may_write(_b)) \
+ if (!btree_node_may_write(_b)) { \
+ set_btree_node_need_write_if_dirty(_b); \
break; \
+ } \
\
if (!btree_node_write_in_flight(_b)) { \
- bch2_btree_node_write(_c, _b, _cl, SIX_LOCK_read);\
+ bch2_btree_node_write(_c, _b, SIX_LOCK_read); \
break; \
} \
\