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

bcachefs: Don't require alloc btree to be updated before buckets are used

This is to break a circular dependency in the shutdown path.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent beb6db68
...@@ -843,7 +843,7 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans, ...@@ -843,7 +843,7 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans,
struct bkey_s_c k; struct bkey_s_c k;
bool invalidating_cached_data; bool invalidating_cached_data;
size_t b; size_t b;
int ret; int ret = 0;
BUG_ON(!ca->alloc_heap.used || BUG_ON(!ca->alloc_heap.used ||
!ca->alloc_heap.data[0].nr); !ca->alloc_heap.data[0].nr);
...@@ -857,11 +857,18 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans, ...@@ -857,11 +857,18 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans,
BUG_ON(!fifo_push(&ca->free_inc, b)); BUG_ON(!fifo_push(&ca->free_inc, b));
g = bucket(ca, b);
m = READ_ONCE(g->mark);
bch2_mark_alloc_bucket(c, ca, b, true, gc_pos_alloc(c, NULL), 0); bch2_mark_alloc_bucket(c, ca, b, true, gc_pos_alloc(c, NULL), 0);
spin_unlock(&c->freelist_lock); spin_unlock(&c->freelist_lock);
percpu_up_read(&c->mark_lock); percpu_up_read(&c->mark_lock);
invalidating_cached_data = m.cached_sectors != 0;
if (!invalidating_cached_data)
goto out;
BUG_ON(BKEY_ALLOC_VAL_U64s_MAX > 8); BUG_ON(BKEY_ALLOC_VAL_U64s_MAX > 8);
bch2_btree_iter_set_pos(iter, POS(ca->dev_idx, b)); bch2_btree_iter_set_pos(iter, POS(ca->dev_idx, b));
...@@ -915,7 +922,7 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans, ...@@ -915,7 +922,7 @@ static int bch2_invalidate_one_bucket2(struct btree_trans *trans,
flags); flags);
if (ret == -EINTR) if (ret == -EINTR)
goto retry; goto retry;
out:
if (!ret) { if (!ret) {
/* remove from alloc_heap: */ /* remove from alloc_heap: */
struct alloc_heap_entry e, *top = ca->alloc_heap.data; struct alloc_heap_entry e, *top = ca->alloc_heap.data;
......
...@@ -1457,11 +1457,13 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans, ...@@ -1457,11 +1457,13 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!ret && unlikely(!test_bit(BCH_FS_ALLOC_WRITTEN, &c->flags))) { if (k.k->type != KEY_TYPE_alloc ||
(!ret && unlikely(!test_bit(BCH_FS_ALLOC_WRITTEN, &c->flags)))) {
/* /*
* During journal replay, and if gc repairs alloc info at * During journal replay, and if gc repairs alloc info at
* runtime, the alloc info in the btree might not be up to date * runtime, the alloc info in the btree might not be up to date
* yet - so, trust the in memory mark: * yet - so, trust the in memory mark - unless we're already
* updating that key:
*/ */
struct bucket *g; struct bucket *g;
struct bucket_mark m; struct bucket_mark m;
...@@ -1472,22 +1474,39 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans, ...@@ -1472,22 +1474,39 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
u = alloc_mem_to_key(g, m); u = alloc_mem_to_key(g, m);
percpu_up_read(&c->mark_lock); percpu_up_read(&c->mark_lock);
} else { } else {
/*
* Unless we're already updating that key:
*/
if (k.k->type != KEY_TYPE_alloc) {
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
"pointer to nonexistent bucket %llu:%llu",
iter->pos.inode, iter->pos.offset);
ret = -1;
goto out;
}
u = bch2_alloc_unpack(k); u = bch2_alloc_unpack(k);
} }
if (gen_after(u.gen, p.ptr.gen)) { if (u.gen != p.ptr.gen) {
ret = 1; ret = 1;
if (gen_after(p.ptr.gen, u.gen)) {
bch2_fs_inconsistent(c,
"bucket %llu:%llu gen %u data type %s: ptr gen %u newer than bucket gen",
iter->pos.inode, iter->pos.offset, u.gen,
bch2_data_types[u.data_type ?: data_type],
p.ptr.gen);
ret = -EIO;
}
if (gen_cmp(u.gen, p.ptr.gen) >= 96U) {
bch2_fs_inconsistent(c,
"bucket %llu:%llu gen %u data type %s: ptr gen %u too stale",
iter->pos.inode, iter->pos.offset, u.gen,
bch2_data_types[u.data_type ?: data_type],
p.ptr.gen);
ret = -EIO;
}
if (!p.ptr.cached) {
bch2_fs_inconsistent(c,
"bucket %llu:%llu gen %u data type %s: stale dirty ptr (gen %u)",
iter->pos.inode, iter->pos.offset, u.gen,
bch2_data_types[u.data_type ?: data_type],
p.ptr.gen);
ret = -EIO;
}
goto out; goto out;
} }
......
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