From 2be4840afd4fc54c2ad06ccc2aac903e45bd37f5 Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Mon, 19 Feb 2018 13:17:29 +0200 Subject: [PATCH] librados/snap_set_diff: don't assert on empty snapset Instead treat the diff as a full-object delta. Signed-off-by: Mykola Golub --- src/librados/snap_set_diff.cc | 9 ++++++++- src/librados/snap_set_diff.h | 3 ++- src/librbd/api/DiffIterate.cc | 11 ++++++++--- src/librbd/deep_copy/ObjectCopyRequest.cc | 17 ++++++++++++++++- src/librbd/deep_copy/ObjectCopyRequest.h | 1 + 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/librados/snap_set_diff.cc b/src/librados/snap_set_diff.cc index fcf42d080dabc..8b83b908e0ec2 100644 --- a/src/librados/snap_set_diff.cc +++ b/src/librados/snap_set_diff.cc @@ -17,7 +17,8 @@ void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set, librados::snap_t start, librados::snap_t end, interval_set *diff, uint64_t *end_size, - bool *end_exists, librados::snap_t *clone_end_snap_id) + bool *end_exists, librados::snap_t *clone_end_snap_id, + bool *whole_object) { ldout(cct, 10) << "calc_snap_set_diff start " << start << " end " << end << ", snap_set seq " << snap_set.seq << dendl; @@ -27,6 +28,7 @@ void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set, *end_size = 0; *end_exists = false; *clone_end_snap_id = 0; + *whole_object = false; for (vector::const_iterator r = snap_set.clones.begin(); r != snap_set.clones.end(); @@ -38,6 +40,11 @@ void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set, // head is valid starting from right after the last seen seq a = snap_set.seq + 1; b = librados::SNAP_HEAD; + } else if (r->snaps.empty()) { + ldout(cct, 1) << "clone " << r->cloneid + << ": empty snaps, return whole object" << dendl; + *whole_object = true; + return; } else { a = r->snaps[0]; // note: b might be < r->cloneid if a snap has been trimmed. diff --git a/src/librados/snap_set_diff.h b/src/librados/snap_set_diff.h index aba03ee317ec4..d09a368a4cc83 100644 --- a/src/librados/snap_set_diff.h +++ b/src/librados/snap_set_diff.h @@ -12,6 +12,7 @@ void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set, librados::snap_t start, librados::snap_t end, interval_set *diff, uint64_t *end_size, - bool *end_exists, librados::snap_t *clone_end_snap_id); + bool *end_exists, librados::snap_t *clone_end_snap_id, + bool *whole_object); #endif diff --git a/src/librbd/api/DiffIterate.cc b/src/librbd/api/DiffIterate.cc index 7b07634cfa69a..7a33c64b3ba3d 100644 --- a/src/librbd/api/DiffIterate.cc +++ b/src/librbd/api/DiffIterate.cc @@ -131,17 +131,22 @@ class C_DiffObject : public Context { uint64_t end_size; bool end_exists; librados::snap_t clone_end_snap_id; + bool whole_object; calc_snap_set_diff(cct, m_snap_set, m_diff_context.from_snap_id, m_diff_context.end_snap_id, &diff, &end_size, - &end_exists, &clone_end_snap_id); + &end_exists, &clone_end_snap_id, &whole_object); + if (whole_object) { + ldout(cct, 1) << "object " << m_oid << ": need to provide full object" + << dendl; + } ldout(cct, 20) << " diff " << diff << " end_exists=" << end_exists << dendl; - if (diff.empty()) { + if (diff.empty() && !whole_object) { if (m_diff_context.from_snap_id == 0 && !end_exists) { compute_parent_overlap(diffs); } return; - } else if (m_diff_context.whole_object) { + } else if (m_diff_context.whole_object || whole_object) { // provide the full object extents to the callback for (vector::iterator q = m_object_extents.begin(); q != m_object_extents.end(); ++q) { diff --git a/src/librbd/deep_copy/ObjectCopyRequest.cc b/src/librbd/deep_copy/ObjectCopyRequest.cc index 39ed63c3c3cec..b3424266976d9 100644 --- a/src/librbd/deep_copy/ObjectCopyRequest.cc +++ b/src/librbd/deep_copy/ObjectCopyRequest.cc @@ -190,6 +190,12 @@ template void ObjectCopyRequest::handle_read_object(int r) { ldout(m_cct, 20) << "r=" << r << dendl; + if (r == -ENOENT && m_read_whole_object) { + ldout(m_cct, 5) << "object missing when forced to read whole object" + << dendl; + r = 0; + } + if (r == -ENOENT) { m_retry_snap_set = m_snap_set; m_retry_missing_read = true; @@ -478,7 +484,16 @@ void ObjectCopyRequest::compute_read_ops() { librados::snap_t clone_end_snap_id; calc_snap_set_diff(m_cct, m_snap_set, start_src_snap_id, end_src_snap_id, &diff, &end_size, &exists, - &clone_end_snap_id); + &clone_end_snap_id, &m_read_whole_object); + + if (m_read_whole_object) { + ldout(m_cct, 1) << "need to read full object" << dendl; + diff.insert(0, m_src_image_ctx->layout.object_size); + exists = true; + end_size = m_src_image_ctx->layout.object_size; + clone_end_snap_id = end_src_snap_id; + } + if (!exists) { end_size = 0; } diff --git a/src/librbd/deep_copy/ObjectCopyRequest.h b/src/librbd/deep_copy/ObjectCopyRequest.h index e974b56d8f4e7..8e2b56fa57a7e 100644 --- a/src/librbd/deep_copy/ObjectCopyRequest.h +++ b/src/librbd/deep_copy/ObjectCopyRequest.h @@ -142,6 +142,7 @@ class ObjectCopyRequest { int m_snap_ret = 0; bool m_retry_missing_read = false; librados::snap_set_t m_retry_snap_set; + bool m_read_whole_object = false; std::map m_read_ops; std::list m_read_snaps;