X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Freflink.c;h=26f0275ff0afad6a0c170854b24c409782bd36eb;hb=8642d4ae10f167a2eb850403f6d2b60757242b31;hp=a53a3d53c8da0d958ccdfd0e68144d55f0f74c3a;hpb=6f5afc0c12bbf56ffdabe5b2c5297aef255c4baa;p=bcachefs-tools-debian diff --git a/libbcachefs/reflink.c b/libbcachefs/reflink.c index a53a3d5..26f0275 100644 --- a/libbcachefs/reflink.c +++ b/libbcachefs/reflink.c @@ -26,19 +26,13 @@ static inline unsigned bkey_type_to_indirect(const struct bkey *k) /* reflink pointers */ int bch2_reflink_p_invalid(const struct bch_fs *c, struct bkey_s_c k, - int rw, struct printbuf *err) + unsigned flags, struct printbuf *err) { struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k); - if (bkey_val_bytes(p.k) != sizeof(*p.v)) { - pr_buf(err, "incorrect value size (%zu != %zu)", - bkey_val_bytes(p.k), sizeof(*p.v)); - return -EINVAL; - } - if (c->sb.version >= bcachefs_metadata_version_reflink_p_fix && le64_to_cpu(p.v->idx) < le32_to_cpu(p.v->front_pad)) { - pr_buf(err, "idx < front_pad (%llu < %u)", + prt_printf(err, "idx < front_pad (%llu < %u)", le64_to_cpu(p.v->idx), le32_to_cpu(p.v->front_pad)); return -EINVAL; } @@ -51,7 +45,7 @@ void bch2_reflink_p_to_text(struct printbuf *out, struct bch_fs *c, { struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k); - pr_buf(out, "idx %llu front_pad %u back_pad %u", + prt_printf(out, "idx %llu front_pad %u back_pad %u", le64_to_cpu(p.v->idx), le32_to_cpu(p.v->front_pad), le32_to_cpu(p.v->back_pad)); @@ -78,17 +72,9 @@ bool bch2_reflink_p_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r /* indirect extents */ int bch2_reflink_v_invalid(const struct bch_fs *c, struct bkey_s_c k, - int rw, struct printbuf *err) + unsigned flags, struct printbuf *err) { - struct bkey_s_c_reflink_v r = bkey_s_c_to_reflink_v(k); - - if (bkey_val_bytes(r.k) < sizeof(*r.v)) { - pr_buf(err, "incorrect value size (%zu < %zu)", - bkey_val_bytes(r.k), sizeof(*r.v)); - return -EINVAL; - } - - return bch2_bkey_ptrs_invalid(c, k, rw, err); + return bch2_bkey_ptrs_invalid(c, k, flags, err); } void bch2_reflink_v_to_text(struct printbuf *out, struct bch_fs *c, @@ -96,7 +82,7 @@ void bch2_reflink_v_to_text(struct printbuf *out, struct bch_fs *c, { struct bkey_s_c_reflink_v r = bkey_s_c_to_reflink_v(k); - pr_buf(out, "refcount: %llu ", le64_to_cpu(r.v->refcount)); + prt_printf(out, "refcount: %llu ", le64_to_cpu(r.v->refcount)); bch2_bkey_ptrs_to_text(out, c, k); } @@ -131,14 +117,8 @@ int bch2_trans_mark_reflink_v(struct btree_trans *trans, /* indirect inline data */ int bch2_indirect_inline_data_invalid(const struct bch_fs *c, struct bkey_s_c k, - int rw, struct printbuf *err) + unsigned flags, struct printbuf *err) { - if (bkey_val_bytes(k.k) < sizeof(struct bch_indirect_inline_data)) { - pr_buf(err, "incorrect value size (%zu < %zu)", - bkey_val_bytes(k.k), sizeof(struct bch_indirect_inline_data)); - return -EINVAL; - } - return 0; } @@ -148,7 +128,7 @@ void bch2_indirect_inline_data_to_text(struct printbuf *out, struct bkey_s_c_indirect_inline_data d = bkey_s_c_to_indirect_inline_data(k); unsigned datalen = bkey_inline_data_bytes(k.k); - pr_buf(out, "refcount %llu datalen %u: %*phN", + prt_printf(out, "refcount %llu datalen %u: %*phN", le64_to_cpu(d.v->refcount), datalen, min(datalen, 32U), d.v->data); } @@ -187,24 +167,13 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, if (orig->k.type == KEY_TYPE_inline_data) bch2_check_set_feature(c, BCH_FEATURE_reflink_inline_data); - for_each_btree_key_norestart(trans, reflink_iter, BTREE_ID_reflink, - POS(0, c->reflink_hint), - BTREE_ITER_INTENT|BTREE_ITER_SLOTS, k, ret) { - if (reflink_iter.pos.inode) { - bch2_btree_iter_set_pos(&reflink_iter, POS_MIN); - continue; - } - - if (bkey_deleted(k.k) && orig->k.size <= k.k->size) - break; - } - + bch2_trans_iter_init(trans, &reflink_iter, BTREE_ID_reflink, POS_MAX, + BTREE_ITER_INTENT); + k = bch2_btree_iter_peek_prev(&reflink_iter); + ret = bkey_err(k); if (ret) goto err; - /* rewind iter to start of hole, if necessary: */ - bch2_btree_iter_set_pos_to_extent_start(&reflink_iter); - r_v = bch2_trans_kmalloc(trans, sizeof(__le64) + bkey_bytes(&orig->k)); ret = PTR_ERR_OR_ZERO(r_v); if (ret) @@ -233,14 +202,19 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, orig->k.type = KEY_TYPE_reflink_p; r_p = bkey_i_to_reflink_p(orig); set_bkey_val_bytes(&r_p->k, sizeof(r_p->v)); + + /* FORTIFY_SOURCE is broken here, and doesn't provide unsafe_memset() */ +#if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE) + __underlying_memset(&r_p->v, 0, sizeof(r_p->v)); +#else memset(&r_p->v, 0, sizeof(r_p->v)); +#endif r_p->v.idx = cpu_to_le64(bkey_start_offset(&r_v->k)); ret = bch2_trans_update(trans, extent_iter, &r_p->k_i, BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE); err: - c->reflink_hint = reflink_iter.pos.offset; bch2_trans_iter_exit(trans, &reflink_iter); return ret; @@ -251,15 +225,15 @@ static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end) struct bkey_s_c k; int ret; - for_each_btree_key_continue_norestart(*iter, 0, k, ret) { - if (bkey_cmp(iter->pos, end) >= 0) - break; + for_each_btree_key_upto_continue_norestart(*iter, end, 0, k, ret) { + if (bkey_extent_is_unwritten(k)) + continue; if (bkey_extent_is_data(k.k)) return k; } - if (bkey_cmp(iter->pos, end) >= 0) + if (bkey_ge(iter->pos, end)) bch2_btree_iter_set_pos(iter, end); return ret ? bkey_s_c_err(ret) : bkey_s_c_null; } @@ -282,8 +256,8 @@ s64 bch2_remap_range(struct bch_fs *c, u32 dst_snapshot, src_snapshot; int ret = 0, ret2 = 0; - if (!percpu_ref_tryget(&c->writes)) - return -EROFS; + if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_reflink)) + return -BCH_ERR_erofs_no_writes; bch2_check_set_feature(c, BCH_FEATURE_reflink); @@ -299,8 +273,9 @@ s64 bch2_remap_range(struct bch_fs *c, bch2_trans_iter_init(&trans, &dst_iter, BTREE_ID_extents, dst_start, BTREE_ITER_INTENT); - while ((ret == 0 || ret == -EINTR) && - bkey_cmp(dst_iter.pos, dst_end) < 0) { + while ((ret == 0 || + bch2_err_matches(ret, BCH_ERR_transaction_restart)) && + bkey_lt(dst_iter.pos, dst_end)) { struct disk_reservation disk_res = { 0 }; bch2_trans_begin(&trans); @@ -333,7 +308,7 @@ s64 bch2_remap_range(struct bch_fs *c, if (ret) continue; - if (bkey_cmp(src_want, src_iter.pos) < 0) { + if (bkey_lt(src_want, src_iter.pos)) { ret = bch2_fpunch_at(&trans, &dst_iter, dst_inum, min(dst_end.offset, dst_iter.pos.offset + @@ -377,7 +352,7 @@ s64 bch2_remap_range(struct bch_fs *c, dst_end.offset - dst_iter.pos.offset)); ret = bch2_extent_update(&trans, dst_inum, &dst_iter, - new_dst.k, &disk_res, NULL, + new_dst.k, &disk_res, new_i_size, i_sectors_delta, true); bch2_disk_reservation_put(c, &disk_res); @@ -385,8 +360,8 @@ s64 bch2_remap_range(struct bch_fs *c, bch2_trans_iter_exit(&trans, &dst_iter); bch2_trans_iter_exit(&trans, &src_iter); - BUG_ON(!ret && bkey_cmp(dst_iter.pos, dst_end)); - BUG_ON(bkey_cmp(dst_iter.pos, dst_end) > 0); + BUG_ON(!ret && !bkey_eq(dst_iter.pos, dst_end)); + BUG_ON(bkey_gt(dst_iter.pos, dst_end)); dst_done = dst_iter.pos.offset - dst_start.offset; new_i_size = min(dst_iter.pos.offset << 9, new_i_size); @@ -409,13 +384,13 @@ s64 bch2_remap_range(struct bch_fs *c, } bch2_trans_iter_exit(&trans, &inode_iter); - } while (ret2 == -EINTR); + } while (bch2_err_matches(ret2, BCH_ERR_transaction_restart)); bch2_trans_exit(&trans); bch2_bkey_buf_exit(&new_src, c); bch2_bkey_buf_exit(&new_dst, c); - percpu_ref_put(&c->writes); + bch2_write_ref_put(c, BCH_WRITE_REF_reflink); return dst_done ?: ret ?: ret2; }