summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-05-30 00:54:39 +0200
committerKent Overstreet <kent.overstreet@linux.dev>2024-07-15 01:00:14 +0200
commit38ad9dc8c6194413a468f1eb288836b6c2783c6f (patch)
tree38f913074a21ec09f5816201c0dc28c1dd92bee2 /fs
parentbcachefs: Walk leaf to root in btree_gc (diff)
downloadlinux-38ad9dc8c6194413a468f1eb288836b6c2783c6f.tar.xz
linux-38ad9dc8c6194413a468f1eb288836b6c2783c6f.zip
bcachefs: Initialize gc buckets in alloc trigger
Needed for online fsck; we need the trigger to initialize newly allocated buckets and generation number changes while gc is running. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/alloc_background.c22
-rw-r--r--fs/bcachefs/btree_gc.c29
2 files changed, 20 insertions, 31 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c
index 9bb0dbe134d5..831fd0e2a5bf 100644
--- a/fs/bcachefs/alloc_background.c
+++ b/fs/bcachefs/alloc_background.c
@@ -831,10 +831,9 @@ int bch2_trigger_alloc(struct btree_trans *trans,
struct bch_alloc_v4 old_a_convert;
const struct bch_alloc_v4 *old_a = bch2_alloc_to_v4(old, &old_a_convert);
+ struct bch_alloc_v4 *new_a = bkey_s_to_alloc_v4(new).v;
if (flags & BTREE_TRIGGER_transactional) {
- struct bch_alloc_v4 *new_a = bkey_s_to_alloc_v4(new).v;
-
alloc_data_type_set(new_a, new_a->data_type);
if (bch2_bucket_sectors_total(*new_a) > bch2_bucket_sectors_total(*old_a)) {
@@ -906,7 +905,6 @@ int bch2_trigger_alloc(struct btree_trans *trans,
}
if ((flags & BTREE_TRIGGER_atomic) && (flags & BTREE_TRIGGER_insert)) {
- struct bch_alloc_v4 *new_a = bkey_s_to_alloc_v4(new).v;
u64 journal_seq = trans->journal_res.seq;
u64 bucket_journal_seq = new_a->journal_seq;
@@ -935,11 +933,9 @@ int bch2_trigger_alloc(struct btree_trans *trans,
c->journal.flushed_seq_ondisk,
new.k->p.inode, new.k->p.offset,
bucket_journal_seq);
- if (ret) {
- bch2_fs_fatal_error(c,
- "setting bucket_needs_journal_commit: %s", bch2_err_str(ret));
+ if (bch2_fs_fatal_err_on(ret, c,
+ "setting bucket_needs_journal_commit: %s", bch2_err_str(ret)))
goto err;
- }
}
if (new_a->gen != old_a->gen) {
@@ -974,6 +970,18 @@ int bch2_trigger_alloc(struct btree_trans *trans,
if (statechange(a->data_type == BCH_DATA_need_gc_gens))
bch2_gc_gens_async(c);
}
+
+ if ((flags & BTREE_TRIGGER_gc) && (flags & BTREE_TRIGGER_insert)) {
+ rcu_read_lock();
+ struct bucket *g = gc_bucket(ca, new.k->p.offset);
+ if (unlikely(!g)) {
+ rcu_read_unlock();
+ goto invalid_bucket;
+ }
+ g->gen_valid = 1;
+ g->gen = new_a->gen;
+ rcu_read_unlock();
+ }
err:
printbuf_exit(&buf);
bch2_dev_put(ca);
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 22771a861b29..f651a70b2a83 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -624,7 +624,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
}
ret = bch2_key_trigger(trans, btree_id, level, old, unsafe_bkey_s_c_to_s(k),
- BTREE_TRIGGER_gc|flags);
+ BTREE_TRIGGER_gc|BTREE_TRIGGER_insert|flags);
out:
fsck_err:
printbuf_exit(&buf);
@@ -891,14 +891,16 @@ static int bch2_gc_alloc_done(struct bch_fs *c)
static int bch2_gc_alloc_start(struct bch_fs *c)
{
+ int ret = 0;
+
for_each_member_device(c, ca) {
struct bucket_array *buckets = kvmalloc(sizeof(struct bucket_array) +
ca->mi.nbuckets * sizeof(struct bucket),
GFP_KERNEL|__GFP_ZERO);
if (!buckets) {
bch2_dev_put(ca);
- bch_err(c, "error allocating ca->buckets[gc]");
- return -BCH_ERR_ENOMEM_gc_alloc_start;
+ ret = -BCH_ERR_ENOMEM_gc_alloc_start;
+ break;
}
buckets->first_bucket = ca->mi.first_bucket;
@@ -908,27 +910,6 @@ static int bch2_gc_alloc_start(struct bch_fs *c)
rcu_assign_pointer(ca->buckets_gc, buckets);
}
- struct bch_dev *ca = NULL;
- int ret = bch2_trans_run(c,
- for_each_btree_key(trans, iter, BTREE_ID_alloc, POS_MIN,
- BTREE_ITER_prefetch, k, ({
- ca = bch2_dev_iterate(c, ca, k.k->p.inode);
- if (!ca) {
- bch2_btree_iter_set_pos(&iter, POS(k.k->p.inode + 1, 0));
- continue;
- }
-
- if (bucket_valid(ca, k.k->p.offset)) {
- struct bch_alloc_v4 a_convert;
- const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &a_convert);
-
- struct bucket *g = gc_bucket(ca, k.k->p.offset);
- g->gen_valid = 1;
- g->gen = a->gen;
- }
- 0;
- })));
- bch2_dev_put(ca);
bch_err_fn(c, ret);
return ret;
}