X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Flibrbd%2Fimage%2FRemoveRequest.cc;fp=src%2Fceph%2Fsrc%2Flibrbd%2Fimage%2FRemoveRequest.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=5782702d78f926640edc68b57e7088764e181e16;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/librbd/image/RemoveRequest.cc b/src/ceph/src/librbd/image/RemoveRequest.cc deleted file mode 100644 index 5782702..0000000 --- a/src/ceph/src/librbd/image/RemoveRequest.cc +++ /dev/null @@ -1,810 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "common/dout.h" -#include "common/errno.h" -#include "librbd/internal.h" -#include "librbd/ImageState.h" -#include "librbd/Journal.h" -#include "librbd/ObjectMap.h" -#include "librbd/ExclusiveLock.h" -#include "librbd/MirroringWatcher.h" -#include "librbd/journal/RemoveRequest.h" -#include "librbd/image/RemoveRequest.h" -#include "librbd/operation/TrimRequest.h" -#include "librbd/mirror/DisableRequest.h" - -#define dout_subsys ceph_subsys_rbd -#undef dout_prefix -#define dout_prefix *_dout << "librbd::image::RemoveRequest: " << this << " " \ - << __func__ << ": " - -namespace librbd { -namespace image { - -using librados::IoCtx; -using util::create_context_callback; -using util::create_async_context_callback; -using util::create_rados_callback; - -template -RemoveRequest::RemoveRequest(IoCtx &ioctx, const std::string &image_name, - const std::string &image_id, bool force, - bool from_trash_remove, - ProgressContext &prog_ctx, - ContextWQ *op_work_queue, Context *on_finish) - : m_ioctx(ioctx), m_image_name(image_name), m_image_id(image_id), - m_force(force), m_from_trash_remove(from_trash_remove), - m_prog_ctx(prog_ctx), m_op_work_queue(op_work_queue), - m_on_finish(on_finish) { - m_cct = reinterpret_cast(m_ioctx.cct()); - - m_image_ctx = I::create((m_image_id.empty() ? m_image_name : std::string()), - m_image_id, nullptr, m_ioctx, false); -} - -template -void RemoveRequest::send() { - ldout(m_cct, 20) << dendl; - - open_image(); -} - -template -void RemoveRequest::open_image() { - ldout(m_cct, 20) << dendl; - - using klass = RemoveRequest; - Context *ctx = create_context_callback( - this); - - m_image_ctx->state->open(true, ctx); -} - -template -void RemoveRequest::handle_open_image(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0) { - m_image_ctx->destroy(); - m_image_ctx = nullptr; - - if (r != -ENOENT) { - lderr(m_cct) << "error opening image: " << cpp_strerror(r) << dendl; - finish(r); - return; - } - - remove_image(); - return; - } - - m_image_id = m_image_ctx->id; - m_image_name = m_image_ctx->name; - m_header_oid = m_image_ctx->header_oid; - m_old_format = m_image_ctx->old_format; - m_unknown_format = false; - - check_exclusive_lock(); -} - -template -void RemoveRequest::check_exclusive_lock() { - ldout(m_cct, 20) << dendl; - - if (m_image_ctx->exclusive_lock == nullptr) { - validate_image_removal(); - } else { - acquire_exclusive_lock(); - } -} - -template -void RemoveRequest::acquire_exclusive_lock() { - ldout(m_cct, 20) << dendl; - - using klass = RemoveRequest; - if (m_force) { - Context *ctx = create_context_callback< - klass, &klass::handle_exclusive_lock_force>(this); - m_exclusive_lock = m_image_ctx->exclusive_lock; - m_exclusive_lock->shut_down(ctx); - } else { - Context *ctx = create_context_callback< - klass, &klass::handle_exclusive_lock>(this); - RWLock::WLocker owner_lock(m_image_ctx->owner_lock); - m_image_ctx->exclusive_lock->try_acquire_lock(ctx); - } -} - -template -void RemoveRequest::handle_exclusive_lock_force(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - delete m_exclusive_lock; - m_exclusive_lock = nullptr; - - if (r < 0) { - lderr(m_cct) << "error shutting down exclusive lock: " - << cpp_strerror(r) << dendl; - send_close_image(r); - return; - } - - assert(m_image_ctx->exclusive_lock == nullptr); - validate_image_removal(); -} - -template -void RemoveRequest::handle_exclusive_lock(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 || !m_image_ctx->exclusive_lock->is_lock_owner()) { - lderr(m_cct) << "cannot obtain exclusive lock - not removing" << dendl; - send_close_image(-EBUSY); - return; - } - - validate_image_removal(); -} - -template -void RemoveRequest::validate_image_removal() { - ldout(m_cct, 20) << dendl; - - check_image_snaps(); -} - -template -void RemoveRequest::check_image_snaps() { - ldout(m_cct, 20) << dendl; - - if (m_image_ctx->snaps.size()) { - lderr(m_cct) << "image has snapshots - not removing" << dendl; - send_close_image(-ENOTEMPTY); - return; - } - - list_image_watchers(); -} - -template -void RemoveRequest::list_image_watchers() { - ldout(m_cct, 20) << dendl; - - librados::ObjectReadOperation op; - op.list_watchers(&m_watchers, &m_ret_val); - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - - int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion, - &op, &m_out_bl); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_list_image_watchers(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r == 0 && m_ret_val < 0) { - r = m_ret_val; - } - if (r < 0) { - lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r) - << dendl; - send_close_image(r); - return; - } - - get_mirror_image(); -} - -template -void RemoveRequest::get_mirror_image() { - ldout(m_cct, 20) << dendl; - if ((m_watchers.empty()) || - ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0)) { - check_image_watchers(); - return; - } - - librados::ObjectReadOperation op; - cls_client::mirror_image_get_start(&op, m_image_id); - - using klass = RemoveRequest; - librados::AioCompletion *comp = - create_rados_callback(this); - m_out_bl.clear(); - int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl); - assert(r == 0); - comp->release(); -} - -template -void RemoveRequest::handle_get_mirror_image(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r == -ENOENT || r == -EOPNOTSUPP) { - check_image_watchers(); - return; - } else if (r < 0) { - ldout(m_cct, 5) << "error retrieving mirror image: " << cpp_strerror(r) - << dendl; - } - - list_mirror_watchers(); -} - -template -void RemoveRequest::list_mirror_watchers() { - ldout(m_cct, 20) << dendl; - - librados::ObjectReadOperation op; - op.list_watchers(&m_mirror_watchers, &m_ret_val); - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - m_out_bl.clear(); - int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, rados_completion, - &op, &m_out_bl); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_list_mirror_watchers(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r == 0 && m_ret_val < 0) { - r = m_ret_val; - } - if (r < 0 && r != -ENOENT) { - ldout(m_cct, 5) << "error listing mirror watchers: " << cpp_strerror(r) - << dendl; - } - - for (auto &watcher : m_mirror_watchers) { - m_watchers.remove_if([watcher] (obj_watch_t &w) { - return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0); - }); - } - - check_image_watchers(); -} - -template -void RemoveRequest::check_image_watchers() { - if (m_watchers.size() > 1) { - lderr(m_cct) << "image has watchers - not removing" << dendl; - send_close_image(-EBUSY); - return; - } - - check_group(); -} - -template -void RemoveRequest::check_group() { - ldout(m_cct, 20) << dendl; - - librados::ObjectReadOperation op; - librbd::cls_client::image_get_group_start(&op); - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = create_rados_callback< - klass, &klass::handle_check_group>(this); - m_out_bl.clear(); - int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion, &op, - &m_out_bl); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_check_group(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - cls::rbd::GroupSpec s; - if (r == 0) { - bufferlist::iterator it = m_out_bl.begin(); - r = librbd::cls_client::image_get_group_finish(&it, &s); - } - if (r < 0 && r != -EOPNOTSUPP) { - lderr(m_cct) << "error fetching group for image: " - << cpp_strerror(r) << dendl; - send_close_image(r); - return; - } - - if (s.is_valid()) { - lderr(m_cct) << "image is in a group - not removing" << dendl; - send_close_image(-EMLINK); - return; - } - - trim_image(); -} - -template -void RemoveRequest::trim_image() { - ldout(m_cct, 20) << dendl; - - using klass = RemoveRequest; - Context *ctx = create_async_context_callback( - *m_image_ctx, create_context_callback< - klass, &klass::handle_trim_image>(this)); - - RWLock::RLocker owner_lock(m_image_ctx->owner_lock); - auto req = librbd::operation::TrimRequest::create( - *m_image_ctx, ctx, m_image_ctx->size, 0, m_prog_ctx); - req->send(); -} - -template -void RemoveRequest::handle_trim_image(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0) { - lderr(m_cct) << "warning: failed to remove some object(s): " - << cpp_strerror(r) << dendl; - } - - if (m_old_format) { - send_close_image(r); - return; - } - - remove_child(); -} - -template -void RemoveRequest::remove_child() { - ldout(m_cct, 20) << dendl; - - m_image_ctx->parent_lock.get_read(); - ParentInfo parent_info = m_image_ctx->parent_md; - m_image_ctx->parent_lock.put_read(); - - librados::ObjectWriteOperation op; - librbd::cls_client::remove_child(&op, parent_info.spec, m_image_id); - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - int r = m_image_ctx->md_ctx.aio_operate(RBD_CHILDREN, rados_completion, &op); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_remove_child(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r == -ENOENT) { - r = 0; - } else if (r < 0) { - lderr(m_cct) << "error removing child from children list: " - << cpp_strerror(r) << dendl; - send_close_image(r); - return; - } - - - send_disable_mirror(); -} - -template -void RemoveRequest::send_disable_mirror() { - ldout(m_cct, 20) << dendl; - - using klass = RemoveRequest; - Context *ctx = create_context_callback< - klass, &klass::handle_disable_mirror>(this); - - mirror::DisableRequest *req = - mirror::DisableRequest::create(m_image_ctx, m_force, !m_force, ctx); - req->send(); -} - -template -void RemoveRequest::handle_disable_mirror(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r == -EOPNOTSUPP) { - r = 0; - } else if (r < 0) { - lderr(m_cct) << "error disabling image mirroring: " - << cpp_strerror(r) << dendl; - } - - send_close_image(r); -} - -template -void RemoveRequest::send_close_image(int r) { - ldout(m_cct, 20) << dendl; - - m_ret_val = r; - using klass = RemoveRequest; - Context *ctx = create_context_callback< - klass, &klass::handle_send_close_image>(this); - - m_image_ctx->state->close(ctx); -} - -template -void RemoveRequest::handle_send_close_image(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0) { - lderr(m_cct) << "error encountered while closing image: " - << cpp_strerror(r) << dendl; - } - - m_image_ctx->destroy(); - m_image_ctx = nullptr; - if (m_ret_val < 0) { - r = m_ret_val; - finish(r); - return; - } - - remove_header(); -} - -template -void RemoveRequest::remove_header() { - ldout(m_cct, 20) << dendl; - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - int r = m_ioctx.aio_remove(m_header_oid, rados_completion); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_remove_header(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "error removing header: " << cpp_strerror(r) << dendl; - m_ret_val = r; - } - - remove_image(); -} - -template -void RemoveRequest::remove_header_v2() { - ldout(m_cct, 20) << dendl; - - if (m_header_oid.empty()) { - m_header_oid = util::header_name(m_image_id); - } - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - int r = m_ioctx.aio_remove(m_header_oid, rados_completion); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_remove_header_v2(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "error removing header: " << cpp_strerror(r) << dendl; - finish(r); - return; - } - - send_journal_remove(); -} - -template -void RemoveRequest::send_journal_remove() { - ldout(m_cct, 20) << dendl; - - using klass = RemoveRequest; - Context *ctx = create_context_callback< - klass, &klass::handle_journal_remove>(this); - - journal::RemoveRequest *req = journal::RemoveRequest::create( - m_ioctx, m_image_id, Journal<>::IMAGE_CLIENT_ID, m_op_work_queue, ctx); - req->send(); -} - -template -void RemoveRequest::handle_journal_remove(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(r) - << dendl; - finish(r); - return; - } else { - r = 0; - } - - send_object_map_remove(); -} - -template -void RemoveRequest::send_object_map_remove() { - ldout(m_cct, 20) << dendl; - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - - int r = ObjectMap<>::aio_remove(m_ioctx, - m_image_id, - rados_completion); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_object_map_remove(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(r) - << dendl; - finish(r); - return; - } else { - r = 0; - } - - mirror_image_remove(); -} - -template -void RemoveRequest::mirror_image_remove() { - ldout(m_cct, 20) << dendl; - - librados::ObjectWriteOperation op; - cls_client::mirror_image_remove(&op, m_image_id); - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - int r = m_ioctx.aio_operate(RBD_MIRRORING, rados_completion, &op); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_mirror_image_remove(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT && r != -EOPNOTSUPP) { - lderr(m_cct) << "failed to remove mirror image state: " - << cpp_strerror(r) << dendl; - finish(r); - return; - } - - if (m_from_trash_remove) { - // both the id object and the directory entry have been removed in - // a previous call to trash_move. - finish(0); - return; - } - - remove_id_object(); -} - -template -void RemoveRequest::remove_image() { - ldout(m_cct, 20) << dendl; - - if (m_old_format || m_unknown_format) { - remove_v1_image(); - } else { - remove_v2_image(); - } -} - -template -void RemoveRequest::remove_v1_image() { - ldout(m_cct, 20) << dendl; - - Context *ctx = new FunctionContext([this] (int r) { - r = tmap_rm(m_ioctx, m_image_name); - handle_remove_v1_image(r); - }); - - m_op_work_queue->queue(ctx, 0); -} - -template -void RemoveRequest::handle_remove_v1_image(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - m_old_format = (r == 0); - if (r == 0 || (r < 0 && !m_unknown_format)) { - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "error removing image from v1 directory: " - << cpp_strerror(r) << dendl; - } - - m_on_finish->complete(r); - delete this; - return; - } - - if (!m_old_format) { - remove_v2_image(); - } -} - -template -void RemoveRequest::remove_v2_image() { - ldout(m_cct, 20) << dendl; - - if (m_image_id.empty()) { - dir_get_image_id(); - return; - } else if (m_image_name.empty()) { - dir_get_image_name(); - return; - } - - remove_header_v2(); - return; -} - -template -void RemoveRequest::dir_get_image_id() { - ldout(m_cct, 20) << dendl; - - librados::ObjectReadOperation op; - librbd::cls_client::dir_get_id_start(&op, m_image_name); - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - m_out_bl.clear(); - int r = m_ioctx.aio_operate(RBD_DIRECTORY, rados_completion, &op, &m_out_bl); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_dir_get_image_id(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "error fetching image id: " << cpp_strerror(r) - << dendl; - finish(r); - return; - } - - if (r == 0) { - bufferlist::iterator iter = m_out_bl.begin(); - r = librbd::cls_client::dir_get_id_finish(&iter, &m_image_id); - if (r < 0) { - finish(r); - return; - } - } - - remove_header_v2(); -} - -template -void RemoveRequest::dir_get_image_name() { - ldout(m_cct, 20) << dendl; - - librados::ObjectReadOperation op; - librbd::cls_client::dir_get_name_start(&op, m_image_id); - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - m_out_bl.clear(); - int r = m_ioctx.aio_operate(RBD_DIRECTORY, rados_completion, &op, &m_out_bl); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_dir_get_image_name(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "error fetching image name: " << cpp_strerror(r) - << dendl; - finish(r); - return; - } - - if (r == 0) { - bufferlist::iterator iter = m_out_bl.begin(); - r = librbd::cls_client::dir_get_name_finish(&iter, &m_image_name); - if (r < 0) { - finish(r); - return; - } - } - - remove_header_v2(); -} - -template -void RemoveRequest::remove_id_object() { - ldout(m_cct, 20) << dendl; - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - int r = m_ioctx.aio_remove(util::id_obj_name(m_image_name), rados_completion); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_remove_id_object(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "error removing id object: " << cpp_strerror(r) - << dendl; - finish(r); - return; - } - - dir_remove_image(); -} - -template -void RemoveRequest::dir_remove_image() { - ldout(m_cct, 20) << dendl; - - librados::ObjectWriteOperation op; - librbd::cls_client::dir_remove_image(&op, m_image_name, m_image_id); - - using klass = RemoveRequest; - librados::AioCompletion *rados_completion = - create_rados_callback(this); - int r = m_ioctx.aio_operate(RBD_DIRECTORY, rados_completion, &op); - assert(r == 0); - rados_completion->release(); -} - -template -void RemoveRequest::handle_dir_remove_image(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - if (r < 0 && r != -ENOENT) { - lderr(m_cct) << "error removing image from v2 directory: " - << cpp_strerror(r) << dendl; - } - - finish(r); -} - -template -void RemoveRequest::finish(int r) { - ldout(m_cct, 20) << "r=" << r << dendl; - - m_on_finish->complete(r); - delete this; -} - -} // namespace image -} // namespace librbd - -template class librbd::image::RemoveRequest;