From 78f0176f93b5cb5b839ff4e56b3f99e1d41dc735 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 16 Sep 2016 10:15:12 -0400 Subject: [PATCH] os/bluestore: factor _do_clone_range out of _clone Signed-off-by: Sage Weil --- src/os/bluestore/BlueStore.cc | 189 +++++++++++++++++++++------------- src/os/bluestore/BlueStore.h | 6 +- 2 files changed, 120 insertions(+), 75 deletions(-) diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 3bdee77f47d85..2d55127f55c0a 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -7957,99 +7957,28 @@ int BlueStore::_clone(TransContext *txc, << " and " << newo->oid << dendl; return -EINVAL; } - oldo->extent_map.fault_range(db, 0, oldo->onode.size); - _dump_onode(oldo); - - newo->extent_map.fault_range(db, 0, newo->onode.size); bufferlist bl; newo->exists = true; _assign_nid(txc, newo); - // data + // clone data oldo->flush(); - r = _do_truncate(txc, c, newo, 0); if (r < 0) goto out; - if (g_conf->bluestore_clone_cow) { - // hmm, this could go into an ExtentMap::dup() method. - vector id_to_blob(oldo->extent_map.extent_map.size()); - for (auto &e : oldo->extent_map.extent_map) { - e.blob->last_encoded_id = -1; - } - int n = 0; - bool dirtied_oldo = false; - for (auto &e : oldo->extent_map.extent_map) { - BlobRef cb; // clone blob - if (e.blob->last_encoded_id >= 0) { - // blob is already duped - cb = id_to_blob[e.blob->last_encoded_id]; - } else { - // we need to dup the blob. - // make sure it is shared - const bluestore_blob_t& blob = e.blob->get_blob(); - if (!blob.is_shared()) { - e.blob->dirty_blob().sbid = _assign_blobid(txc); - c->make_blob_shared(e.blob); - dirtied_oldo = true; // fixme: overkill - } else if (!e.blob->shared_blob->loaded) { - c->load_shared_blob(e.blob->shared_blob); - } - cb = new Blob; - e.blob->last_encoded_id = n; - id_to_blob[n] = cb; - e.blob->dup(*cb); - if (cb->id >= 0) { - newo->extent_map.spanning_blob_map.insert(*cb); - cb->get(); - } - // bump the extent refs on the copied blob's extents - for (auto p : blob.extents) { - if (p.is_valid()) { - e.blob->shared_blob->shared_blob.ref_map.get(p.offset, p.length); - } - } - txc->write_shared_blob(e.blob->shared_blob); - // ugly: duplicate deferred csum work, if any. - for (auto& dc : txc->deferred_csum) { - if (dc.blob == e.blob) { - dout(20) << __func__ << " duplicating deferred csum for blob " - << *e.blob << dendl; - txc->add_deferred_csum(cb, dc.b_off, dc.data); - } - } - } - // dup extent - newo->extent_map.add(e.logical_offset, e.blob_offset, e.length, cb); - txc->statfs_delta.stored() += e.length; - if (e.blob->get_blob().is_compressed()) { - txc->statfs_delta.compressed_original() -= e.length; - } - ++n; - } - if (dirtied_oldo) { - oldo->extent_map.dirty_range(txc->t, 0, oldo->onode.size); // overkill - txc->write_onode(oldo); - } - newo->onode.size = oldo->onode.size; - newo->extent_map.dirty_range(txc->t, 0, newo->onode.size); - txc->write_onode(newo); - _dump_onode(oldo); - _dump_onode(newo); + _do_clone_range(txc, c, oldo, newo, 0, oldo->onode.size, 0); } else { - // read + write r = _do_read(c.get(), oldo, 0, oldo->onode.size, bl, 0); if (r < 0) goto out; - r = _do_write(txc, c, newo, 0, oldo->onode.size, bl, 0); if (r < 0) goto out; } - // attrs + // clone attrs newo->onode.attrs = oldo->onode.attrs; // clone omap @@ -8091,6 +8020,118 @@ int BlueStore::_clone(TransContext *txc, return r; } +int BlueStore::_do_clone_range( + TransContext *txc, + CollectionRef& c, + OnodeRef& oldo, + OnodeRef& newo, + uint64_t srcoff, uint64_t length, uint64_t dstoff) +{ + dout(15) << __func__ << " " << c->cid << " " << oldo->oid << " -> " + << newo->oid + << " 0x" << std::hex << srcoff << "~" << length << " -> " + << " 0x" << dstoff << "~" << length << std::dec << dendl; + oldo->extent_map.fault_range(db, srcoff, length); + newo->extent_map.fault_range(db, dstoff, length); + _dump_onode(oldo); + _dump_onode(newo); + + // hmm, this could go into an ExtentMap::dup() method. + vector id_to_blob(oldo->extent_map.extent_map.size()); + for (auto &e : oldo->extent_map.extent_map) { + e.blob->last_encoded_id = -1; + } + int n = 0; + bool dirtied_oldo = false; + for (auto ep = oldo->extent_map.seek_lextent(srcoff); + ep != oldo->extent_map.extent_map.end(); + ++ep) { + auto& e = *ep; + if (e.logical_offset >= srcoff + length) { + break; + } + dout(20) << __func__ << " src " << e << dendl; + BlobRef cb; + if (e.blob->last_encoded_id >= 0) { + // blob is already duped + cb = id_to_blob[e.blob->last_encoded_id]; + } else { + // dup the blob + const bluestore_blob_t& blob = e.blob->get_blob(); + // make sure it is shared + if (!blob.is_shared()) { + e.blob->dirty_blob().sbid = _assign_blobid(txc); + c->make_blob_shared(e.blob); + dirtied_oldo = true; // fixme: overkill + } else if (!e.blob->shared_blob->loaded) { + c->load_shared_blob(e.blob->shared_blob); + } + cb = new Blob; + e.blob->last_encoded_id = n; + id_to_blob[n] = cb; + e.blob->dup(*cb); + if (cb->id >= 0) { + newo->extent_map.spanning_blob_map.insert(*cb); + cb->get(); + } + // bump the extent refs on the copied blob's extents + for (auto p : blob.extents) { + if (p.is_valid()) { + e.blob->shared_blob->shared_blob.ref_map.get(p.offset, p.length); + } + } + txc->write_shared_blob(e.blob->shared_blob); + // ugly: duplicate deferred csum work, if any. + for (auto& dc : txc->deferred_csum) { + if (dc.blob == e.blob) { + dout(20) << __func__ << " duplicating deferred csum for blob " + << *e.blob << dendl; + txc->add_deferred_csum(cb, dc.b_off, dc.data); + } + } + dout(20) << __func__ << " new " << *cb << dendl; + } + // dup extent + int skip_front, skip_back; + if (e.logical_offset < srcoff) { + skip_front = srcoff - e.logical_offset; + } else { + skip_front = 0; + } + if (e.logical_offset + e.length > srcoff + length) { + skip_back = e.logical_offset + e.length - (srcoff + length); + } else { + skip_back = 0; + } + Extent *ne = new Extent(e.logical_offset + skip_front + dstoff - srcoff, + e.blob_offset + skip_front, + e.length - skip_front - skip_back, cb); + newo->extent_map.extent_map.insert(*ne); + ne->blob->ref_map.get(ne->blob_offset, ne->length); + // fixme: we may leave parts of new blob unreferenced that could + // be freed (relative to the shared_blob). + txc->statfs_delta.stored() += ne->length; + if (e.blob->get_blob().is_compressed()) { + txc->statfs_delta.compressed_original() -= ne->length; + } + dout(20) << __func__ << " dst " << *ne << dendl; + ++n; + } + if (dirtied_oldo) { + oldo->extent_map.dirty_range(txc->t, srcoff, length); // overkill + txc->write_onode(oldo); + } + txc->write_onode(newo); + + if (dstoff + length > newo->onode.size) { + newo->onode.size = dstoff + length; + } + newo->extent_map.dirty_range(txc->t, dstoff, length); + _dump_onode(oldo); + _dump_onode(newo); + return 0; +} + int BlueStore::_clone_range(TransContext *txc, CollectionRef& c, OnodeRef& oldo, diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index c90f4d3314d95..b02cd0e93b5b9 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -426,7 +426,6 @@ public: void dup(Blob& o) { o.id = id; o.shared_blob = shared_blob; - o.ref_map = ref_map; o.blob = blob; o.dirty = dirty; o.blob_bl = blob_bl; @@ -1814,6 +1813,11 @@ private: uint64_t expected_object_size, uint64_t expected_write_size, uint32_t flags); + int _do_clone_range(TransContext *txc, + CollectionRef& c, + OnodeRef& oldo, + OnodeRef& newo, + uint64_t srcoff, uint64_t length, uint64_t dstoff); int _clone(TransContext *txc, CollectionRef& c, OnodeRef& oldo, -- 2.39.5