From 2e6948be1f620cbb9c3313a1d15bfd96dd361e95 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 7 Sep 2021 16:56:14 -0500 Subject: [PATCH] os/bluestore: duplicate zone refs when cloning When we clone an object, add zone refs pointing to the new object for any relevant extents. This is only half of the solution; we will want to make sure the cleaner is clever enough to keep shared blobs shared when they are relocated. Signed-off-by: Sage Weil --- src/os/bluestore/BlueStore.cc | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index f1269c757b5..3744a3b9a1e 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -15781,6 +15781,38 @@ int BlueStore::_do_clone_range( _dump_onode<30>(cct, *newo); oldo->extent_map.dup(this, txc, c, oldo, newo, srcoff, length, dstoff); + +#ifdef HAVE_LIBZBD + if (bdev->is_smr()) { + // duplicate the refs for the shared region. + Extent dummy(dstoff); + for (auto e = newo->extent_map.extent_map.lower_bound(dummy); + e != newo->extent_map.extent_map.end(); + ++e) { + if (e->logical_offset >= dstoff + length) { + break; + } + for (auto& ex : e->blob->get_blob().get_extents()) { + // note that we may introduce a new extent reference that is + // earlier than the first zone ref. we allow this since it is + // a lot of work to avoid and has marginal impact on cleaning + // performance. + if (!ex.is_valid()) { + continue; + } + uint32_t zone = ex.offset / zone_size; + if (!newo->onode.zone_offset_refs.count(zone)) { + uint64_t zoff = ex.offset % zone_size; + dout(20) << __func__ << " add ref zone 0x" << std::hex << zone + << " offset 0x" << zoff << std::dec + << " -> " << newo->oid << dendl; + txc->note_write_zone_offset(newo, zone, zoff); + } + } + } + } +#endif + _dump_onode<30>(cct, *oldo); _dump_onode<30>(cct, *newo); return 0; -- 2.39.5