bcachefs: Merging for indirect extents
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 15 May 2021 19:04:08 +0000 (15:04 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:06 +0000 (17:09 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/extents.c
fs/bcachefs/reflink.c

index abb15688a6642349a63e32da24ce71b744190b1c..c7643e6c8816e70e9c7b22f39336af079d547478 100644 (file)
@@ -229,33 +229,36 @@ void bch2_extent_to_text(struct printbuf *out, struct bch_fs *c,
        bch2_bkey_ptrs_to_text(out, c, k);
 }
 
-bool bch2_extent_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r)
+bool bch2_extent_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
 {
-       struct bkey_s_extent l = bkey_s_to_extent(_l);
-       struct bkey_s_c_extent r = bkey_s_c_to_extent(_r);
+       struct bkey_ptrs   l_ptrs = bch2_bkey_ptrs(l);
+       struct bkey_ptrs_c r_ptrs = bch2_bkey_ptrs_c(r);
        union bch_extent_entry *en_l;
        const union bch_extent_entry *en_r;
        struct extent_ptr_decoded lp, rp;
        bool use_right_ptr;
        struct bch_dev *ca;
 
-       if (bkey_val_u64s(l.k) != bkey_val_u64s(r.k))
-               return false;
-
-       extent_for_each_entry(l, en_l) {
-               en_r = vstruct_idx(r.v, (u64 *) en_l - l.v->_data);
-
+       en_l = l_ptrs.start;
+       en_r = r_ptrs.start;
+       while (en_l < l_ptrs.end && en_r < r_ptrs.end) {
                if (extent_entry_type(en_l) != extent_entry_type(en_r))
                        return false;
+
+               en_l = extent_entry_next(en_l);
+               en_r = extent_entry_next(en_r);
        }
 
-       en_l = l.v->start;
-       en_r = r.v->start;
+       if (en_l < l_ptrs.end || en_r < r_ptrs.end)
+               return false;
+
+       en_l = l_ptrs.start;
+       en_r = r_ptrs.start;
        lp.crc = bch2_extent_crc_unpack(l.k, NULL);
        rp.crc = bch2_extent_crc_unpack(r.k, NULL);
 
-       while (__bkey_ptr_next_decode(l.k, extent_entry_last(l), lp, en_l) &&
-              __bkey_ptr_next_decode(r.k, extent_entry_last(r), rp, en_r)) {
+       while (__bkey_ptr_next_decode(l.k, l_ptrs.end, lp, en_l) &&
+              __bkey_ptr_next_decode(r.k, r_ptrs.end, rp, en_r)) {
                if (lp.ptr.offset + lp.crc.offset + lp.crc.live_size !=
                    rp.ptr.offset + rp.crc.offset ||
                    lp.ptr.dev                  != rp.ptr.dev ||
@@ -311,43 +314,45 @@ bool bch2_extent_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r)
        }
 
        use_right_ptr = false;
-       extent_for_each_entry(l, en_l) {
-               struct bch_extent_crc_unpacked crc_l, crc_r;
-
-               en_r = vstruct_idx(r.v, (u64 *) en_l - l.v->_data);
-
+       en_l = l_ptrs.start;
+       en_r = r_ptrs.start;
+       while (en_l < l_ptrs.end) {
                if (extent_entry_type(en_l) == BCH_EXTENT_ENTRY_ptr &&
                    use_right_ptr)
                        en_l->ptr = en_r->ptr;
 
-               if (!extent_entry_is_crc(en_l))
-                       continue;
-
-               use_right_ptr = false;
-
-               crc_l = bch2_extent_crc_unpack(l.k, entry_to_crc(en_l));
-               crc_r = bch2_extent_crc_unpack(r.k, entry_to_crc(en_r));
-
-               if (crc_l.offset + crc_l.live_size + crc_r.live_size <=
-                   crc_l.uncompressed_size) {
-                       /* can use left extent's crc entry */
-               } else if (crc_l.live_size <= crc_r.offset ) {
-                       /* can use right extent's crc entry */
-                       crc_r.offset -= crc_l.live_size;
-                       bch2_extent_crc_pack(entry_to_crc(en_l), crc_r,
-                                            extent_entry_type(en_l));
-                       use_right_ptr = true;
-               } else {
-                       crc_l.csum = bch2_checksum_merge(crc_l.csum_type,
-                                                        crc_l.csum,
-                                                        crc_r.csum,
-                                                        crc_r.uncompressed_size << 9);
-
-                       crc_l.uncompressed_size += crc_r.uncompressed_size;
-                       crc_l.compressed_size   += crc_r.compressed_size;
-                       bch2_extent_crc_pack(entry_to_crc(en_l), crc_l,
-                                            extent_entry_type(en_l));
+               if (extent_entry_is_crc(en_l)) {
+                       struct bch_extent_crc_unpacked crc_l =
+                               bch2_extent_crc_unpack(l.k, entry_to_crc(en_l));
+                       struct bch_extent_crc_unpacked crc_r =
+                               bch2_extent_crc_unpack(r.k, entry_to_crc(en_r));
+
+                       use_right_ptr = false;
+
+                       if (crc_l.offset + crc_l.live_size + crc_r.live_size <=
+                           crc_l.uncompressed_size) {
+                               /* can use left extent's crc entry */
+                       } else if (crc_l.live_size <= crc_r.offset ) {
+                               /* can use right extent's crc entry */
+                               crc_r.offset -= crc_l.live_size;
+                               bch2_extent_crc_pack(entry_to_crc(en_l), crc_r,
+                                                    extent_entry_type(en_l));
+                               use_right_ptr = true;
+                       } else {
+                               crc_l.csum = bch2_checksum_merge(crc_l.csum_type,
+                                                                crc_l.csum,
+                                                                crc_r.csum,
+                                                                crc_r.uncompressed_size << 9);
+
+                               crc_l.uncompressed_size += crc_r.uncompressed_size;
+                               crc_l.compressed_size   += crc_r.compressed_size;
+                               bch2_extent_crc_pack(entry_to_crc(en_l), crc_l,
+                                                    extent_entry_type(en_l));
+                       }
                }
+
+               en_l = extent_entry_next(en_l);
+               en_r = extent_entry_next(en_r);
        }
 
        bch2_key_resize(l.k, l.k->size + r.k->size);
index ead31f9e31aa0b1bbc540dfde36183afe71fc722..ba700810a4bee67223264c01a877011ef1a16676 100644 (file)
@@ -82,6 +82,14 @@ void bch2_reflink_v_to_text(struct printbuf *out, struct bch_fs *c,
        bch2_bkey_ptrs_to_text(out, c, k);
 }
 
+bool bch2_reflink_v_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r)
+{
+       struct bkey_s_reflink_v   l = bkey_s_to_reflink_v(_l);
+       struct bkey_s_c_reflink_v r = bkey_s_c_to_reflink_v(_r);
+
+       return l.v->refcount == r.v->refcount && bch2_extent_merge(c, _l, _r);
+}
+
 /* indirect inline data */
 
 const char *bch2_indirect_inline_data_invalid(const struct bch_fs *c,