X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftools%2Frbd_mirror%2Fimage_sync%2FSnapshotCopyRequest.cc;fp=src%2Fceph%2Fsrc%2Ftools%2Frbd_mirror%2Fimage_sync%2FSnapshotCopyRequest.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=f5f0701d1134c1cb0ed346f93eacabaade27e006;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc b/src/ceph/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc deleted file mode 100644 index f5f0701..0000000 --- a/src/ceph/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc +++ /dev/null @@ -1,614 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "SnapshotCopyRequest.h" -#include "SnapshotCreateRequest.h" -#include "common/errno.h" -#include "common/WorkQueue.h" -#include "journal/Journaler.h" -#include "librbd/ExclusiveLock.h" -#include "librbd/Operations.h" -#include "librbd/Utils.h" -#include "librbd/journal/Types.h" - -#define dout_context g_ceph_context -#define dout_subsys ceph_subsys_rbd_mirror -#undef dout_prefix -#define dout_prefix *_dout << "rbd::mirror::image_sync::SnapshotCopyRequest: " \ - << this << " " << __func__ - -namespace rbd { -namespace mirror { -namespace image_sync { - -namespace { - -template -const std::string &get_snapshot_name(I *image_ctx, librados::snap_t snap_id) { - auto snap_it = std::find_if(image_ctx->snap_ids.begin(), - image_ctx->snap_ids.end(), - [snap_id]( - const std::pair< - std::pair, - librados::snap_t> &pair) { - return pair.second == snap_id; - }); - assert(snap_it != image_ctx->snap_ids.end()); - return snap_it->first.second; -} - -} // anonymous namespace - -using librbd::util::create_context_callback; -using librbd::util::unique_lock_name; - -template -SnapshotCopyRequest::SnapshotCopyRequest(I *local_image_ctx, - I *remote_image_ctx, - SnapMap *snap_map, - Journaler *journaler, - librbd::journal::MirrorPeerClientMeta *meta, - ContextWQ *work_queue, - Context *on_finish) - : BaseRequest("rbd::mirror::image_sync::SnapshotCopyRequest", - local_image_ctx->cct, on_finish), - m_local_image_ctx(local_image_ctx), m_remote_image_ctx(remote_image_ctx), - m_snap_map(snap_map), m_journaler(journaler), m_client_meta(meta), - m_work_queue(work_queue), m_snap_seqs(meta->snap_seqs), - m_lock(unique_lock_name("SnapshotCopyRequest::m_lock", this)) { - m_snap_map->clear(); - - // snap ids ordered from oldest to newest - m_remote_snap_ids.insert(remote_image_ctx->snaps.begin(), - remote_image_ctx->snaps.end()); - m_local_snap_ids.insert(local_image_ctx->snaps.begin(), - local_image_ctx->snaps.end()); -} - -template -void SnapshotCopyRequest::send() { - librbd::ParentSpec remote_parent_spec; - int r = validate_parent(m_remote_image_ctx, &remote_parent_spec); - if (r < 0) { - derr << ": remote image parent spec mismatch" << dendl; - error(r); - return; - } - - r = validate_parent(m_local_image_ctx, &m_local_parent_spec); - if (r < 0) { - derr << ": local image parent spec mismatch" << dendl; - error(r); - return; - } - - send_snap_unprotect(); -} - -template -void SnapshotCopyRequest::cancel() { - Mutex::Locker locker(m_lock); - - dout(20) << dendl; - m_canceled = true; -} - -template -void SnapshotCopyRequest::send_snap_unprotect() { - - SnapIdSet::iterator snap_id_it = m_local_snap_ids.begin(); - if (m_prev_snap_id != CEPH_NOSNAP) { - snap_id_it = m_local_snap_ids.upper_bound(m_prev_snap_id); - } - - for (; snap_id_it != m_local_snap_ids.end(); ++snap_id_it) { - librados::snap_t local_snap_id = *snap_id_it; - - m_local_image_ctx->snap_lock.get_read(); - - bool local_unprotected; - int r = m_local_image_ctx->is_snap_unprotected(local_snap_id, - &local_unprotected); - if (r < 0) { - derr << ": failed to retrieve local snap unprotect status: " - << cpp_strerror(r) << dendl; - m_local_image_ctx->snap_lock.put_read(); - finish(r); - return; - } - m_local_image_ctx->snap_lock.put_read(); - - if (local_unprotected) { - // snap is already unprotected -- check next snap - continue; - } - - // if local snapshot is protected and (1) it isn't in our mapping - // table, or (2) the remote snapshot isn't protected, unprotect it - auto snap_seq_it = std::find_if( - m_snap_seqs.begin(), m_snap_seqs.end(), - [local_snap_id](const SnapSeqs::value_type& pair) { - return pair.second == local_snap_id; - }); - - if (snap_seq_it != m_snap_seqs.end()) { - m_remote_image_ctx->snap_lock.get_read(); - bool remote_unprotected; - r = m_remote_image_ctx->is_snap_unprotected(snap_seq_it->first, - &remote_unprotected); - if (r < 0) { - derr << ": failed to retrieve remote snap unprotect status: " - << cpp_strerror(r) << dendl; - m_remote_image_ctx->snap_lock.put_read(); - finish(r); - return; - } - m_remote_image_ctx->snap_lock.put_read(); - - if (remote_unprotected) { - // remote is unprotected -- unprotect local snap - break; - } - } else { - // remote snapshot doesn't exist -- unprotect local snap - break; - } - } - - if (snap_id_it == m_local_snap_ids.end()) { - // no local snapshots to unprotect - m_prev_snap_id = CEPH_NOSNAP; - send_snap_remove(); - return; - } - - m_prev_snap_id = *snap_id_it; - m_snap_name = get_snapshot_name(m_local_image_ctx, m_prev_snap_id); - - dout(20) << ": " - << "snap_name=" << m_snap_name << ", " - << "snap_id=" << m_prev_snap_id << dendl; - - auto finish_op_ctx = start_local_op(); - if (finish_op_ctx == nullptr) { - derr << ": lost exclusive lock" << dendl; - finish(-EROFS); - return; - } - - auto ctx = new FunctionContext([this, finish_op_ctx](int r) { - handle_snap_unprotect(r); - finish_op_ctx->complete(0); - }); - RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); - m_local_image_ctx->operations->execute_snap_unprotect( - cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx); -} - -template -void SnapshotCopyRequest::handle_snap_unprotect(int r) { - dout(20) << ": r=" << r << dendl; - - if (r < 0) { - derr << ": failed to unprotect snapshot '" << m_snap_name << "': " - << cpp_strerror(r) << dendl; - finish(r); - return; - } - if (handle_cancellation()) - { - return; - } - - send_snap_unprotect(); -} - -template -void SnapshotCopyRequest::send_snap_remove() { - SnapIdSet::iterator snap_id_it = m_local_snap_ids.begin(); - if (m_prev_snap_id != CEPH_NOSNAP) { - snap_id_it = m_local_snap_ids.upper_bound(m_prev_snap_id); - } - - for (; snap_id_it != m_local_snap_ids.end(); ++snap_id_it) { - librados::snap_t local_snap_id = *snap_id_it; - - cls::rbd::SnapshotNamespace snap_namespace; - m_local_image_ctx->snap_lock.get_read(); - int r = m_local_image_ctx->get_snap_namespace(local_snap_id, - &snap_namespace); - m_local_image_ctx->snap_lock.put_read(); - if (r < 0) { - derr << ": failed to retrieve local snap namespace: " << m_snap_name - << dendl; - finish(r); - return; - } - - if (boost::get(&snap_namespace) == - nullptr) { - continue; - } - - // if the local snapshot isn't in our mapping table, remove it - auto snap_seq_it = std::find_if( - m_snap_seqs.begin(), m_snap_seqs.end(), - [local_snap_id](const SnapSeqs::value_type& pair) { - return pair.second == local_snap_id; - }); - - if (snap_seq_it == m_snap_seqs.end()) { - break; - } - } - - if (snap_id_it == m_local_snap_ids.end()) { - // no local snapshots to delete - m_prev_snap_id = CEPH_NOSNAP; - send_snap_create(); - return; - } - - m_prev_snap_id = *snap_id_it; - m_snap_name = get_snapshot_name(m_local_image_ctx, m_prev_snap_id); - - dout(20) << ": " - << "snap_name=" << m_snap_name << ", " - << "snap_id=" << m_prev_snap_id << dendl; - - auto finish_op_ctx = start_local_op(); - if (finish_op_ctx == nullptr) { - derr << ": lost exclusive lock" << dendl; - finish(-EROFS); - return; - } - - auto ctx = new FunctionContext([this, finish_op_ctx](int r) { - handle_snap_remove(r); - finish_op_ctx->complete(0); - }); - RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); - m_local_image_ctx->operations->execute_snap_remove( - cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx); -} - -template -void SnapshotCopyRequest::handle_snap_remove(int r) { - dout(20) << ": r=" << r << dendl; - - if (r < 0) { - derr << ": failed to remove snapshot '" << m_snap_name << "': " - << cpp_strerror(r) << dendl; - finish(r); - return; - } - if (handle_cancellation()) - { - return; - } - - send_snap_remove(); -} - -template -void SnapshotCopyRequest::send_snap_create() { - SnapIdSet::iterator snap_id_it = m_remote_snap_ids.begin(); - if (m_prev_snap_id != CEPH_NOSNAP) { - snap_id_it = m_remote_snap_ids.upper_bound(m_prev_snap_id); - } - - for (; snap_id_it != m_remote_snap_ids.end(); ++snap_id_it) { - librados::snap_t remote_snap_id = *snap_id_it; - - cls::rbd::SnapshotNamespace snap_namespace; - m_remote_image_ctx->snap_lock.get_read(); - int r = m_remote_image_ctx->get_snap_namespace(remote_snap_id, &snap_namespace); - m_remote_image_ctx->snap_lock.put_read(); - if (r < 0) { - derr << ": failed to retrieve remote snap namespace: " << m_snap_name - << dendl; - finish(r); - return; - } - - // if the remote snapshot isn't in our mapping table, create it - if (m_snap_seqs.find(remote_snap_id) == m_snap_seqs.end() && - boost::get(&snap_namespace) != nullptr) { - break; - } - } - - if (snap_id_it == m_remote_snap_ids.end()) { - // no remote snapshots to create - m_prev_snap_id = CEPH_NOSNAP; - send_snap_protect(); - return; - } - - m_prev_snap_id = *snap_id_it; - m_snap_name = get_snapshot_name(m_remote_image_ctx, m_prev_snap_id); - - m_remote_image_ctx->snap_lock.get_read(); - auto snap_info_it = m_remote_image_ctx->snap_info.find(m_prev_snap_id); - if (snap_info_it == m_remote_image_ctx->snap_info.end()) { - m_remote_image_ctx->snap_lock.put_read(); - derr << ": failed to retrieve remote snap info: " << m_snap_name - << dendl; - finish(-ENOENT); - return; - } - - uint64_t size = snap_info_it->second.size; - m_snap_namespace = snap_info_it->second.snap_namespace; - librbd::ParentSpec parent_spec; - uint64_t parent_overlap = 0; - if (snap_info_it->second.parent.spec.pool_id != -1) { - parent_spec = m_local_parent_spec; - parent_overlap = snap_info_it->second.parent.overlap; - } - m_remote_image_ctx->snap_lock.put_read(); - - - dout(20) << ": " - << "snap_name=" << m_snap_name << ", " - << "snap_id=" << m_prev_snap_id << ", " - << "size=" << size << ", " - << "parent_info=[" - << "pool_id=" << parent_spec.pool_id << ", " - << "image_id=" << parent_spec.image_id << ", " - << "snap_id=" << parent_spec.snap_id << ", " - << "overlap=" << parent_overlap << "]" << dendl; - - Context *finish_op_ctx = start_local_op(); - if (finish_op_ctx == nullptr) { - derr << ": lost exclusive lock" << dendl; - finish(-EROFS); - return; - } - - auto ctx = new FunctionContext([this, finish_op_ctx](int r) { - handle_snap_create(r); - finish_op_ctx->complete(0); - }); - SnapshotCreateRequest *req = SnapshotCreateRequest::create( - m_local_image_ctx, m_snap_name, m_snap_namespace, size, parent_spec, - parent_overlap, ctx); - req->send(); -} - -template -void SnapshotCopyRequest::handle_snap_create(int r) { - dout(20) << ": r=" << r << dendl; - - if (r < 0) { - derr << ": failed to create snapshot '" << m_snap_name << "': " - << cpp_strerror(r) << dendl; - finish(r); - return; - } - if (handle_cancellation()) - { - return; - } - - assert(m_prev_snap_id != CEPH_NOSNAP); - - auto snap_it = m_local_image_ctx->snap_ids.find({cls::rbd::UserSnapshotNamespace(), - m_snap_name}); - assert(snap_it != m_local_image_ctx->snap_ids.end()); - librados::snap_t local_snap_id = snap_it->second; - - dout(20) << ": mapping remote snap id " << m_prev_snap_id << " to " - << local_snap_id << dendl; - m_snap_seqs[m_prev_snap_id] = local_snap_id; - - send_snap_create(); -} - -template -void SnapshotCopyRequest::send_snap_protect() { - SnapIdSet::iterator snap_id_it = m_remote_snap_ids.begin(); - if (m_prev_snap_id != CEPH_NOSNAP) { - snap_id_it = m_remote_snap_ids.upper_bound(m_prev_snap_id); - } - - for (; snap_id_it != m_remote_snap_ids.end(); ++snap_id_it) { - librados::snap_t remote_snap_id = *snap_id_it; - - m_remote_image_ctx->snap_lock.get_read(); - - bool remote_protected; - int r = m_remote_image_ctx->is_snap_protected(remote_snap_id, - &remote_protected); - if (r < 0) { - derr << ": failed to retrieve remote snap protect status: " - << cpp_strerror(r) << dendl; - m_remote_image_ctx->snap_lock.put_read(); - finish(r); - return; - } - m_remote_image_ctx->snap_lock.put_read(); - - if (!remote_protected) { - // snap is not protected -- check next snap - continue; - } - - // if local snapshot is not protected, protect it - auto snap_seq_it = m_snap_seqs.find(remote_snap_id); - assert(snap_seq_it != m_snap_seqs.end()); - - m_local_image_ctx->snap_lock.get_read(); - bool local_protected; - r = m_local_image_ctx->is_snap_protected(snap_seq_it->second, - &local_protected); - if (r < 0) { - derr << ": failed to retrieve local snap protect status: " - << cpp_strerror(r) << dendl; - m_local_image_ctx->snap_lock.put_read(); - finish(r); - return; - } - m_local_image_ctx->snap_lock.put_read(); - - if (!local_protected) { - break; - } - } - - if (snap_id_it == m_remote_snap_ids.end()) { - // no local snapshots to protect - m_prev_snap_id = CEPH_NOSNAP; - send_update_client(); - return; - } - - m_prev_snap_id = *snap_id_it; - m_snap_name = get_snapshot_name(m_remote_image_ctx, m_prev_snap_id); - - dout(20) << ": " - << "snap_name=" << m_snap_name << ", " - << "snap_id=" << m_prev_snap_id << dendl; - - auto finish_op_ctx = start_local_op(); - if (finish_op_ctx == nullptr) { - derr << ": lost exclusive lock" << dendl; - finish(-EROFS); - return; - } - - auto ctx = new FunctionContext([this, finish_op_ctx](int r) { - handle_snap_protect(r); - finish_op_ctx->complete(0); - }); - RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); - m_local_image_ctx->operations->execute_snap_protect( - cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx); -} - -template -void SnapshotCopyRequest::handle_snap_protect(int r) { - dout(20) << ": r=" << r << dendl; - - if (r < 0) { - derr << ": failed to protect snapshot '" << m_snap_name << "': " - << cpp_strerror(r) << dendl; - finish(r); - return; - } - if (handle_cancellation()) - { - return; - } - - send_snap_protect(); -} - -template -void SnapshotCopyRequest::send_update_client() { - dout(20) << dendl; - - compute_snap_map(); - - librbd::journal::MirrorPeerClientMeta client_meta(*m_client_meta); - client_meta.snap_seqs = m_snap_seqs; - - librbd::journal::ClientData client_data(client_meta); - bufferlist data_bl; - ::encode(client_data, data_bl); - - Context *ctx = create_context_callback< - SnapshotCopyRequest, &SnapshotCopyRequest::handle_update_client>( - this); - m_journaler->update_client(data_bl, ctx); -} - -template -void SnapshotCopyRequest::handle_update_client(int r) { - dout(20) << ": r=" << r << dendl; - - if (r < 0) { - derr << ": failed to update client data: " << cpp_strerror(r) - << dendl; - finish(r); - return; - } - if (handle_cancellation()) - { - return; - } - - m_client_meta->snap_seqs = m_snap_seqs; - - finish(0); -} - -template -bool SnapshotCopyRequest::handle_cancellation() { - { - Mutex::Locker locker(m_lock); - if (!m_canceled) { - return false; - } - } - dout(10) << ": snapshot copy canceled" << dendl; - finish(-ECANCELED); - return true; -} - -template -void SnapshotCopyRequest::error(int r) { - dout(20) << ": r=" << r << dendl; - - m_work_queue->queue(new FunctionContext([this, r](int r1) { finish(r); })); -} - -template -void SnapshotCopyRequest::compute_snap_map() { - SnapIds local_snap_ids; - for (auto &pair : m_snap_seqs) { - local_snap_ids.reserve(1 + local_snap_ids.size()); - local_snap_ids.insert(local_snap_ids.begin(), pair.second); - m_snap_map->insert(std::make_pair(pair.first, local_snap_ids)); - } -} - -template -int SnapshotCopyRequest::validate_parent(I *image_ctx, - librbd::ParentSpec *spec) { - RWLock::RLocker owner_locker(image_ctx->owner_lock); - RWLock::RLocker snap_locker(image_ctx->snap_lock); - - // ensure remote image's parent specs are still consistent - *spec = image_ctx->parent_md.spec; - for (auto &snap_info_pair : image_ctx->snap_info) { - auto &parent_spec = snap_info_pair.second.parent.spec; - if (parent_spec.pool_id == -1) { - continue; - } else if (spec->pool_id == -1) { - *spec = parent_spec; - continue; - } - - if (*spec != parent_spec) { - return -EINVAL; - } - } - return 0; -} - -template -Context *SnapshotCopyRequest::start_local_op() { - RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); - if (m_local_image_ctx->exclusive_lock == nullptr) { - return nullptr; - } - return m_local_image_ctx->exclusive_lock->start_op(); -} - -} // namespace image_sync -} // namespace mirror -} // namespace rbd - -template class rbd::mirror::image_sync::SnapshotCopyRequest;