Commit 38ad9dc8 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 9ab55df5
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -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);

	if (flags & BTREE_TRIGGER_transactional) {
	struct bch_alloc_v4 *new_a = bkey_s_to_alloc_v4(new).v;

	if (flags & BTREE_TRIGGER_transactional) {
		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,12 +933,10 @@ 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) {
			rcu_read_lock();
@@ -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);
+5 −24
Original line number Diff line number Diff line
@@ -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;
}