diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2022-11-17 16:03:15 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:46 -0400 |
commit | 42af0ad569edbfcd252e9abf0badd97b895c34be (patch) | |
tree | ae24fa72c52e7f8ed6797a98cae59fdae556f543 | |
parent | 7fec8266af12b655e98978050e716e12e8544fe6 (diff) | |
download | lwn-42af0ad569edbfcd252e9abf0badd97b895c34be.tar.gz lwn-42af0ad569edbfcd252e9abf0badd97b895c34be.zip |
bcachefs: Fix a race with b->write_type
b->write_type needs to be set atomically with setting the
btree_node_need_write flag, so move it into b->flags.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/bcachefs.h | 17 | ||||
-rw-r--r-- | fs/bcachefs/btree_cache.c | 1 | ||||
-rw-r--r-- | fs/bcachefs/btree_io.c | 14 | ||||
-rw-r--r-- | fs/bcachefs/btree_types.h | 20 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 12 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 4 |
6 files changed, 40 insertions, 28 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index c8ab0e2029df..e61dc1e6da06 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -627,23 +627,6 @@ typedef struct { #define BCACHEFS_ROOT_SUBVOL_INUM \ ((subvol_inum) { BCACHEFS_ROOT_SUBVOL, BCACHEFS_ROOT_INO }) -#define BCH_BTREE_WRITE_TYPES() \ - x(initial, 0) \ - x(init_next_bset, 1) \ - x(cache_reclaim, 2) \ - x(journal_reclaim, 3) \ - x(interior, 4) - -enum btree_write_type { -#define x(t, n) BTREE_WRITE_##t, - BCH_BTREE_WRITE_TYPES() -#undef x - BTREE_WRITE_TYPE_NR, -}; - -#define BTREE_WRITE_TYPE_MASK (roundup_pow_of_two(BTREE_WRITE_TYPE_NR) - 1) -#define BTREE_WRITE_TYPE_BITS ilog2(BTREE_WRITE_TYPE_MASK) - struct bch_fs { struct closure cl; diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c index 5adfdc5afbea..c9d287f38d63 100644 --- a/fs/bcachefs/btree_cache.c +++ b/fs/bcachefs/btree_cache.c @@ -631,7 +631,6 @@ out: b->flags = 0; b->written = 0; b->nsets = 0; - b->write_type = 0; b->sib_u64s[0] = 0; b->sib_u64s[1] = 0; b->whiteout_u64s = 0; diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 5d750f447241..8dbe930c1eb2 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -1636,6 +1636,7 @@ static void __btree_node_write_done(struct bch_fs *c, struct btree *b) { struct btree_write *w = btree_prev_write(b); unsigned long old, new, v; + unsigned type = 0; bch2_btree_complete_write(c, b, w); @@ -1654,6 +1655,9 @@ static void __btree_node_write_done(struct bch_fs *c, struct btree *b) new |= (1U << BTREE_NODE_write_in_flight_inner); new |= (1U << BTREE_NODE_just_written); new ^= (1U << BTREE_NODE_write_idx); + + type = new & BTREE_WRITE_TYPE_MASK; + new &= ~BTREE_WRITE_TYPE_MASK; } else { new &= ~(1U << BTREE_NODE_write_in_flight); new &= ~(1U << BTREE_NODE_write_in_flight_inner); @@ -1661,7 +1665,7 @@ static void __btree_node_write_done(struct bch_fs *c, struct btree *b) } while ((v = cmpxchg(&b->flags, old, new)) != old); if (new & (1U << BTREE_NODE_write_in_flight)) - __bch2_btree_node_write(c, b, BTREE_WRITE_ALREADY_STARTED|b->write_type); + __bch2_btree_node_write(c, b, BTREE_WRITE_ALREADY_STARTED|type); else wake_up_bit(&b->flags, BTREE_NODE_write_in_flight); } @@ -1846,6 +1850,10 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, unsigned flags) if (old & (1 << BTREE_NODE_write_in_flight)) return; + if (flags & BTREE_WRITE_ONLY_IF_NEED) + type = new & BTREE_WRITE_TYPE_MASK; + new &= ~BTREE_WRITE_TYPE_MASK; + new &= ~(1 << BTREE_NODE_dirty); new &= ~(1 << BTREE_NODE_need_write); new |= (1 << BTREE_NODE_write_in_flight); @@ -1857,10 +1865,6 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, unsigned flags) if (new & (1U << BTREE_NODE_need_write)) return; do_write: - if ((flags & BTREE_WRITE_ONLY_IF_NEED)) - type = b->write_type; - b->write_type = 0; - BUG_ON((type == BTREE_WRITE_initial) != (b->written == 0)); atomic_dec(&c->btree_cache.dirty); diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index 38c4754dbd7e..72e6a214b89a 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -77,7 +77,6 @@ struct btree { u8 nsets; u8 nr_key_bits; u16 version_ondisk; - u8 write_type; struct bkey_format format; @@ -445,6 +444,23 @@ struct btree_trans { struct replicas_delta_list *fs_usage_deltas; }; +#define BCH_BTREE_WRITE_TYPES() \ + x(initial, 0) \ + x(init_next_bset, 1) \ + x(cache_reclaim, 2) \ + x(journal_reclaim, 3) \ + x(interior, 4) + +enum btree_write_type { +#define x(t, n) BTREE_WRITE_##t, + BCH_BTREE_WRITE_TYPES() +#undef x + BTREE_WRITE_TYPE_NR, +}; + +#define BTREE_WRITE_TYPE_MASK (roundup_pow_of_two(BTREE_WRITE_TYPE_NR) - 1) +#define BTREE_WRITE_TYPE_BITS ilog2(roundup_pow_of_two(BTREE_WRITE_TYPE_NR)) + #define BTREE_FLAGS() \ x(read_in_flight) \ x(read_error) \ @@ -464,6 +480,8 @@ struct btree_trans { x(never_write) enum btree_flags { + /* First bits for btree node write type */ + BTREE_NODE_FLAGS_START = BTREE_WRITE_TYPE_BITS - 1, #define x(flag) BTREE_NODE_##flag, BTREE_FLAGS() #undef x diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index ac3a5ef1b1af..03e016758af3 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1257,6 +1257,7 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as, struct bch_fs *c = as->c; struct bkey_packed *k; struct printbuf buf = PRINTBUF; + unsigned long old, new, v; BUG_ON(insert->k.type == KEY_TYPE_btree_ptr_v2 && !btree_ptr_sectors_written(insert)); @@ -1294,8 +1295,15 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as, bch2_btree_bset_insert_key(trans, path, b, node_iter, insert); set_btree_node_dirty_acct(c, b); - set_btree_node_need_write(b); - b->write_type = BTREE_WRITE_interior; + + v = READ_ONCE(b->flags); + do { + old = new = v; + + new &= ~BTREE_WRITE_TYPE_MASK; + new |= BTREE_WRITE_interior; + new |= 1 << BTREE_NODE_need_write; + } while ((v = cmpxchg(&b->flags, old, new)) != old); printbuf_exit(&buf); } diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 1405ad4eda02..445f8f57ef0c 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -178,11 +178,11 @@ static int __btree_node_flush(struct journal *j, struct journal_entry_pin *pin, w->journal.seq != seq) break; + new &= ~BTREE_WRITE_TYPE_MASK; + new |= BTREE_WRITE_journal_reclaim; new |= 1 << BTREE_NODE_need_write; } while ((v = cmpxchg(&b->flags, old, new)) != old); - b->write_type = BTREE_WRITE_journal_reclaim; - btree_node_write_if_need(c, b, SIX_LOCK_read); six_unlock_read(&b->c.lock); |