mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 03:57:34 -04:00
bcachefs: unify reflink_p trigger
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
@@ -74,7 +74,7 @@ bool bch2_reflink_p_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r
|
||||
return true;
|
||||
}
|
||||
|
||||
static int trans_mark_reflink_p_segment(struct btree_trans *trans,
|
||||
static int trans_trigger_reflink_p_segment(struct btree_trans *trans,
|
||||
struct bkey_s_c_reflink_p p,
|
||||
u64 *idx, unsigned flags)
|
||||
{
|
||||
@@ -141,47 +141,16 @@ static int trans_mark_reflink_p_segment(struct btree_trans *trans,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __trans_mark_reflink_p(struct btree_trans *trans,
|
||||
enum btree_id btree_id, unsigned level,
|
||||
struct bkey_s_c k, unsigned flags)
|
||||
{
|
||||
struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k);
|
||||
u64 idx, end_idx;
|
||||
int ret = 0;
|
||||
|
||||
idx = le64_to_cpu(p.v->idx) - le32_to_cpu(p.v->front_pad);
|
||||
end_idx = le64_to_cpu(p.v->idx) + p.k->size +
|
||||
le32_to_cpu(p.v->back_pad);
|
||||
|
||||
while (idx < end_idx && !ret)
|
||||
ret = trans_mark_reflink_p_segment(trans, p, &idx, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_trans_mark_reflink_p(struct btree_trans *trans,
|
||||
enum btree_id btree_id, unsigned level,
|
||||
struct bkey_s_c old,
|
||||
struct bkey_s new,
|
||||
unsigned flags)
|
||||
{
|
||||
if (flags & BTREE_TRIGGER_INSERT) {
|
||||
struct bch_reflink_p *v = bkey_s_to_reflink_p(new).v;
|
||||
|
||||
v->front_pad = v->back_pad = 0;
|
||||
}
|
||||
|
||||
return trigger_run_overwrite_then_insert(__trans_mark_reflink_p, trans, btree_id, level, old, new, flags);
|
||||
}
|
||||
|
||||
static s64 __bch2_mark_reflink_p(struct btree_trans *trans,
|
||||
struct bkey_s_c_reflink_p p,
|
||||
u64 start, u64 end,
|
||||
u64 *idx, unsigned flags, size_t r_idx)
|
||||
static s64 gc_trigger_reflink_p_segment(struct btree_trans *trans,
|
||||
struct bkey_s_c_reflink_p p,
|
||||
u64 *idx, unsigned flags, size_t r_idx)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct reflink_gc *r;
|
||||
int add = !(flags & BTREE_TRIGGER_OVERWRITE) ? 1 : -1;
|
||||
u64 next_idx = end;
|
||||
u64 start = le64_to_cpu(p.v->idx);
|
||||
u64 end = le64_to_cpu(p.v->idx) + p.k->size;
|
||||
u64 next_idx = end + le32_to_cpu(p.v->back_pad);
|
||||
s64 ret = 0;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
@@ -205,20 +174,24 @@ static s64 __bch2_mark_reflink_p(struct btree_trans *trans,
|
||||
" missing range %llu-%llu",
|
||||
(bch2_bkey_val_to_text(&buf, c, p.s_c), buf.buf),
|
||||
*idx, next_idx)) {
|
||||
struct bkey_i_error *new;
|
||||
|
||||
new = bch2_trans_kmalloc(trans, sizeof(*new));
|
||||
ret = PTR_ERR_OR_ZERO(new);
|
||||
struct bkey_i *update = bch2_bkey_make_mut_noupdate(trans, p.s_c);
|
||||
ret = PTR_ERR_OR_ZERO(update);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
bkey_init(&new->k);
|
||||
new->k.type = KEY_TYPE_error;
|
||||
new->k.p = bkey_start_pos(p.k);
|
||||
new->k.p.offset += *idx - start;
|
||||
bch2_key_resize(&new->k, next_idx - *idx);
|
||||
ret = bch2_btree_insert_trans(trans, BTREE_ID_extents, &new->k_i,
|
||||
BTREE_TRIGGER_NORUN);
|
||||
if (next_idx <= start) {
|
||||
bkey_i_to_reflink_p(update)->v.front_pad = cpu_to_le32(start - next_idx);
|
||||
} else if (*idx >= end) {
|
||||
bkey_i_to_reflink_p(update)->v.back_pad = cpu_to_le32(*idx - end);
|
||||
} else {
|
||||
bkey_error_init(update);
|
||||
update->k.p = p.k->p;
|
||||
update->k.p.offset = next_idx;
|
||||
update->k.size = next_idx - *idx;
|
||||
set_bkey_val_u64s(&update->k, 0);
|
||||
}
|
||||
|
||||
ret = bch2_btree_insert_trans(trans, BTREE_ID_extents, update, BTREE_TRIGGER_NORUN);
|
||||
}
|
||||
|
||||
*idx = next_idx;
|
||||
@@ -228,50 +201,55 @@ static s64 __bch2_mark_reflink_p(struct btree_trans *trans,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __mark_reflink_p(struct btree_trans *trans,
|
||||
static int __trigger_reflink_p(struct btree_trans *trans,
|
||||
enum btree_id btree_id, unsigned level,
|
||||
struct bkey_s_c k, unsigned flags)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k);
|
||||
struct reflink_gc *ref;
|
||||
size_t l, r, m;
|
||||
u64 idx = le64_to_cpu(p.v->idx), start = idx;
|
||||
u64 end = le64_to_cpu(p.v->idx) + p.k->size;
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(!(flags & BTREE_TRIGGER_GC));
|
||||
u64 idx = le64_to_cpu(p.v->idx) - le32_to_cpu(p.v->front_pad);
|
||||
u64 end = le64_to_cpu(p.v->idx) + p.k->size + le32_to_cpu(p.v->back_pad);
|
||||
|
||||
if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_reflink_p_fix) {
|
||||
idx -= le32_to_cpu(p.v->front_pad);
|
||||
end += le32_to_cpu(p.v->back_pad);
|
||||
if (flags & BTREE_TRIGGER_TRANSACTIONAL) {
|
||||
while (idx < end && !ret)
|
||||
ret = trans_trigger_reflink_p_segment(trans, p, &idx, flags);
|
||||
}
|
||||
|
||||
l = 0;
|
||||
r = c->reflink_gc_nr;
|
||||
while (l < r) {
|
||||
m = l + (r - l) / 2;
|
||||
if (flags & BTREE_TRIGGER_GC) {
|
||||
size_t l = 0, r = c->reflink_gc_nr;
|
||||
|
||||
ref = genradix_ptr(&c->reflink_gc_table, m);
|
||||
if (ref->offset <= idx)
|
||||
l = m + 1;
|
||||
else
|
||||
r = m;
|
||||
while (l < r) {
|
||||
size_t m = l + (r - l) / 2;
|
||||
struct reflink_gc *ref = genradix_ptr(&c->reflink_gc_table, m);
|
||||
if (ref->offset <= idx)
|
||||
l = m + 1;
|
||||
else
|
||||
r = m;
|
||||
}
|
||||
|
||||
while (idx < end && !ret)
|
||||
ret = gc_trigger_reflink_p_segment(trans, p, &idx, flags, l++);
|
||||
}
|
||||
|
||||
while (idx < end && !ret)
|
||||
ret = __bch2_mark_reflink_p(trans, p, start, end,
|
||||
&idx, flags, l++);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_mark_reflink_p(struct btree_trans *trans,
|
||||
enum btree_id btree_id, unsigned level,
|
||||
struct bkey_s_c old, struct bkey_s new,
|
||||
unsigned flags)
|
||||
int bch2_trigger_reflink_p(struct btree_trans *trans,
|
||||
enum btree_id btree_id, unsigned level,
|
||||
struct bkey_s_c old,
|
||||
struct bkey_s new,
|
||||
unsigned flags)
|
||||
{
|
||||
return trigger_run_overwrite_then_insert(__mark_reflink_p, trans, btree_id, level, old, new, flags);
|
||||
if ((flags & BTREE_TRIGGER_TRANSACTIONAL) &&
|
||||
(flags & BTREE_TRIGGER_INSERT)) {
|
||||
struct bch_reflink_p *v = bkey_s_to_reflink_p(new).v;
|
||||
|
||||
v->front_pad = v->back_pad = 0;
|
||||
}
|
||||
|
||||
return trigger_run_overwrite_then_insert(__trigger_reflink_p, trans, btree_id, level, old, new, flags);
|
||||
}
|
||||
|
||||
/* indirect extents */
|
||||
|
||||
@@ -9,17 +9,15 @@ int bch2_reflink_p_invalid(struct bch_fs *, struct bkey_s_c,
|
||||
void bch2_reflink_p_to_text(struct printbuf *, struct bch_fs *,
|
||||
struct bkey_s_c);
|
||||
bool bch2_reflink_p_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
|
||||
int bch2_trans_mark_reflink_p(struct btree_trans *, enum btree_id, unsigned,
|
||||
struct bkey_s_c, struct bkey_s, unsigned);
|
||||
int bch2_mark_reflink_p(struct btree_trans *, enum btree_id, unsigned,
|
||||
struct bkey_s_c, struct bkey_s, unsigned);
|
||||
int bch2_trigger_reflink_p(struct btree_trans *, enum btree_id, unsigned,
|
||||
struct bkey_s_c, struct bkey_s, unsigned);
|
||||
|
||||
#define bch2_bkey_ops_reflink_p ((struct bkey_ops) { \
|
||||
.key_invalid = bch2_reflink_p_invalid, \
|
||||
.val_to_text = bch2_reflink_p_to_text, \
|
||||
.key_merge = bch2_reflink_p_merge, \
|
||||
.trans_trigger = bch2_trans_mark_reflink_p, \
|
||||
.atomic_trigger = bch2_mark_reflink_p, \
|
||||
.trans_trigger = bch2_trigger_reflink_p, \
|
||||
.atomic_trigger = bch2_trigger_reflink_p, \
|
||||
.min_val_size = 16, \
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user