+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "librbd/operation/RebuildObjectMapRequest.h"
-#include "common/dout.h"
-#include "common/errno.h"
-#include "librbd/AsyncObjectThrottle.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/ImageCtx.h"
-#include "librbd/internal.h"
-#include "librbd/ObjectMap.h"
-#include "librbd/operation/ResizeRequest.h"
-#include "librbd/operation/TrimRequest.h"
-#include "librbd/operation/ObjectMapIterate.h"
-#include "librbd/Utils.h"
-#include <boost/lambda/bind.hpp>
-#include <boost/lambda/construct.hpp>
-
-#define dout_subsys ceph_subsys_rbd
-#undef dout_prefix
-#define dout_prefix *_dout << "librbd::RebuildObjectMapRequest: "
-
-namespace librbd {
-namespace operation {
-
-template <typename I>
-void RebuildObjectMapRequest<I>::send() {
- send_resize_object_map();
-}
-
-template <typename I>
-bool RebuildObjectMapRequest<I>::should_complete(int r) {
- CephContext *cct = m_image_ctx.cct;
- ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl;
-
- RWLock::RLocker owner_lock(m_image_ctx.owner_lock);
- switch (m_state) {
- case STATE_RESIZE_OBJECT_MAP:
- ldout(cct, 5) << "RESIZE_OBJECT_MAP" << dendl;
- if (r == -ESTALE && !m_attempted_trim) {
- // objects are still flagged as in-use -- delete them
- m_attempted_trim = true;
- send_trim_image();
- return false;
- } else if (r == 0) {
- send_verify_objects();
- }
- break;
-
- case STATE_TRIM_IMAGE:
- ldout(cct, 5) << "TRIM_IMAGE" << dendl;
- if (r == 0) {
- send_resize_object_map();
- }
- break;
-
- case STATE_VERIFY_OBJECTS:
- ldout(cct, 5) << "VERIFY_OBJECTS" << dendl;
- if (r == 0) {
- send_save_object_map();
- }
- break;
-
- case STATE_SAVE_OBJECT_MAP:
- ldout(cct, 5) << "SAVE_OBJECT_MAP" << dendl;
- if (r == 0) {
- send_update_header();
- }
- break;
- case STATE_UPDATE_HEADER:
- ldout(cct, 5) << "UPDATE_HEADER" << dendl;
- if (r == 0) {
- return true;
- }
- break;
-
- default:
- assert(false);
- break;
- }
-
- if (r == -ERESTART) {
- ldout(cct, 5) << "rebuild object map operation interrupted" << dendl;
- return true;
- } else if (r < 0) {
- lderr(cct) << "rebuild object map encountered an error: " << cpp_strerror(r)
- << dendl;
- return true;
- }
- return false;
-}
-
-template <typename I>
-void RebuildObjectMapRequest<I>::send_resize_object_map() {
- assert(m_image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
-
- m_image_ctx.snap_lock.get_read();
- assert(m_image_ctx.object_map != nullptr);
-
- uint64_t size = get_image_size();
- uint64_t num_objects = Striper::get_num_objects(m_image_ctx.layout, size);
-
- if (m_image_ctx.object_map->size() == num_objects) {
- m_image_ctx.snap_lock.put_read();
- send_verify_objects();
- return;
- }
-
- ldout(cct, 5) << this << " send_resize_object_map" << dendl;
- m_state = STATE_RESIZE_OBJECT_MAP;
-
- // should have been canceled prior to releasing lock
- assert(m_image_ctx.exclusive_lock == nullptr ||
- m_image_ctx.exclusive_lock->is_lock_owner());
-
- m_image_ctx.object_map->aio_resize(size, OBJECT_NONEXISTENT,
- this->create_callback_context());
- m_image_ctx.snap_lock.put_read();
-}
-
-template <typename I>
-void RebuildObjectMapRequest<I>::send_trim_image() {
- CephContext *cct = m_image_ctx.cct;
-
- RWLock::RLocker l(m_image_ctx.owner_lock);
-
- // should have been canceled prior to releasing lock
- assert(m_image_ctx.exclusive_lock == nullptr ||
- m_image_ctx.exclusive_lock->is_lock_owner());
- ldout(cct, 5) << this << " send_trim_image" << dendl;
- m_state = STATE_TRIM_IMAGE;
-
- uint64_t new_size;
- uint64_t orig_size;
- {
- RWLock::RLocker l(m_image_ctx.snap_lock);
- assert(m_image_ctx.object_map != nullptr);
-
- new_size = get_image_size();
- orig_size = m_image_ctx.get_object_size() *
- m_image_ctx.object_map->size();
- }
- TrimRequest<I> *req = TrimRequest<I>::create(m_image_ctx,
- this->create_callback_context(),
- orig_size, new_size, m_prog_ctx);
- req->send();
-}
-
-template <typename I>
-bool update_object_map(I& image_ctx, uint64_t object_no, uint8_t current_state,
- uint8_t new_state) {
- CephContext *cct = image_ctx.cct;
- uint64_t snap_id = image_ctx.snap_id;
-
- uint8_t state = (*image_ctx.object_map)[object_no];
- if (state == OBJECT_EXISTS && new_state == OBJECT_NONEXISTENT &&
- snap_id == CEPH_NOSNAP) {
- // might be writing object to OSD concurrently
- new_state = state;
- }
-
- if (new_state != state) {
- ldout(cct, 15) << image_ctx.get_object_name(object_no)
- << " rebuild updating object map "
- << static_cast<uint32_t>(state) << "->"
- << static_cast<uint32_t>(new_state) << dendl;
- (*image_ctx.object_map)[object_no] = new_state;
- }
- return false;
-}
-
-template <typename I>
-void RebuildObjectMapRequest<I>::send_verify_objects() {
- assert(m_image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
-
- m_state = STATE_VERIFY_OBJECTS;
- ldout(cct, 5) << this << " send_verify_objects" << dendl;
-
- ObjectMapIterateRequest<I> *req =
- new ObjectMapIterateRequest<I>(m_image_ctx,
- this->create_callback_context(),
- m_prog_ctx, update_object_map);
-
- req->send();
-}
-
-template <typename I>
-void RebuildObjectMapRequest<I>::send_save_object_map() {
- assert(m_image_ctx.owner_lock.is_locked());
- CephContext *cct = m_image_ctx.cct;
-
- ldout(cct, 5) << this << " send_save_object_map" << dendl;
- m_state = STATE_SAVE_OBJECT_MAP;
-
- // should have been canceled prior to releasing lock
- assert(m_image_ctx.exclusive_lock == nullptr ||
- m_image_ctx.exclusive_lock->is_lock_owner());
-
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- assert(m_image_ctx.object_map != nullptr);
- m_image_ctx.object_map->aio_save(this->create_callback_context());
-}
-
-template <typename I>
-void RebuildObjectMapRequest<I>::send_update_header() {
- assert(m_image_ctx.owner_lock.is_locked());
-
- // should have been canceled prior to releasing lock
- assert(m_image_ctx.exclusive_lock == nullptr ||
- m_image_ctx.exclusive_lock->is_lock_owner());
-
- ldout(m_image_ctx.cct, 5) << this << " send_update_header" << dendl;
- m_state = STATE_UPDATE_HEADER;
-
- librados::ObjectWriteOperation op;
-
- uint64_t flags = RBD_FLAG_OBJECT_MAP_INVALID | RBD_FLAG_FAST_DIFF_INVALID;
- cls_client::set_flags(&op, m_image_ctx.snap_id, 0, flags);
-
- librados::AioCompletion *comp = this->create_callback_completion();
- int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op);
- assert(r == 0);
- comp->release();
-
- RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
- m_image_ctx.update_flags(m_image_ctx.snap_id, flags, false);
-}
-
-template <typename I>
-uint64_t RebuildObjectMapRequest<I>::get_image_size() const {
- assert(m_image_ctx.snap_lock.is_locked());
- if (m_image_ctx.snap_id == CEPH_NOSNAP) {
- if (!m_image_ctx.resize_reqs.empty()) {
- return m_image_ctx.resize_reqs.front()->get_image_size();
- } else {
- return m_image_ctx.size;
- }
- }
- return m_image_ctx.get_image_size(m_image_ctx.snap_id);
-}
-
-} // namespace operation
-} // namespace librbd
-
-template class librbd::operation::RebuildObjectMapRequest<librbd::ImageCtx>;