Commit cdce1094 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: reconstruct_alloc cleanup



Now that we've got the errors_silent mechanism, we don't have to check
if the reconstruct_alloc option is set all over the place.

Also - users no longer have to explicitly select fsck and fix_errors.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 3bbed372
Loading
Loading
Loading
Loading
+29 −33
Original line number Diff line number Diff line
@@ -1052,14 +1052,13 @@ int bch2_check_alloc_key(struct btree_trans *trans,
	if (ret)
		goto err;

	if (k.k->type != discard_key_type &&
	    (c->opts.reconstruct_alloc ||
	     fsck_err(c, need_discard_key_wrong,
	if (fsck_err_on(k.k->type != discard_key_type,
			c, need_discard_key_wrong,
			"incorrect key in need_discard btree (got %s should be %s)\n"
			"  %s",
			bch2_bkey_types[k.k->type],
			bch2_bkey_types[discard_key_type],
		      (bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf)))) {
			(bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
		struct bkey_i *update =
			bch2_trans_kmalloc(trans, sizeof(*update));

@@ -1083,15 +1082,14 @@ int bch2_check_alloc_key(struct btree_trans *trans,
	if (ret)
		goto err;

	if (k.k->type != freespace_key_type &&
	    (c->opts.reconstruct_alloc ||
	     fsck_err(c, freespace_key_wrong,
	if (fsck_err_on(k.k->type != freespace_key_type,
			c, freespace_key_wrong,
			"incorrect key in freespace btree (got %s should be %s)\n"
			"  %s",
			bch2_bkey_types[k.k->type],
			bch2_bkey_types[freespace_key_type],
			(printbuf_reset(&buf),
		       bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf)))) {
			 bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
		struct bkey_i *update =
			bch2_trans_kmalloc(trans, sizeof(*update));

@@ -1115,14 +1113,13 @@ int bch2_check_alloc_key(struct btree_trans *trans,
	if (ret)
		goto err;

	if (a->gen != alloc_gen(k, gens_offset) &&
	    (c->opts.reconstruct_alloc ||
	     fsck_err(c, bucket_gens_key_wrong,
	if (fsck_err_on(a->gen != alloc_gen(k, gens_offset),
			c, bucket_gens_key_wrong,
			"incorrect gen in bucket_gens btree (got %u should be %u)\n"
			"  %s",
			alloc_gen(k, gens_offset), a->gen,
			(printbuf_reset(&buf),
		       bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf)))) {
			 bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
		struct bkey_i_bucket_gens *g =
			bch2_trans_kmalloc(trans, sizeof(*g));

@@ -1174,14 +1171,13 @@ int bch2_check_alloc_hole_freespace(struct btree_trans *trans,

	*end = bkey_min(k.k->p, *end);

	if (k.k->type != KEY_TYPE_set &&
	    (c->opts.reconstruct_alloc ||
	     fsck_err(c, freespace_hole_missing,
	if (fsck_err_on(k.k->type != KEY_TYPE_set,
			c, freespace_hole_missing,
			"hole in alloc btree missing in freespace btree\n"
			"  device %llu buckets %llu-%llu",
			freespace_iter->pos.inode,
			freespace_iter->pos.offset,
		      end->offset))) {
			end->offset)) {
		struct bkey_i *update =
			bch2_trans_kmalloc(trans, sizeof(*update));

+1 −2
Original line number Diff line number Diff line
@@ -477,8 +477,7 @@ static int check_bp_exists(struct btree_trans *trans,
	prt_printf(&buf, "\nbp pos ");
	bch2_bpos_to_text(&buf, bp_iter.pos);

	if (c->opts.reconstruct_alloc ||
	    fsck_err(c, ptr_to_missing_backpointer, "%s", buf.buf))
	if (fsck_err(c, ptr_to_missing_backpointer, "%s", buf.buf))
		ret = bch2_bucket_backpointer_mod(trans, bucket, bp, orig_k, true);

	goto out;
+38 −44
Original line number Diff line number Diff line
@@ -593,16 +593,15 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
		struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
		enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, &entry_c->ptr);

		if (!g->gen_valid &&
		    (c->opts.reconstruct_alloc ||
		     fsck_err(c, ptr_to_missing_alloc_key,
		if (fsck_err_on(!g->gen_valid,
				c, ptr_to_missing_alloc_key,
				"bucket %u:%zu data type %s ptr gen %u missing in alloc btree\n"
				"while marking %s",
				p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
				bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
				p.ptr.gen,
				(printbuf_reset(&buf),
			       bch2_bkey_val_to_text(&buf, c, *k), buf.buf)))) {
				 bch2_bkey_val_to_text(&buf, c, *k), buf.buf))) {
			if (!p.ptr.cached) {
				g->gen_valid		= true;
				g->gen			= p.ptr.gen;
@@ -611,16 +610,15 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
			}
		}

		if (gen_cmp(p.ptr.gen, g->gen) > 0 &&
		    (c->opts.reconstruct_alloc ||
		     fsck_err(c, ptr_gen_newer_than_bucket_gen,
		if (fsck_err_on(gen_cmp(p.ptr.gen, g->gen) > 0,
				c, ptr_gen_newer_than_bucket_gen,
				"bucket %u:%zu data type %s ptr gen in the future: %u > %u\n"
				"while marking %s",
				p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
				bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
				p.ptr.gen, g->gen,
				(printbuf_reset(&buf),
			       bch2_bkey_val_to_text(&buf, c, *k), buf.buf)))) {
				 bch2_bkey_val_to_text(&buf, c, *k), buf.buf))) {
			if (!p.ptr.cached) {
				g->gen_valid		= true;
				g->gen			= p.ptr.gen;
@@ -633,28 +631,26 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
			}
		}

		if (gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX &&
		    (c->opts.reconstruct_alloc ||
		     fsck_err(c, ptr_gen_newer_than_bucket_gen,
		if (fsck_err_on(gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX,
				c, ptr_gen_newer_than_bucket_gen,
				"bucket %u:%zu gen %u data type %s: ptr gen %u too stale\n"
				"while marking %s",
				p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), g->gen,
				bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
				p.ptr.gen,
				(printbuf_reset(&buf),
			       bch2_bkey_val_to_text(&buf, c, *k), buf.buf))))
				 bch2_bkey_val_to_text(&buf, c, *k), buf.buf)))
			do_update = true;

		if (!p.ptr.cached && gen_cmp(p.ptr.gen, g->gen) < 0 &&
		    (c->opts.reconstruct_alloc ||
		     fsck_err(c, stale_dirty_ptr,
		if (fsck_err_on(!p.ptr.cached && gen_cmp(p.ptr.gen, g->gen) < 0,
				c, stale_dirty_ptr,
				"bucket %u:%zu data type %s stale dirty ptr: %u < %u\n"
				"while marking %s",
				p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
				bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
				p.ptr.gen, g->gen,
				(printbuf_reset(&buf),
			       bch2_bkey_val_to_text(&buf, c, *k), buf.buf))))
				 bch2_bkey_val_to_text(&buf, c, *k), buf.buf)))
			do_update = true;

		if (data_type != BCH_DATA_btree && p.ptr.gen != g->gen)
@@ -1411,8 +1407,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
	if (gen_after(old->gen, gc.gen))
		return 0;

	if (c->opts.reconstruct_alloc ||
	    fsck_err_on(new.data_type != gc.data_type, c,
	if (fsck_err_on(new.data_type != gc.data_type, c,
			alloc_key_data_type_wrong,
			"bucket %llu:%llu gen %u has wrong data_type"
			": got %s, should be %s",
@@ -1423,8 +1418,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
		new.data_type = gc.data_type;

#define copy_bucket_field(_errtype, _f)					\
	if (c->opts.reconstruct_alloc ||				\
	    fsck_err_on(new._f != gc._f, c, _errtype,			\
	if (fsck_err_on(new._f != gc._f, c, _errtype,			\
			"bucket %llu:%llu gen %u data type %s has wrong " #_f	\
			": got %u, should be %u",			\
			iter->pos.inode, iter->pos.offset,		\
+1 −2
Original line number Diff line number Diff line
@@ -125,8 +125,7 @@ static int bch2_check_lru_key(struct btree_trans *trans,
			goto out;
		}

		if (c->opts.reconstruct_alloc ||
		    fsck_err(c, lru_entry_bad,
		if (fsck_err(c, lru_entry_bad,
			     "incorrect lru entry: lru %s time %llu\n"
			     "  %s\n"
			     "  for %s",
+38 −13
Original line number Diff line number Diff line
@@ -52,14 +52,47 @@ static bool btree_id_is_alloc(enum btree_id id)
}

/* for -o reconstruct_alloc: */
static void drop_alloc_keys(struct journal_keys *keys)
static void do_reconstruct_alloc(struct bch_fs *c)
{
	bch2_journal_log_msg(c, "dropping alloc info");
	bch_info(c, "dropping and reconstructing all alloc info");

	mutex_lock(&c->sb_lock);
	struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);

	__set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_allocations, ext->recovery_passes_required);
	__set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_alloc_info, ext->recovery_passes_required);
	__set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_lrus, ext->recovery_passes_required);
	__set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_extents_to_backpointers, ext->recovery_passes_required);
	__set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_alloc_to_lru_refs, ext->recovery_passes_required);

	__set_bit_le64(BCH_FSCK_ERR_ptr_to_missing_alloc_key, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_ptr_gen_newer_than_bucket_gen, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_stale_dirty_ptr, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_alloc_key_data_type_wrong, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_alloc_key_gen_wrong, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_alloc_key_dirty_sectors_wrong, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_alloc_key_stripe_wrong, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_alloc_key_stripe_redundancy_wrong, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_need_discard_key_wrong, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_freespace_key_wrong, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_bucket_gens_key_wrong, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_freespace_hole_missing, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_ptr_to_missing_backpointer, ext->errors_silent);
	__set_bit_le64(BCH_FSCK_ERR_lru_entry_bad, ext->errors_silent);
	c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);

	bch2_write_super(c);
	mutex_unlock(&c->sb_lock);

	c->recovery_passes_explicit |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));

	struct journal_keys *keys = &c->journal_keys;
	size_t src, dst;

	for (src = 0, dst = 0; src < keys->nr; src++)
		if (!btree_id_is_alloc(keys->data[src].btree_id))
			keys->data[dst++] = keys->data[src];

	keys->nr = dst;
}

@@ -395,11 +428,8 @@ static int read_btree_roots(struct bch_fs *c)
		if (!r->alive)
			continue;

		if (btree_id_is_alloc(i) &&
		    c->opts.reconstruct_alloc) {
			c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);
		if (btree_id_is_alloc(i) && c->opts.reconstruct_alloc)
			continue;
		}

		if (r->error) {
			__fsck_err(c,
@@ -930,10 +960,8 @@ int bch2_fs_recovery(struct bch_fs *c)
	c->journal_replay_seq_start	= last_seq;
	c->journal_replay_seq_end	= blacklist_seq - 1;

	if (c->opts.reconstruct_alloc) {
		c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);
		drop_alloc_keys(&c->journal_keys);
	}
	if (c->opts.reconstruct_alloc)
		do_reconstruct_alloc(c);

	zero_out_btree_mem_ptr(&c->journal_keys);

@@ -968,9 +996,6 @@ int bch2_fs_recovery(struct bch_fs *c)
	if (ret)
		goto err;

	if (c->opts.reconstruct_alloc)
		bch2_journal_log_msg(c, "dropping alloc info");

	/*
	 * Skip past versions that might have possibly been used (as nonces),
	 * but hadn't had their pointers written:
Loading