Skip to content

Commit

Permalink
librbd: generalized copy deep function
Browse files Browse the repository at this point in the history
(mostly taken from rbd-mirror image sync)

Signed-off-by: Mykola Golub <mgolub@mirantis.com>
  • Loading branch information
Mykola Golub committed Aug 28, 2017
1 parent c9b6dfc commit e595c5b
Show file tree
Hide file tree
Showing 15 changed files with 3,000 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/librbd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@ set(librbd_internal_srcs
exclusive_lock/StandardPolicy.cc
image/CloneRequest.cc
image/CloseRequest.cc
image/CopyRequest.cc
image/CreateRequest.cc
image/OpenRequest.cc
image/RefreshParentRequest.cc
image/RefreshRequest.cc
image/RemoveRequest.cc
image/SetFlagsRequest.cc
image/SetSnapRequest.cc
image_copy/ImageCopyRequest.cc
image_copy/ObjectCopyRequest.cc
image_copy/SnapshotCopyRequest.cc
image_copy/SnapshotCreateRequest.cc
image_watcher/NotifyLockOwner.cc
io/AioCompletion.cc
io/AsyncOperation.cc
Expand Down
2 changes: 2 additions & 0 deletions src/librbd/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ struct SnapInfo {
}
};

typedef std::map<uint64_t, uint64_t> SnapSeqs;

} // namespace librbd

#endif // LIBRBD_TYPES_H
282 changes: 282 additions & 0 deletions src/librbd/image/CopyRequest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#include "CopyRequest.h"
#include "common/errno.h"
#include "librbd/ExclusiveLock.h"
#include "librbd/ImageCtx.h"
#include "librbd/ObjectMap.h"
#include "librbd/Utils.h"
#include "librbd/image_copy/ImageCopyRequest.h"
#include "librbd/image_copy/SnapshotCopyRequest.h"
#include "librbd/operation/SnapshotRemoveRequest.h"

#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd
#undef dout_prefix
#define dout_prefix *_dout << "librbd::image::CopyRequest: " \
<< this << " " << __func__ << ": "

namespace librbd {

namespace image {

using namespace librbd::image_copy;

using librbd::util::create_context_callback;
using librbd::util::unique_lock_name;

template <typename I>
CopyRequest<I>::CopyRequest(I *src_image_ctx, I *dst_image_ctx,
ContextWQ *work_queue, ProgressContext *prog_ctx,
Context *on_finish)
: RefCountedObject(dst_image_ctx->cct, 1), m_src_image_ctx(src_image_ctx),
m_dst_image_ctx(dst_image_ctx), m_cct(dst_image_ctx->cct),
m_work_queue(work_queue), m_prog_ctx(prog_ctx), m_on_finish(on_finish),
m_lock(unique_lock_name("CopyRequest::m_lock", this)) {
}

template <typename I>
CopyRequest<I>::~CopyRequest() {
assert(m_snapshot_copy_request == nullptr);
assert(m_image_copy_request == nullptr);
}

template <typename I>
void CopyRequest<I>::send() {
send_copy_snapshots();
}

template <typename I>
void CopyRequest<I>::cancel() {
Mutex::Locker locker(m_lock);

ldout(m_cct, 20) << dendl;

m_canceled = true;

if (m_snapshot_copy_request != nullptr) {
m_snapshot_copy_request->cancel();
}

if (m_image_copy_request != nullptr) {
m_image_copy_request->cancel();
}
}

template <typename I>
void CopyRequest<I>::send_copy_snapshots() {
m_lock.Lock();
if (m_canceled) {
m_lock.Unlock();
finish(-ECANCELED);
return;
}

ldout(m_cct, 20) << dendl;

Context *ctx = create_context_callback<
CopyRequest<I>, &CopyRequest<I>::handle_copy_snapshots>(this);
m_snapshot_copy_request = SnapshotCopyRequest<I>::create(
m_src_image_ctx, m_dst_image_ctx, m_work_queue, &m_snap_seqs, ctx);
m_snapshot_copy_request->get();
m_lock.Unlock();

m_snapshot_copy_request->send();
}

template <typename I>
void CopyRequest<I>::handle_copy_snapshots(int r) {
ldout(m_cct, 20) << "r=" << r << dendl;

{
Mutex::Locker locker(m_lock);
m_snapshot_copy_request->put();
m_snapshot_copy_request = nullptr;
if (r == 0 && m_canceled) {
r = -ECANCELED;
}
}

if (r == -ECANCELED) {
ldout(m_cct, 10) << "snapshot copy canceled" << dendl;
finish(r);
return;
} else if (r < 0) {
lderr(m_cct) << "failed to copy snapshot metadata: " << cpp_strerror(r) << dendl;
finish(r);
return;
}

send_copy_image();
}

template <typename I>
void CopyRequest<I>::send_copy_image() {
m_lock.Lock();
if (m_canceled) {
m_lock.Unlock();
finish(-ECANCELED);
return;
}

ldout(m_cct, 20) << dendl;

Context *ctx = create_context_callback<
CopyRequest<I>, &CopyRequest<I>::handle_copy_image>(this);
m_image_copy_request = ImageCopyRequest<I>::create(
m_src_image_ctx, m_dst_image_ctx, m_snap_seqs, m_prog_ctx, ctx);
m_image_copy_request->get();
m_lock.Unlock();

m_image_copy_request->send();
}

template <typename I>
void CopyRequest<I>::handle_copy_image(int r) {
ldout(m_cct, 20) << "r=" << r << dendl;

{
Mutex::Locker locker(m_lock);
m_image_copy_request->put();
m_image_copy_request = nullptr;
if (r == 0 && m_canceled) {
r = -ECANCELED;
}
}

if (r == -ECANCELED) {
ldout(m_cct, 10) << "image copy canceled" << dendl;
finish(r);
return;
} else if (r < 0) {
lderr(m_cct) << "failed to copy image: " << cpp_strerror(r) << dendl;
finish(r);
return;
}

send_copy_object_map();
}

template <typename I>
void CopyRequest<I>::send_copy_object_map() {
std::string copy_snap_name;
{
RWLock::RLocker snap_locker(m_src_image_ctx->snap_lock);
assert(m_src_image_ctx->snap_id != CEPH_NOSNAP);
copy_snap_name = m_src_image_ctx->snap_name;
auto snap_id_it = m_dst_image_ctx->snap_ids.find(
{cls::rbd::UserSnapshotNamespace(), copy_snap_name});
assert(snap_id_it != m_dst_image_ctx->snap_ids.end());
m_copy_snap_id = snap_id_it->second;
}

m_dst_image_ctx->owner_lock.get_read();
m_dst_image_ctx->snap_lock.get_read();
if (!m_dst_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP,
m_dst_image_ctx->snap_lock)) {
m_dst_image_ctx->snap_lock.put_read();
m_dst_image_ctx->owner_lock.put_read();
send_remove_copy_snapshot();
return;
}

assert(m_dst_image_ctx->object_map != nullptr);
assert(!copy_snap_name.empty());

ldout(m_cct, 20) << dendl;

Context *finish_op_ctx = nullptr;
if (m_dst_image_ctx->exclusive_lock != nullptr) {
finish_op_ctx = m_dst_image_ctx->exclusive_lock->start_op();
}
if (finish_op_ctx == nullptr) {
lderr(m_cct) << "lost exclusive lock" << dendl;
m_dst_image_ctx->snap_lock.put_read();
m_dst_image_ctx->owner_lock.put_read();
finish(-EROFS);
return;
}

// rollback the object map (copy snapshot object map to HEAD)
RWLock::WLocker object_map_locker(m_dst_image_ctx->object_map_lock);
auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
handle_copy_object_map(r);
finish_op_ctx->complete(0);
});
m_dst_image_ctx->object_map->rollback(m_copy_snap_id, ctx);
m_dst_image_ctx->snap_lock.put_read();
m_dst_image_ctx->owner_lock.put_read();
}

template <typename I>
void CopyRequest<I>::handle_copy_object_map(int r) {
ldout(m_cct, 20) << dendl;

assert(r == 0);
send_refresh_object_map();
}

template <typename I>
void CopyRequest<I>::send_refresh_object_map() {
ldout(m_cct, 20) << dendl;

Context *ctx = create_context_callback<
CopyRequest<I>, &CopyRequest<I>::handle_refresh_object_map>(this);
m_object_map = m_dst_image_ctx->create_object_map(CEPH_NOSNAP);
m_object_map->open(ctx);
}

template <typename I>
void CopyRequest<I>::handle_refresh_object_map(int r) {
ldout(m_cct, 20) << "r=" << r << dendl;

assert(r == 0);
{
RWLock::WLocker snap_locker(m_dst_image_ctx->snap_lock);
std::swap(m_dst_image_ctx->object_map, m_object_map);
}
delete m_object_map;

send_remove_copy_snapshot();
}

template <typename I>
void CopyRequest<I>::send_remove_copy_snapshot() {
ldout(m_cct, 20) << dendl;

RWLock::RLocker owner_lock(m_dst_image_ctx->owner_lock);

Context *ctx = create_context_callback<
CopyRequest<I>, &CopyRequest<I>::handle_remove_copy_snapshot>(this);

auto req = new operation::SnapshotRemoveRequest<I>(
*m_dst_image_ctx, ctx, cls::rbd::UserSnapshotNamespace(), "",
m_copy_snap_id);
req->send();
}

template <typename I>
void CopyRequest<I>::handle_remove_copy_snapshot(int r) {
ldout(m_cct, 20) << "r=" << r << dendl;

if (r < 0) {
lderr(m_cct) << "failed to remove copy snapshot: " << cpp_strerror(r)
<< dendl;
}

finish(r);
}

template <typename I>
void CopyRequest<I>::finish(int r) {
ldout(m_cct, 20) << "r=" << r << dendl;

m_on_finish->complete(r);
put();
}

} // namespace image
} // namespace librbd

template class librbd::image::CopyRequest<librbd::ImageCtx>;

0 comments on commit e595c5b

Please sign in to comment.