Skip to content

Commit

Permalink
os/bluestore: factor _do_clone_range out of _clone
Browse files Browse the repository at this point in the history
Signed-off-by: Sage Weil <sage@redhat.com>
  • Loading branch information
liewegas committed Sep 16, 2016
1 parent 71a40cf commit 78f0176
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 75 deletions.
189 changes: 115 additions & 74 deletions src/os/bluestore/BlueStore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<BlobRef> 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
Expand Down Expand Up @@ -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<BlobRef> 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,
Expand Down
6 changes: 5 additions & 1 deletion src/os/bluestore/BlueStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,6 @@ class BlueStore : public ObjectStore,
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;
Expand Down Expand Up @@ -1814,6 +1813,11 @@ class BlueStore : public ObjectStore,
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,
Expand Down

0 comments on commit 78f0176

Please sign in to comment.