Commit 71c9e0ba authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet
Browse files

bcachefs: bch2_extent_ptr_decoded_append()



This new helper for the move path avoids creating a new CRC entry when
we already have one that matches the pointer being added.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent a2753581
Loading
Loading
Loading
Loading
+44 −85
Original line number Diff line number Diff line
@@ -332,36 +332,36 @@ bool bch2_extent_narrow_crcs(struct bkey_i_extent *e,
	struct bch_extent_crc_unpacked u;
	struct extent_ptr_decoded p;
	union bch_extent_entry *i;
	bool ret = false;

	/* Find a checksum entry that covers only live data: */
	if (!n.csum_type)
	if (!n.csum_type) {
		extent_for_each_crc(extent_i_to_s(e), u, i)
			if (!u.compression_type &&
			    u.csum_type &&
			    u.live_size == u.uncompressed_size) {
				n = u;
				break;
				goto found;
			}

	if (!bch2_can_narrow_extent_crcs(extent_i_to_s_c(e), n))
		return false;

	}
found:
	BUG_ON(n.compression_type);
	BUG_ON(n.offset);
	BUG_ON(n.live_size != e->k.size);

	bch2_extent_crc_append(e, n);
restart_narrow_pointers:
	extent_for_each_ptr_decode(extent_i_to_s(e), p, i)
		if (can_narrow_crc(p.crc, n)) {
			i->ptr.offset += p.crc.offset;
			extent_ptr_append(e, i->ptr);
			bch2_extent_drop_ptr(extent_i_to_s(e), &i->ptr);
			p.ptr.offset += p.crc.offset;
			p.crc = n;
			bch2_extent_ptr_decoded_append(e, &p);
			ret = true;
			goto restart_narrow_pointers;
		}

	bch2_extent_drop_redundant_crcs(extent_i_to_s(e));
	return true;
	return ret;
}

/* returns true if not equal */
@@ -378,66 +378,6 @@ static inline bool bch2_crc_unpacked_cmp(struct bch_extent_crc_unpacked l,
		bch2_crc_cmp(l.csum, r.csum));
}

void bch2_extent_drop_redundant_crcs(struct bkey_s_extent e)
{
	union bch_extent_entry *entry = e.v->start;
	union bch_extent_crc *crc, *prev = NULL;
	struct bch_extent_crc_unpacked u, prev_u = { 0 };

	while (entry != extent_entry_last(e)) {
		union bch_extent_entry *next = extent_entry_next(entry);
		size_t crc_u64s = extent_entry_u64s(entry);

		if (!extent_entry_is_crc(entry))
			goto next;

		crc = entry_to_crc(entry);
		u = bch2_extent_crc_unpack(e.k, crc);

		if (next == extent_entry_last(e)) {
			/* crc entry with no pointers after it: */
			goto drop;
		}

		if (extent_entry_is_crc(next)) {
			/* no pointers before next crc entry: */
			goto drop;
		}

		if (prev && !bch2_crc_unpacked_cmp(u, prev_u)) {
			/* identical to previous crc entry: */
			goto drop;
		}

		if (!prev &&
		    !u.csum_type &&
		    !u.compression_type) {
			/* null crc entry: */
			union bch_extent_entry *e2;

			extent_for_each_entry_from(e, e2, extent_entry_next(entry)) {
				if (!extent_entry_is_ptr(e2))
					break;

				e2->ptr.offset += u.offset;
			}
			goto drop;
		}

		prev = crc;
		prev_u = u;
next:
		entry = next;
		continue;
drop:
		memmove_u64s_down(crc, next,
				  (u64 *) extent_entry_last(e) - (u64 *) next);
		e.k->u64s -= crc_u64s;
	}

	EBUG_ON(bkey_val_u64s(e.k) && !bch2_extent_nr_ptrs(e.c));
}

static void bch2_extent_drop_stale(struct bch_fs *c, struct bkey_s_extent e)
{
	struct bch_extent_ptr *ptr;
@@ -1846,25 +1786,44 @@ static void bch2_extent_crc_init(union bch_extent_crc *crc,
void bch2_extent_crc_append(struct bkey_i_extent *e,
			    struct bch_extent_crc_unpacked new)
{
	struct bch_extent_crc_unpacked crc;
	const union bch_extent_entry *i;
	bch2_extent_crc_init((void *) extent_entry_last(extent_i_to_s(e)), new);
	__extent_entry_push(e);
}

	BUG_ON(new.compressed_size > new.uncompressed_size);
	BUG_ON(new.live_size != e->k.size);
	BUG_ON(!new.compressed_size || !new.uncompressed_size);
static inline void __extent_entry_insert(struct bkey_i_extent *e,
					 union bch_extent_entry *dst,
					 union bch_extent_entry *new)
{
	union bch_extent_entry *end = extent_entry_last(extent_i_to_s(e));

	/*
	 * Look up the last crc entry, so we can check if we need to add
	 * another:
	 */
	extent_for_each_crc(extent_i_to_s(e), crc, i)
		;
	memmove_u64s_up((u64 *) dst + extent_entry_u64s(new),
			dst, (u64 *) end - (u64 *) dst);
	e->k.u64s += extent_entry_u64s(new);
	memcpy_u64s_small(dst, new, extent_entry_u64s(new));
}

	if (!bch2_crc_unpacked_cmp(crc, new))
		return;
void bch2_extent_ptr_decoded_append(struct bkey_i_extent *e,
				    struct extent_ptr_decoded *p)
{
	struct bch_extent_crc_unpacked crc = bch2_extent_crc_unpack(&e->k, NULL);
	union bch_extent_entry *pos;

	bch2_extent_crc_init((void *) extent_entry_last(extent_i_to_s(e)), new);
	__extent_entry_push(e);
	if (!bch2_crc_unpacked_cmp(crc, p->crc)) {
		pos = e->v.start;
		goto found;
	}

	extent_for_each_crc(extent_i_to_s(e), crc, pos)
		if (!bch2_crc_unpacked_cmp(crc, p->crc)) {
			pos = extent_entry_next(pos);
			goto found;
		}

	bch2_extent_crc_append(e, p->crc);
	pos = extent_entry_last(extent_i_to_s(e));
found:
	p->ptr.type = 1 << BCH_EXTENT_ENTRY_ptr;
	__extent_entry_insert(e, pos, to_entry(&p->ptr));
}

/*
+6 −3
Original line number Diff line number Diff line
@@ -213,11 +213,13 @@ union bch_extent_crc {
#define to_entry(_entry)						\
({									\
	BUILD_BUG_ON(!type_is(_entry, union bch_extent_crc *) &&	\
		     !type_is(_entry, struct bch_extent_ptr *));	\
		     !type_is(_entry, struct bch_extent_ptr *) &&	\
		     !type_is(_entry, struct bch_extent_stripe_ptr *));	\
									\
	__builtin_choose_expr(						\
		(type_is_exact(_entry, const union bch_extent_crc *) ||	\
		 type_is_exact(_entry, const struct bch_extent_ptr *)),	\
		 type_is_exact(_entry, const struct bch_extent_ptr *) ||\
		 type_is_exact(_entry, const struct bch_extent_stripe_ptr *)),\
		(const union bch_extent_entry *) (_entry),		\
		(union bch_extent_entry *) (_entry));			\
})
@@ -402,6 +404,8 @@ out: \

void bch2_extent_crc_append(struct bkey_i_extent *,
			    struct bch_extent_crc_unpacked);
void bch2_extent_ptr_decoded_append(struct bkey_i_extent *,
				    struct extent_ptr_decoded *);

static inline void __extent_entry_push(struct bkey_i_extent *e)
{
@@ -492,7 +496,6 @@ static inline struct bch_devs_list bch2_bkey_cached_devs(struct bkey_s_c k)
bool bch2_can_narrow_extent_crcs(struct bkey_s_c_extent,
				 struct bch_extent_crc_unpacked);
bool bch2_extent_narrow_crcs(struct bkey_i_extent *, struct bch_extent_crc_unpacked);
void bch2_extent_drop_redundant_crcs(struct bkey_s_extent);

union bch_extent_entry *bch2_extent_drop_ptr(struct bkey_s_extent ,
					     struct bch_extent_ptr *);
+8 −4
Original line number Diff line number Diff line
@@ -436,7 +436,11 @@ static void init_append_extent(struct bch_write_op *op,
	e->k.version	= version;
	bkey_extent_set_cached(&e->k, op->flags & BCH_WRITE_CACHED);

	if (crc.csum_type ||
	    crc.compression_type ||
	    crc.nonce)
		bch2_extent_crc_append(e, crc);

	bch2_alloc_sectors_append_ptrs(op->c, wp, e, crc.compressed_size);

	bch2_keylist_push(&op->insert_keys);
+1 −2
Original line number Diff line number Diff line
@@ -112,8 +112,7 @@ static int bch2_migrate_index_update(struct bch_write_op *op)
				continue;
			}

			bch2_extent_crc_append(insert, p.crc);
			extent_ptr_append(insert, p.ptr);
			bch2_extent_ptr_decoded_append(insert, &p);
			did_work = true;
		}

+10 −0
Original line number Diff line number Diff line
@@ -581,6 +581,16 @@ size_t bch2_rand_range(size_t);
void memcpy_to_bio(struct bio *, struct bvec_iter, void *);
void memcpy_from_bio(void *, struct bio *, struct bvec_iter);

static inline void memcpy_u64s_small(void *dst, const void *src,
				     unsigned u64s)
{
	u64 *d = dst;
	const u64 *s = src;

	while (u64s--)
		*d++ = *s++;
}

static inline void __memcpy_u64s(void *dst, const void *src,
				 unsigned u64s)
{