diff options
author | Jason Dillaman <dillaman@redhat.com> | 2020-03-10 21:19:42 +0100 |
---|---|---|
committer | Jason Dillaman <dillaman@redhat.com> | 2020-03-10 22:21:48 +0100 |
commit | 2b3a46801d3921220c82d9ded54ad76da6db0b91 (patch) | |
tree | 38ae9d49b54333bd68313008fa7c45a0ff64d099 | |
parent | librbd: helper state machine for computing diffs between object-maps (diff) | |
download | ceph-2b3a46801d3921220c82d9ded54ad76da6db0b91.tar.xz ceph-2b3a46801d3921220c82d9ded54ad76da6db0b91.zip |
librbd: switch diff-iterate API to use new object-map diff helper
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
-rw-r--r-- | src/librbd/api/DiffIterate.cc | 140 |
1 files changed, 14 insertions, 126 deletions
diff --git a/src/librbd/api/DiffIterate.cc b/src/librbd/api/DiffIterate.cc index af61cd9e384..7e47c7ec3a8 100644 --- a/src/librbd/api/DiffIterate.cc +++ b/src/librbd/api/DiffIterate.cc @@ -10,6 +10,7 @@ #include "librbd/io/AioCompletion.h" #include "librbd/io/ImageDispatchSpec.h" #include "librbd/io/ImageRequestWQ.h" +#include "librbd/object_map/DiffRequest.h" #include "include/rados/librados.hpp" #include "include/interval_set.h" #include "common/errno.h" @@ -313,16 +314,19 @@ int DiffIterate<I>::execute() { int r; bool fast_diff_enabled = false; BitVector<2> object_diff_state; - { - std::shared_lock image_locker{m_image_ctx.image_lock}; - if (m_whole_object && (m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) { - r = diff_object_map(from_snap_id, end_snap_id, &object_diff_state); - if (r < 0) { - ldout(cct, 5) << "fast diff disabled" << dendl; - } else { - ldout(cct, 5) << "fast diff enabled" << dendl; - fast_diff_enabled = true; - } + if (m_whole_object) { + C_SaferCond ctx; + auto req = object_map::DiffRequest<I>::create(&m_image_ctx, from_snap_id, + end_snap_id, + &object_diff_state, &ctx); + req->send(); + + r = ctx.wait(); + if (r < 0) { + ldout(cct, 5) << "fast diff disabled" << dendl; + } else { + ldout(cct, 5) << "fast diff enabled" << dendl; + fast_diff_enabled = true; } } @@ -431,122 +435,6 @@ int DiffIterate<I>::execute() { return 0; } -template <typename I> -int DiffIterate<I>::diff_object_map(uint64_t from_snap_id, uint64_t to_snap_id, - BitVector<2>* object_diff_state) { - ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock)); - CephContext* cct = m_image_ctx.cct; - - bool diff_from_start = (from_snap_id == 0); - if (from_snap_id == 0) { - if (!m_image_ctx.snaps.empty()) { - from_snap_id = m_image_ctx.snaps.back(); - } else { - from_snap_id = CEPH_NOSNAP; - } - } - - object_diff_state->clear(); - uint64_t current_snap_id = from_snap_id; - uint64_t next_snap_id = to_snap_id; - BitVector<2> prev_object_map; - bool prev_object_map_valid = false; - while (true) { - uint64_t current_size = m_image_ctx.size; - if (current_snap_id != CEPH_NOSNAP) { - std::map<librados::snap_t, SnapInfo>::const_iterator snap_it = - m_image_ctx.snap_info.find(current_snap_id); - ceph_assert(snap_it != m_image_ctx.snap_info.end()); - current_size = snap_it->second.size; - - ++snap_it; - if (snap_it != m_image_ctx.snap_info.end()) { - next_snap_id = snap_it->first; - } else { - next_snap_id = CEPH_NOSNAP; - } - } - - uint64_t flags; - int r = m_image_ctx.get_flags(from_snap_id, &flags); - if (r < 0) { - lderr(cct) << "diff_object_map: failed to retrieve image flags" << dendl; - return r; - } - if ((flags & RBD_FLAG_FAST_DIFF_INVALID) != 0) { - ldout(cct, 1) << "diff_object_map: cannot perform fast diff on invalid " - << "object map" << dendl; - return -EINVAL; - } - - BitVector<2> object_map; - std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, - current_snap_id)); - r = cls_client::object_map_load(&m_image_ctx.md_ctx, oid, &object_map); - if (r < 0) { - lderr(cct) << "diff_object_map: failed to load object map " << oid - << dendl; - return r; - } - ldout(cct, 20) << "diff_object_map: loaded object map " << oid << dendl; - - uint64_t num_objs = Striper::get_num_objects(m_image_ctx.layout, - current_size); - if (object_map.size() < num_objs) { - ldout(cct, 1) << "diff_object_map: object map too small: " - << object_map.size() << " < " << num_objs << dendl; - return -EINVAL; - } - object_map.resize(num_objs); - object_diff_state->resize(object_map.size()); - - uint64_t overlap = std::min(object_map.size(), prev_object_map.size()); - auto it = object_map.begin(); - auto overlap_end_it = it + overlap; - auto pre_it = prev_object_map.begin(); - auto diff_it = object_diff_state->begin(); - uint64_t i = 0; - for (; it != overlap_end_it; ++it, ++pre_it, ++diff_it, ++i) { - ldout(cct, 20) << __func__ << ": object state: " << i << " " - << static_cast<uint32_t>(*pre_it) - << "->" << static_cast<uint32_t>(*it) << dendl; - if (*it == OBJECT_NONEXISTENT) { - if (*pre_it != OBJECT_NONEXISTENT) { - *diff_it = OBJECT_DIFF_STATE_HOLE; - } - } else if (*it == OBJECT_EXISTS || - (*pre_it != *it && - !(*pre_it == OBJECT_EXISTS && - *it == OBJECT_EXISTS_CLEAN))) { - *diff_it = OBJECT_DIFF_STATE_UPDATED; - } - } - ldout(cct, 20) << "diff_object_map: computed overlap diffs" << dendl; - auto end_it = object_map.end(); - if (object_map.size() > prev_object_map.size() && - (diff_from_start || prev_object_map_valid)) { - for (; it != end_it; ++it,++diff_it, ++i) { - ldout(cct, 20) << __func__ << ": object state: " << i << " " - << "->" << static_cast<uint32_t>(*it) << dendl; - if (*it == OBJECT_NONEXISTENT) { - *diff_it = OBJECT_DIFF_STATE_NONE; - } else { - *diff_it = OBJECT_DIFF_STATE_UPDATED; - } - } - } - ldout(cct, 20) << "diff_object_map: computed resize diffs" << dendl; - - if (current_snap_id == next_snap_id || next_snap_id > to_snap_id) { - break; - } - current_snap_id = next_snap_id; - prev_object_map = object_map; - prev_object_map_valid = true; - } - return 0; -} - } // namespace api } // namespace librbd |