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: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
a2753581f6
commit
71c9e0ba42
@ -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,27 +1786,46 @@ 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;
|
||||
|
||||
BUG_ON(new.compressed_size > new.uncompressed_size);
|
||||
BUG_ON(new.live_size != e->k.size);
|
||||
BUG_ON(!new.compressed_size || !new.uncompressed_size);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
;
|
||||
|
||||
if (!bch2_crc_unpacked_cmp(crc, new))
|
||||
return;
|
||||
|
||||
bch2_extent_crc_init((void *) extent_entry_last(extent_i_to_s(e)), new);
|
||||
__extent_entry_push(e);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
* bch_extent_normalize - clean up an extent, dropping stale pointers etc.
|
||||
*
|
||||
|
@ -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 *);
|
||||
|
@ -431,12 +431,16 @@ static void init_append_extent(struct bch_write_op *op,
|
||||
struct bkey_i_extent *e = bkey_extent_init(op->insert_keys.top);
|
||||
|
||||
op->pos.offset += crc.uncompressed_size;
|
||||
e->k.p = op->pos;
|
||||
e->k.size = crc.uncompressed_size;
|
||||
e->k.version = version;
|
||||
e->k.p = op->pos;
|
||||
e->k.size = crc.uncompressed_size;
|
||||
e->k.version = version;
|
||||
bkey_extent_set_cached(&e->k, op->flags & BCH_WRITE_CACHED);
|
||||
|
||||
bch2_extent_crc_append(e, crc);
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user