// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #include "SetHeadRequest.h" #include "SnapshotCreateRequest.h" #include "common/errno.h" #include "cls/rbd/cls_rbd_client.h" #include "cls/rbd/cls_rbd_types.h" #include "librbd/ExclusiveLock.h" #include "librbd/ObjectMap.h" #include "librbd/Operations.h" #include "librbd/Utils.h" #include "osdc/Striper.h" #define dout_subsys ceph_subsys_rbd #undef dout_prefix #define dout_prefix *_dout << "librbd::deep_copy::SnapshotCreateRequest: " \ << this << " " << __func__ << ": " namespace librbd { namespace deep_copy { using librbd::util::create_context_callback; using librbd::util::create_rados_callback; template SnapshotCreateRequest::SnapshotCreateRequest( I *dst_image_ctx, const std::string &snap_name, const cls::rbd::SnapshotNamespace &snap_namespace, uint64_t size, const cls::rbd::ParentImageSpec &spec, uint64_t parent_overlap, Context *on_finish) : m_dst_image_ctx(dst_image_ctx), m_snap_name(snap_name), m_snap_namespace(snap_namespace), m_size(size), m_parent_spec(spec), m_parent_overlap(parent_overlap), m_on_finish(on_finish), m_cct(dst_image_ctx->cct) { } template void SnapshotCreateRequest::send() { send_set_head(); } template void SnapshotCreateRequest::send_set_head() { ldout(m_cct, 20) << dendl; auto ctx = create_context_callback< SnapshotCreateRequest, &SnapshotCreateRequest::handle_set_head>(this); auto req = SetHeadRequest::create(m_dst_image_ctx, m_size, m_parent_spec, m_parent_overlap, ctx); req->send(); } template void SnapshotCreateRequest::handle_set_head(int r) { ldout(m_cct, 20) << "r=" << r << dendl; if (r < 0) { lderr(m_cct) << "failed to set head: " << cpp_strerror(r) << dendl; finish(r); return; } send_create_snap(); } template void SnapshotCreateRequest::send_create_snap() { ldout(m_cct, 20) << "snap_name=" << m_snap_name << dendl; int r; auto finish_op_ctx = start_lock_op(&r); if (finish_op_ctx == nullptr) { lderr(m_cct) << "lost exclusive lock" << dendl; finish(r); return; } auto ctx = new LambdaContext([this, finish_op_ctx](int r) { handle_create_snap(r); finish_op_ctx->complete(0); }); uint64_t flags = SNAP_CREATE_FLAG_SKIP_OBJECT_MAP | SNAP_CREATE_FLAG_SKIP_NOTIFY_QUIESCE; std::shared_lock owner_locker{m_dst_image_ctx->owner_lock}; m_dst_image_ctx->operations->execute_snap_create( m_snap_namespace, m_snap_name.c_str(), ctx, 0U, flags, m_prog_ctx); } template void SnapshotCreateRequest::handle_create_snap(int r) { ldout(m_cct, 20) << "r=" << r << dendl; if (r < 0) { lderr(m_cct) << "failed to create snapshot '" << m_snap_name << "': " << cpp_strerror(r) << dendl; finish(r); return; } send_create_object_map(); } template void SnapshotCreateRequest::send_create_object_map() { if (!m_dst_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP)) { finish(0); return; } m_dst_image_ctx->image_lock.lock_shared(); auto snap_it = m_dst_image_ctx->snap_ids.find( {cls::rbd::UserSnapshotNamespace(), m_snap_name}); if (snap_it == m_dst_image_ctx->snap_ids.end()) { lderr(m_cct) << "failed to locate snap: " << m_snap_name << dendl; m_dst_image_ctx->image_lock.unlock_shared(); finish(-ENOENT); return; } librados::snap_t local_snap_id = snap_it->second; m_dst_image_ctx->image_lock.unlock_shared(); std::string object_map_oid(librbd::ObjectMap<>::object_map_name( m_dst_image_ctx->id, local_snap_id)); uint64_t object_count = Striper::get_num_objects(m_dst_image_ctx->layout, m_size); ldout(m_cct, 20) << "object_map_oid=" << object_map_oid << ", " << "object_count=" << object_count << dendl; // initialize an empty object map of the correct size (object sync // will populate the object map) librados::ObjectWriteOperation op; librbd::cls_client::object_map_resize(&op, object_count, OBJECT_NONEXISTENT); int r; auto finish_op_ctx = start_lock_op(&r); if (finish_op_ctx == nullptr) { lderr(m_cct) << "lost exclusive lock" << dendl; finish(r); return; } auto ctx = new LambdaContext([this, finish_op_ctx](int r) { handle_create_object_map(r); finish_op_ctx->complete(0); }); librados::AioCompletion *comp = create_rados_callback(ctx); r = m_dst_image_ctx->md_ctx.aio_operate(object_map_oid, comp, &op); ceph_assert(r == 0); comp->release(); } template void SnapshotCreateRequest::handle_create_object_map(int r) { ldout(m_cct, 20) << "r=" << r << dendl; if (r < 0) { lderr(m_cct) << "failed to create object map: " << cpp_strerror(r) << dendl; finish(r); return; } finish(0); } template Context *SnapshotCreateRequest::start_lock_op(int* r) { std::shared_lock owner_locker{m_dst_image_ctx->owner_lock}; if (m_dst_image_ctx->exclusive_lock == nullptr) { return new LambdaContext([](int r) {}); } return m_dst_image_ctx->exclusive_lock->start_op(r); } template void SnapshotCreateRequest::finish(int r) { ldout(m_cct, 20) << "r=" << r << dendl; m_on_finish->complete(r); delete this; } } // namespace deep_copy } // namespace librbd template class librbd::deep_copy::SnapshotCreateRequest;