bcachefs: Move deletion of refcount=0 indirect extents to their triggers
For backpointers, we need to switch the order triggers are run in: we need to run triggers for deletions/overwrites before triggers for inserts. To avoid breaking the reflink triggers, this patch moves deleting of indirect extents with refcount=0 to their triggers, instead of doing it when we update those keys. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
parent
1296ab5520
commit
78668fe0bb
@ -1798,11 +1798,6 @@ static int __bch2_trans_mark_reflink_p(struct btree_trans *trans,
|
||||
|
||||
le64_add_cpu(refcount, add);
|
||||
|
||||
if (!*refcount) {
|
||||
n->k.type = KEY_TYPE_deleted;
|
||||
set_bkey_val_u64s(&n->k, 0);
|
||||
}
|
||||
|
||||
bch2_btree_iter_set_pos_to_extent_start(&iter);
|
||||
ret = bch2_trans_update(trans, &iter, n, 0);
|
||||
if (ret)
|
||||
|
@ -98,6 +98,24 @@ bool bch2_reflink_v_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r
|
||||
return l.v->refcount == r.v->refcount && bch2_extent_merge(c, _l, _r);
|
||||
}
|
||||
|
||||
int bch2_trans_mark_reflink_v(struct btree_trans *trans,
|
||||
struct bkey_s_c old, struct bkey_i *new,
|
||||
unsigned flags)
|
||||
{
|
||||
if (!(flags & BTREE_TRIGGER_OVERWRITE)) {
|
||||
struct bkey_i_reflink_v *r = bkey_i_to_reflink_v(new);
|
||||
|
||||
if (!r->v.refcount) {
|
||||
r->k.type = KEY_TYPE_deleted;
|
||||
r->k.size = 0;
|
||||
set_bkey_val_u64s(&r->k, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return bch2_trans_mark_extent(trans, old, new, flags);
|
||||
}
|
||||
|
||||
/* indirect inline data */
|
||||
|
||||
const char *bch2_indirect_inline_data_invalid(const struct bch_fs *c,
|
||||
@ -119,6 +137,24 @@ void bch2_indirect_inline_data_to_text(struct printbuf *out,
|
||||
min(datalen, 32U), d.v->data);
|
||||
}
|
||||
|
||||
int bch2_trans_mark_indirect_inline_data(struct btree_trans *trans,
|
||||
struct bkey_s_c old, struct bkey_i *new,
|
||||
unsigned flags)
|
||||
{
|
||||
if (!(flags & BTREE_TRIGGER_OVERWRITE)) {
|
||||
struct bkey_i_indirect_inline_data *r =
|
||||
bkey_i_to_indirect_inline_data(new);
|
||||
|
||||
if (!r->v.refcount) {
|
||||
r->k.type = KEY_TYPE_deleted;
|
||||
r->k.size = 0;
|
||||
set_bkey_val_u64s(&r->k, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bch2_make_extent_indirect(struct btree_trans *trans,
|
||||
struct btree_iter *extent_iter,
|
||||
struct bkey_i *orig)
|
||||
|
@ -18,12 +18,14 @@ bool bch2_reflink_p_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
|
||||
const char *bch2_reflink_v_invalid(const struct bch_fs *, struct bkey_s_c);
|
||||
void bch2_reflink_v_to_text(struct printbuf *, struct bch_fs *,
|
||||
struct bkey_s_c);
|
||||
int bch2_trans_mark_reflink_v(struct btree_trans *, struct bkey_s_c,
|
||||
struct bkey_i *, unsigned);
|
||||
|
||||
#define bch2_bkey_ops_reflink_v (struct bkey_ops) { \
|
||||
.key_invalid = bch2_reflink_v_invalid, \
|
||||
.val_to_text = bch2_reflink_v_to_text, \
|
||||
.swab = bch2_ptr_swab, \
|
||||
.trans_trigger = bch2_trans_mark_extent, \
|
||||
.trans_trigger = bch2_trans_mark_reflink_v, \
|
||||
.atomic_trigger = bch2_mark_extent, \
|
||||
}
|
||||
|
||||
@ -31,10 +33,14 @@ const char *bch2_indirect_inline_data_invalid(const struct bch_fs *,
|
||||
struct bkey_s_c);
|
||||
void bch2_indirect_inline_data_to_text(struct printbuf *,
|
||||
struct bch_fs *, struct bkey_s_c);
|
||||
int bch2_trans_mark_indirect_inline_data(struct btree_trans *,
|
||||
struct bkey_s_c, struct bkey_i *,
|
||||
unsigned);
|
||||
|
||||
#define bch2_bkey_ops_indirect_inline_data (struct bkey_ops) { \
|
||||
.key_invalid = bch2_indirect_inline_data_invalid, \
|
||||
.val_to_text = bch2_indirect_inline_data_to_text, \
|
||||
.trans_trigger = bch2_trans_mark_indirect_inline_data, \
|
||||
}
|
||||
|
||||
static inline const __le64 *bkey_refcount_c(struct bkey_s_c k)
|
||||
|
Loading…
Reference in New Issue
Block a user