From 84f535874b7cd5ae4603b10a27a59e2000bed6a9 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 (cherry picked from commit 2be4840afd4fc54c2ad06ccc2aac903e45bd37f5) Conflicts: src/librbd/deep_copy/ObjectCopyRequest.cc src/librbd/deep_copy/ObjectCopyRequest.h deep_copy::ObjectCopyRequest does not exist in luminous, fixed rbd_mirror::image_sync::ObjectCopyRequest instead --- src/librados/snap_set_diff.cc | 9 ++++++++- src/librados/snap_set_diff.h | 3 ++- src/librbd/api/DiffIterate.cc | 11 ++++++++--- .../image_sync/ObjectCopyRequest.cc | 19 ++++++++++++++++++- .../rbd_mirror/image_sync/ObjectCopyRequest.h | 1 + 5 files changed, 37 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 04b8ba450e191..1bd3a8fe5800d 100644 --- a/src/librbd/api/DiffIterate.cc +++ b/src/librbd/api/DiffIterate.cc @@ -131,17 +131,22 @@ private: 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/tools/rbd_mirror/image_sync/ObjectCopyRequest.cc b/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.cc index cc59030878ba3..533f175f9ff30 100644 --- a/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.cc +++ b/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.cc @@ -173,6 +173,13 @@ template void ObjectCopyRequest::handle_read_object(int r) { dout(20) << ": r=" << r << dendl; + auto snap_seq = m_snap_sync_ops.begin()->first.second; + if (r == -ENOENT && m_read_whole_object[snap_seq]) { + dout(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; @@ -413,9 +420,18 @@ void ObjectCopyRequest::compute_diffs() { uint64_t end_size; bool exists; librados::snap_t clone_end_snap_id; + bool read_whole_object; calc_snap_set_diff(cct, m_snap_set, start_remote_snap_id, end_remote_snap_id, &diff, &end_size, &exists, - &clone_end_snap_id); + &clone_end_snap_id, &read_whole_object); + + if (read_whole_object) { + dout(1) << ": need to read full object" << dendl; + diff.insert(0, m_remote_image_ctx->layout.object_size); + exists = true; + end_size = m_remote_image_ctx->layout.object_size; + clone_end_snap_id = end_remote_snap_id; + } dout(20) << ": " << "start_remote_snap=" << start_remote_snap_id << ", " @@ -455,6 +471,7 @@ void ObjectCopyRequest::compute_diffs() { // do not read past the sync point snapshot clone_end_snap_id = remote_sync_pont_snap_id; } + m_read_whole_object[clone_end_snap_id] = read_whole_object; // object write/zero, or truncate // NOTE: a single snapshot clone might represent multiple snapshots, but diff --git a/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.h b/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.h index 8430e7030c439..d52097dc6fbd4 100644 --- a/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.h +++ b/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.h @@ -120,6 +120,7 @@ private: bool m_retry_missing_read = false; librados::snap_set_t m_retry_snap_set; + std::map m_read_whole_object; SnapSyncOps m_snap_sync_ops; SnapObjectStates m_snap_object_states; -- 2.39.5