// SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h"
+#include "bkey_on_stack.h"
#include "btree_update.h"
#include "extents.h"
#include "inode.h"
if ((u64) l.k->size + r.k->size > KEY_SIZE_MAX) {
bch2_key_resize(l.k, KEY_SIZE_MAX);
- __bch2_cut_front(l.k->p, _r);
+ bch2_cut_front_s(l.k->p, _r);
return BCH_MERGE_PARTIAL;
}
r_v->v.refcount = 0;
memcpy(r_v->v.start, e->v.start, bkey_val_bytes(&e->k));
- bch2_trans_update(trans, reflink_iter, &r_v->k_i);
+ bch2_trans_update(trans, reflink_iter, &r_v->k_i, 0);
r_p = bch2_trans_kmalloc(trans, sizeof(*r_p));
if (IS_ERR(r_p))
set_bkey_val_bytes(&r_p->k, sizeof(r_p->v));
r_p->v.idx = cpu_to_le64(bkey_start_offset(&r_v->k));
- bch2_trans_update(trans, extent_iter, &r_p->k_i);
+ bch2_trans_update(trans, extent_iter, &r_p->k_i, 0);
err:
- if (!IS_ERR(reflink_iter)) {
+ if (!IS_ERR(reflink_iter))
c->reflink_hint = reflink_iter->pos.offset;
- bch2_trans_iter_put(trans, reflink_iter);
- }
+ bch2_trans_iter_put(trans, reflink_iter);
return ret;
}
struct btree_trans trans;
struct btree_iter *dst_iter, *src_iter;
struct bkey_s_c src_k;
- BKEY_PADDED(k) new_dst, new_src;
+ BKEY_PADDED(k) new_dst;
+ struct bkey_on_stack new_src;
struct bpos dst_end = dst_start, src_end = src_start;
struct bpos dst_want, src_want;
u64 src_done, dst_done;
int ret = 0, ret2 = 0;
- if (!(c->sb.features & (1ULL << BCH_FEATURE_REFLINK))) {
- mutex_lock(&c->sb_lock);
- if (!(c->sb.features & (1ULL << BCH_FEATURE_REFLINK))) {
- c->disk_sb.sb->features[0] |=
- cpu_to_le64(1ULL << BCH_FEATURE_REFLINK);
+ if (!c->opts.reflink)
+ return -EOPNOTSUPP;
- bch2_write_super(c);
- }
- mutex_unlock(&c->sb_lock);
- }
+ if (!percpu_ref_tryget(&c->writes))
+ return -EROFS;
+
+ bch2_check_set_feature(c, BCH_FEATURE_reflink);
dst_end.offset += remap_sectors;
src_end.offset += remap_sectors;
+ bkey_on_stack_init(&new_src);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 4096);
src_iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, src_start,
BTREE_ITER_INTENT);
while (1) {
- bch2_trans_begin_updates(&trans);
+ bch2_trans_begin(&trans);
+
trans.mem_top = 0;
if (fatal_signal_pending(current)) {
break;
if (src_k.k->type == KEY_TYPE_extent) {
- bkey_reassemble(&new_src.k, src_k);
- src_k = bkey_i_to_s_c(&new_src.k);
+ bkey_on_stack_reassemble(&new_src, c, src_k);
+ src_k = bkey_i_to_s_c(new_src.k);
- bch2_cut_front(src_iter->pos, &new_src.k);
- bch2_cut_back(src_end, &new_src.k.k);
+ bch2_cut_front(src_iter->pos, new_src.k);
+ bch2_cut_back(src_end, new_src.k);
ret = bch2_make_extent_indirect(&trans, src_iter,
- bkey_i_to_extent(&new_src.k));
+ bkey_i_to_extent(new_src.k));
if (ret)
goto btree_err;
ret2 = PTR_ERR_OR_ZERO(inode_iter);
if (!ret2 &&
- inode_u.bi_size < new_i_size)
+ inode_u.bi_size < new_i_size) {
+ inode_u.bi_size = new_i_size;
ret2 = bch2_inode_write(&trans, inode_iter, &inode_u) ?:
- bch2_trans_commit(&trans, NULL, journal_seq,
- BTREE_INSERT_ATOMIC);
+ bch2_trans_commit(&trans, NULL, journal_seq, 0);
+ }
} while (ret2 == -EINTR);
ret = bch2_trans_exit(&trans) ?: ret;
+ bkey_on_stack_exit(&new_src, c);
+
+ percpu_ref_put(&c->writes);
return dst_done ?: ret ?: ret2;
}