Commit 47d2080e authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Kill bch2_bkey_ptr_data_type()



Remove some duplication, and inconsistency between check_fix_ptrs and
the main ptr marking paths

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent dcc1c045
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -29,8 +29,7 @@ static bool extent_matches_bp(struct bch_fs *c,
		if (p.ptr.cached)
			continue;

		bch2_extent_ptr_to_bp(c, btree_id, level, k, p,
				      &bucket2, &bp2);
		bch2_extent_ptr_to_bp(c, btree_id, level, k, p, entry, &bucket2, &bp2);
		if (bpos_eq(bucket, bucket2) &&
		    !memcmp(&bp, &bp2, sizeof(bp)))
			return true;
@@ -507,8 +506,7 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
		if (p.ptr.cached)
			continue;

		bch2_extent_ptr_to_bp(c, btree, level,
				      k, p, &bucket_pos, &bp);
		bch2_extent_ptr_to_bp(c, btree, level, k, p, entry, &bucket_pos, &bp);

		ret = check_bp_exists(trans, s, bucket_pos, bp, k);
		if (ret)
+26 −6
Original line number Diff line number Diff line
@@ -90,20 +90,40 @@ static inline int bch2_bucket_backpointer_mod(struct btree_trans *trans,
	return bch2_trans_update_buffered(trans, BTREE_ID_backpointers, &bp_k.k_i);
}

static inline enum bch_data_type bkey_ptr_data_type(enum btree_id btree_id, unsigned level,
						    struct bkey_s_c k, struct extent_ptr_decoded p)
static inline enum bch_data_type bch2_bkey_ptr_data_type(struct bkey_s_c k,
							 struct extent_ptr_decoded p,
							 const union bch_extent_entry *entry)
{
	return  level		? BCH_DATA_btree :
		p.has_ec	? BCH_DATA_stripe :
				  BCH_DATA_user;
	switch (k.k->type) {
	case KEY_TYPE_btree_ptr:
	case KEY_TYPE_btree_ptr_v2:
		return BCH_DATA_btree;
	case KEY_TYPE_extent:
	case KEY_TYPE_reflink_v:
		return p.has_ec ? BCH_DATA_stripe : BCH_DATA_user;
	case KEY_TYPE_stripe: {
		const struct bch_extent_ptr *ptr = &entry->ptr;
		struct bkey_s_c_stripe s = bkey_s_c_to_stripe(k);

		BUG_ON(ptr < s.v->ptrs ||
		       ptr >= s.v->ptrs + s.v->nr_blocks);

		return ptr >= s.v->ptrs + s.v->nr_blocks - s.v->nr_redundant
			? BCH_DATA_parity
			: BCH_DATA_user;
	}
	default:
		BUG();
	}
}

static inline void bch2_extent_ptr_to_bp(struct bch_fs *c,
			   enum btree_id btree_id, unsigned level,
			   struct bkey_s_c k, struct extent_ptr_decoded p,
			   const union bch_extent_entry *entry,
			   struct bpos *bucket_pos, struct bch_backpointer *bp)
{
	enum bch_data_type data_type = bkey_ptr_data_type(btree_id, level, k, p);
	enum bch_data_type data_type = bch2_bkey_ptr_data_type(k, p, entry);
	s64 sectors = level ? btree_sectors(c) : k.k->size;
	u32 bucket_offset;

+32 −27
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include "bcachefs.h"
#include "alloc_background.h"
#include "alloc_foreground.h"
#include "backpointers.h"
#include "bkey_methods.h"
#include "bkey_buf.h"
#include "btree_journal_iter.h"
@@ -508,7 +509,7 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
	bkey_for_each_ptr_decode(k->k, ptrs_c, p, entry_c) {
		struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
		struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
		enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, &entry_c->ptr);
		enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, p, entry_c);

		if (fsck_err_on(!g->gen_valid,
				c, ptr_to_missing_alloc_key,
@@ -574,7 +575,8 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
			continue;

		if (fsck_err_on(bucket_data_type(g->data_type) &&
				bucket_data_type(g->data_type) != data_type, c,
				bucket_data_type(g->data_type) !=
				bucket_data_type(data_type), c,
				ptr_bucket_data_type_mismatch,
				"bucket %u:%zu different types of data in same bucket: %s, %s\n"
				"while marking %s",
@@ -615,18 +617,13 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
	}

	if (do_update) {
		struct bkey_ptrs ptrs;
		union bch_extent_entry *entry;
		struct bch_extent_ptr *ptr;
		struct bkey_i *new;

		if (is_root) {
			bch_err(c, "cannot update btree roots yet");
			ret = -EINVAL;
			goto err;
		}

		new = kmalloc(bkey_bytes(k->k), GFP_KERNEL);
		struct bkey_i *new = kmalloc(bkey_bytes(k->k), GFP_KERNEL);
		if (!new) {
			ret = -BCH_ERR_ENOMEM_gc_repair_key;
			bch_err_msg(c, ret, "allocating new key");
@@ -641,7 +638,7 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
			 * btree node isn't there anymore, the read path will
			 * sort it out:
			 */
			ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
			struct bkey_ptrs ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
			bkey_for_each_ptr(ptrs, ptr) {
				struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
				struct bucket *g = PTR_GC_BUCKET(ca, ptr);
@@ -649,19 +646,26 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
				ptr->gen = g->gen;
			}
		} else {
			bch2_bkey_drop_ptrs(bkey_i_to_s(new), ptr, ({
				struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
				struct bucket *g = PTR_GC_BUCKET(ca, ptr);
				enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, ptr);
			struct bkey_ptrs ptrs;
			union bch_extent_entry *entry;
restart_drop_ptrs:
			ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
			bkey_for_each_ptr_decode(bkey_i_to_s(new).k, ptrs, p, entry) {
				struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
				struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
				enum bch_data_type data_type = bch2_bkey_ptr_data_type(bkey_i_to_s_c(new), p, entry);

				(ptr->cached &&
				 (!g->gen_valid || gen_cmp(ptr->gen, g->gen) > 0)) ||
				(!ptr->cached &&
				 gen_cmp(ptr->gen, g->gen) < 0) ||
				gen_cmp(g->gen, ptr->gen) > BUCKET_GC_GEN_MAX ||
				if ((p.ptr.cached &&
				     (!g->gen_valid || gen_cmp(p.ptr.gen, g->gen) > 0)) ||
				    (!p.ptr.cached &&
				     gen_cmp(p.ptr.gen, g->gen) < 0) ||
				    gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX ||
				    (g->data_type &&
				 g->data_type != data_type);
			}));
				     g->data_type != data_type)) {
					bch2_bkey_drop_ptr(bkey_i_to_s(new), &entry->ptr);
					goto restart_drop_ptrs;
				}
			}
again:
			ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
			bkey_extent_entry_for_each(ptrs, entry) {
@@ -736,10 +740,6 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
		BUG_ON(bch2_journal_seq_verify &&
		       k->k->version.lo > atomic64_read(&c->journal.seq));

		ret = bch2_check_fix_ptrs(trans, btree_id, level, is_root, k);
		if (ret)
			goto err;

		if (fsck_err_on(k->k->version.lo > atomic64_read(&c->key_version), c,
				bkey_version_in_future,
				"key version number higher than recorded: %llu > %llu",
@@ -748,8 +748,13 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
			atomic64_set(&c->key_version, k->k->version.lo);
	}

	ret = bch2_check_fix_ptrs(trans, btree_id, level, is_root, k);
	if (ret)
		goto err;

	ret = commit_do(trans, NULL, NULL, 0,
			bch2_key_trigger(trans, btree_id, level, old, unsafe_bkey_s_c_to_s(*k), BTREE_TRIGGER_GC));
			bch2_key_trigger(trans, btree_id, level, old,
					 unsafe_bkey_s_c_to_s(*k), BTREE_TRIGGER_GC));
fsck_err:
err:
	bch_err_fn(c, ret);
+7 −5
Original line number Diff line number Diff line
@@ -525,6 +525,7 @@ int bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
			"different types of data in same bucket: %s, %s",
			bch2_data_type_str(g->data_type),
			bch2_data_type_str(data_type))) {
		BUG();
		ret = -EIO;
		goto err;
	}
@@ -628,6 +629,7 @@ int bch2_check_bucket_ref(struct btree_trans *trans,
			bch2_data_type_str(ptr_data_type),
			(printbuf_reset(&buf),
			 bch2_bkey_val_to_text(&buf, c, k), buf.buf));
		BUG();
		ret = -EIO;
		goto err;
	}
@@ -815,14 +817,14 @@ static int __mark_pointer(struct btree_trans *trans,
static int bch2_trigger_pointer(struct btree_trans *trans,
			enum btree_id btree_id, unsigned level,
			struct bkey_s_c k, struct extent_ptr_decoded p,
			s64 *sectors,
			unsigned flags)
			const union bch_extent_entry *entry,
			s64 *sectors, unsigned flags)
{
	bool insert = !(flags & BTREE_TRIGGER_OVERWRITE);
	struct bpos bucket;
	struct bch_backpointer bp;

	bch2_extent_ptr_to_bp(trans->c, btree_id, level, k, p, &bucket, &bp);
	bch2_extent_ptr_to_bp(trans->c, btree_id, level, k, p, entry, &bucket, &bp);
	*sectors = insert ? bp.bucket_len : -((s64) bp.bucket_len);

	if (flags & BTREE_TRIGGER_TRANSACTIONAL) {
@@ -851,7 +853,7 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
	if (flags & BTREE_TRIGGER_GC) {
		struct bch_fs *c = trans->c;
		struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
		enum bch_data_type data_type = bkey_ptr_data_type(btree_id, level, k, p);
		enum bch_data_type data_type = bch2_bkey_ptr_data_type(k, p, entry);

		percpu_down_read(&c->mark_lock);
		struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
@@ -979,7 +981,7 @@ static int __trigger_extent(struct btree_trans *trans,

	bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
		s64 disk_sectors;
		ret = bch2_trigger_pointer(trans, btree_id, level, k, p, &disk_sectors, flags);
		ret = bch2_trigger_pointer(trans, btree_id, level, k, p, entry, &disk_sectors, flags);
		if (ret < 0)
			return ret;

+0 −24
Original line number Diff line number Diff line
@@ -596,30 +596,6 @@ static inline struct bch_devs_list bch2_bkey_cached_devs(struct bkey_s_c k)
	return ret;
}

static inline unsigned bch2_bkey_ptr_data_type(struct bkey_s_c k, const struct bch_extent_ptr *ptr)
{
	switch (k.k->type) {
	case KEY_TYPE_btree_ptr:
	case KEY_TYPE_btree_ptr_v2:
		return BCH_DATA_btree;
	case KEY_TYPE_extent:
	case KEY_TYPE_reflink_v:
		return BCH_DATA_user;
	case KEY_TYPE_stripe: {
		struct bkey_s_c_stripe s = bkey_s_c_to_stripe(k);

		BUG_ON(ptr < s.v->ptrs ||
		       ptr >= s.v->ptrs + s.v->nr_blocks);

		return ptr >= s.v->ptrs + s.v->nr_blocks - s.v->nr_redundant
			? BCH_DATA_parity
			: BCH_DATA_user;
	}
	default:
		BUG();
	}
}

unsigned bch2_bkey_nr_ptrs(struct bkey_s_c);
unsigned bch2_bkey_nr_ptrs_allocated(struct bkey_s_c);
unsigned bch2_bkey_nr_ptrs_fully_allocated(struct bkey_s_c);