Commit b29e197a authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Invalidate buckets when writing to alloc btree

Prep work for persistent alloc information. Refactoring also lets us
make free_inc much smaller, which means a lot fewer buckets stranded on
freelists.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent b2be7c8b
This diff is collapsed.
...@@ -9,6 +9,8 @@ struct bch_dev; ...@@ -9,6 +9,8 @@ struct bch_dev;
struct bch_fs; struct bch_fs;
struct bch_devs_List; struct bch_devs_List;
#define ALLOC_SCAN_BATCH(ca) ((ca)->mi.nbuckets >> 9)
const char *bch2_alloc_invalid(const struct bch_fs *, struct bkey_s_c); const char *bch2_alloc_invalid(const struct bch_fs *, struct bkey_s_c);
void bch2_alloc_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c); void bch2_alloc_to_text(struct bch_fs *, char *, size_t, struct bkey_s_c);
......
...@@ -270,6 +270,10 @@ do { \ ...@@ -270,6 +270,10 @@ do { \
"Store the journal sequence number in the version " \ "Store the journal sequence number in the version " \
"number of every btree key, and verify that btree " \ "number of every btree key, and verify that btree " \
"update ordering is preserved during recovery") \ "update ordering is preserved during recovery") \
BCH_DEBUG_PARAM(test_alloc_startup, \
"Force allocator startup to use the slowpath where it" \
"can't find enough free buckets without invalidating" \
"cached data")
#define BCH_DEBUG_PARAMS_ALL() BCH_DEBUG_PARAMS_ALWAYS() BCH_DEBUG_PARAMS_DEBUG() #define BCH_DEBUG_PARAMS_ALL() BCH_DEBUG_PARAMS_ALWAYS() BCH_DEBUG_PARAMS_DEBUG()
...@@ -403,7 +407,6 @@ struct bch_dev { ...@@ -403,7 +407,6 @@ struct bch_dev {
alloc_fifo free[RESERVE_NR]; alloc_fifo free[RESERVE_NR];
alloc_fifo free_inc; alloc_fifo free_inc;
spinlock_t freelist_lock; spinlock_t freelist_lock;
size_t nr_invalidated;
u8 open_buckets_partial[OPEN_BUCKETS_COUNT]; u8 open_buckets_partial[OPEN_BUCKETS_COUNT];
unsigned open_buckets_partial_nr; unsigned open_buckets_partial_nr;
...@@ -415,8 +418,6 @@ struct bch_dev { ...@@ -415,8 +418,6 @@ struct bch_dev {
size_t inc_gen_needs_gc; size_t inc_gen_needs_gc;
size_t inc_gen_really_needs_gc; size_t inc_gen_really_needs_gc;
u64 allocator_journal_seq_flush;
bool allocator_invalidating_data;
bool allocator_blocked; bool allocator_blocked;
alloc_heap alloc_heap; alloc_heap alloc_heap;
......
...@@ -1145,7 +1145,8 @@ static void bch2_btree_set_root(struct btree_update *as, struct btree *b, ...@@ -1145,7 +1145,8 @@ static void bch2_btree_set_root(struct btree_update *as, struct btree *b,
struct btree *old; struct btree *old;
trace_btree_set_root(c, b); trace_btree_set_root(c, b);
BUG_ON(!b->written); BUG_ON(!b->written &&
!test_bit(BCH_FS_HOLD_BTREE_WRITES, &c->flags));
old = btree_node_root(c, b); old = btree_node_root(c, b);
......
...@@ -405,7 +405,7 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca, ...@@ -405,7 +405,7 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
_old; \ _old; \
}) })
bool bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca, void bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
size_t b, struct bucket_mark *old) size_t b, struct bucket_mark *old)
{ {
struct bucket *g; struct bucket *g;
...@@ -416,8 +416,7 @@ bool bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca, ...@@ -416,8 +416,7 @@ bool bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
g = bucket(ca, b); g = bucket(ca, b);
*old = bucket_data_cmpxchg(c, ca, g, new, ({ *old = bucket_data_cmpxchg(c, ca, g, new, ({
if (!is_available_bucket(new)) BUG_ON(!is_available_bucket(new));
return false;
new.owned_by_allocator = 1; new.owned_by_allocator = 1;
new.data_type = 0; new.data_type = 0;
...@@ -429,7 +428,6 @@ bool bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca, ...@@ -429,7 +428,6 @@ bool bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
if (!old->owned_by_allocator && old->cached_sectors) if (!old->owned_by_allocator && old->cached_sectors)
trace_invalidate(ca, bucket_to_sector(ca, b), trace_invalidate(ca, bucket_to_sector(ca, b),
old->cached_sectors); old->cached_sectors);
return true;
} }
void bch2_mark_alloc_bucket(struct bch_fs *c, struct bch_dev *ca, void bch2_mark_alloc_bucket(struct bch_fs *c, struct bch_dev *ca,
...@@ -822,7 +820,8 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) ...@@ -822,7 +820,8 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
/* XXX: these should be tunable */ /* XXX: these should be tunable */
size_t reserve_none = max_t(size_t, 4, ca->mi.nbuckets >> 9); size_t reserve_none = max_t(size_t, 4, ca->mi.nbuckets >> 9);
size_t copygc_reserve = max_t(size_t, 16, ca->mi.nbuckets >> 7); size_t copygc_reserve = max_t(size_t, 16, ca->mi.nbuckets >> 7);
size_t free_inc_reserve = copygc_reserve / 2; size_t free_inc_nr = max(max_t(size_t, 16, ca->mi.nbuckets >> 12),
btree_reserve);
bool resize = ca->buckets != NULL, bool resize = ca->buckets != NULL,
start_copygc = ca->copygc_thread != NULL; start_copygc = ca->copygc_thread != NULL;
int ret = -ENOMEM; int ret = -ENOMEM;
...@@ -845,8 +844,8 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) ...@@ -845,8 +844,8 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
!init_fifo(&free[RESERVE_MOVINGGC], !init_fifo(&free[RESERVE_MOVINGGC],
copygc_reserve, GFP_KERNEL) || copygc_reserve, GFP_KERNEL) ||
!init_fifo(&free[RESERVE_NONE], reserve_none, GFP_KERNEL) || !init_fifo(&free[RESERVE_NONE], reserve_none, GFP_KERNEL) ||
!init_fifo(&free_inc, free_inc_reserve, GFP_KERNEL) || !init_fifo(&free_inc, free_inc_nr, GFP_KERNEL) ||
!init_heap(&alloc_heap, free_inc_reserve, GFP_KERNEL) || !init_heap(&alloc_heap, ALLOC_SCAN_BATCH(ca) << 1, GFP_KERNEL) ||
!init_heap(&copygc_heap, copygc_reserve, GFP_KERNEL)) !init_heap(&copygc_heap, copygc_reserve, GFP_KERNEL))
goto err; goto err;
......
...@@ -205,7 +205,7 @@ static inline bool bucket_needs_journal_commit(struct bucket_mark m, ...@@ -205,7 +205,7 @@ static inline bool bucket_needs_journal_commit(struct bucket_mark m,
void bch2_bucket_seq_cleanup(struct bch_fs *); void bch2_bucket_seq_cleanup(struct bch_fs *);
bool bch2_invalidate_bucket(struct bch_fs *, struct bch_dev *, void bch2_invalidate_bucket(struct bch_fs *, struct bch_dev *,
size_t, struct bucket_mark *); size_t, struct bucket_mark *);
void bch2_mark_alloc_bucket(struct bch_fs *, struct bch_dev *, void bch2_mark_alloc_bucket(struct bch_fs *, struct bch_dev *,
size_t, bool, struct gc_pos, unsigned); size_t, bool, struct gc_pos, unsigned);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment