From 815177bd696e7876c78fc2eca3855236b9f32841 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 8 Oct 2018 09:55:18 -0400 Subject: [PATCH] librbd: move trash API methods to api namespace Signed-off-by: Jason Dillaman --- src/librbd/CMakeLists.txt | 3 +- src/librbd/api/Migration.cc | 10 +- src/librbd/api/Trash.cc | 356 ++++++++++++++++++++++++++++++++++++ src/librbd/api/Trash.h | 42 +++++ src/librbd/internal.cc | 325 -------------------------------- src/librbd/internal.h | 10 - src/librbd/librbd.cc | 28 +-- 7 files changed, 421 insertions(+), 353 deletions(-) create mode 100644 src/librbd/api/Trash.cc create mode 100644 src/librbd/api/Trash.h diff --git a/src/librbd/CMakeLists.txt b/src/librbd/CMakeLists.txt index b6f38f219cfac..2ba963ed0db0f 100644 --- a/src/librbd/CMakeLists.txt +++ b/src/librbd/CMakeLists.txt @@ -31,8 +31,9 @@ set(librbd_internal_srcs api/Migration.cc api/Mirror.cc api/Namespace.cc - api/Snapshot.cc api/PoolMetadata.cc + api/Snapshot.cc + api/Trash.cc cache/ImageWriteback.cc cache/ObjectCacherObjectDispatch.cc cache/PassthroughImageCache.cc diff --git a/src/librbd/api/Migration.cc b/src/librbd/api/Migration.cc index eb8a2914c2bed..8561ba075006d 100644 --- a/src/librbd/api/Migration.cc +++ b/src/librbd/api/Migration.cc @@ -14,6 +14,7 @@ #include "librbd/Utils.h" #include "librbd/api/Config.h" #include "librbd/api/Group.h" +#include "librbd/api/Trash.h" #include "librbd/deep_copy/MetadataCopyRequest.h" #include "librbd/deep_copy/SnapshotCopyRequest.h" #include "librbd/image/CloneRequest.h" @@ -150,7 +151,7 @@ int trash_search(librados::IoCtx &io_ctx, rbd_trash_image_source_t source, const std::string &image_name, std::string *image_id) { std::vector entries; - int r = trash_list(io_ctx, entries); + int r = Trash<>::list(io_ctx, entries); if (r < 0) { return r; } @@ -1076,8 +1077,8 @@ int Migration::v2_unlink_src_image() { m_src_image_ctx->owner_lock.put_read(); } - int r = trash_move(m_src_io_ctx, RBD_TRASH_IMAGE_SOURCE_MIGRATION, - m_src_image_ctx->name, 0); + int r = Trash::move(m_src_io_ctx, RBD_TRASH_IMAGE_SOURCE_MIGRATION, + m_src_image_ctx->name, 0); if (r < 0) { lderr(m_cct) << "failed moving image to trash: " << cpp_strerror(r) << dendl; @@ -1114,7 +1115,8 @@ template int Migration::v2_relink_src_image() { ldout(m_cct, 10) << dendl; - int r = trash_restore(m_src_io_ctx, m_src_image_ctx->id, m_src_image_ctx->name); + int r = Trash::restore(m_src_io_ctx, m_src_image_ctx->id, + m_src_image_ctx->name); if (r < 0) { lderr(m_cct) << "failed restoring image from trash: " << cpp_strerror(r) << dendl; diff --git a/src/librbd/api/Trash.cc b/src/librbd/api/Trash.cc new file mode 100644 index 0000000000000..560c5f2a24105 --- /dev/null +++ b/src/librbd/api/Trash.cc @@ -0,0 +1,356 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/api/Trash.h" +#include "include/rados/librados.hpp" +#include "common/dout.h" +#include "common/errno.h" +#include "cls/rbd/cls_rbd_client.h" +#include "librbd/ExclusiveLock.h" +#include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "librbd/internal.h" +#include "librbd/Operations.h" +#include "librbd/TrashWatcher.h" +#include "librbd/Utils.h" +#include "librbd/trash/MoveRequest.h" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::api::Trash: " << __func__ << ": " + +namespace librbd { +namespace api { + +template +int Trash::move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source, + const std::string &image_name, uint64_t delay) { + CephContext *cct((CephContext *)io_ctx.cct()); + ldout(cct, 20) << "trash_move " << &io_ctx << " " << image_name + << dendl; + + // try to get image id from the directory + std::string image_id; + int r = cls_client::dir_get_id(&io_ctx, RBD_DIRECTORY, image_name, + &image_id); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "failed to retrieve image id: " << cpp_strerror(r) << dendl; + return r; + } + + ImageCtx *ictx = new ImageCtx((image_id.empty() ? image_name : ""), + image_id, nullptr, io_ctx, false); + r = ictx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT); + if (r == -ENOENT) { + return r; + } else if (r < 0) { + lderr(cct) << "failed to open image: " << cpp_strerror(r) << dendl; + return r; + } else if (ictx->old_format) { + ldout(cct, 10) << "cannot move v1 image to trash" << dendl; + ictx->state->close(); + return -EOPNOTSUPP; + } + + image_id = ictx->id; + ictx->owner_lock.get_read(); + if (ictx->exclusive_lock != nullptr) { + ictx->exclusive_lock->block_requests(0); + + r = ictx->operations->prepare_image_update(false); + if (r < 0) { + lderr(cct) << "cannot obtain exclusive lock - not removing" << dendl; + ictx->owner_lock.put_read(); + ictx->state->close(); + return -EBUSY; + } + } + ictx->owner_lock.put_read(); + + if (!ictx->migration_info.empty()) { + lderr(cct) << "cannot move migrating image to trash" << dendl; + ictx->state->close(); + return -EINVAL; + } + + utime_t delete_time{ceph_clock_now()}; + utime_t deferment_end_time{delete_time}; + deferment_end_time += delay; + cls::rbd::TrashImageSpec trash_image_spec{ + static_cast(source), ictx->name, + delete_time, deferment_end_time}; + + trash_image_spec.state = cls::rbd::TRASH_IMAGE_STATE_MOVING; + C_SaferCond ctx; + auto req = trash::MoveRequest::create(io_ctx, ictx->id, trash_image_spec, + &ctx); + req->send(); + + r = ctx.wait(); + ictx->state->close(); + trash_image_spec.state = cls::rbd::TRASH_IMAGE_STATE_NORMAL; + int ret = cls_client::trash_state_set(&io_ctx, image_id, + trash_image_spec.state, + cls::rbd::TRASH_IMAGE_STATE_MOVING); + if (ret < 0 && ret != -EOPNOTSUPP) { + lderr(cct) << "error setting trash image state: " + << cpp_strerror(ret) << dendl; + return ret; + } + if (r < 0) { + return r; + } + + C_SaferCond notify_ctx; + TrashWatcher::notify_image_added(io_ctx, image_id, trash_image_spec, + ¬ify_ctx); + r = notify_ctx.wait(); + if (r < 0) { + lderr(cct) << "failed to send update notification: " << cpp_strerror(r) + << dendl; + } + + return 0; +} + +template +int Trash::get(IoCtx &io_ctx, const std::string &id, + trash_image_info_t *info) { + CephContext *cct((CephContext *)io_ctx.cct()); + ldout(cct, 20) << __func__ << " " << &io_ctx << dendl; + + cls::rbd::TrashImageSpec spec; + int r = cls_client::trash_get(&io_ctx, id, &spec); + if (r == -ENOENT) { + return r; + } else if (r < 0) { + lderr(cct) << "error retrieving trash entry: " << cpp_strerror(r) + << dendl; + return r; + } + + rbd_trash_image_source_t source = static_cast( + spec.source); + *info = trash_image_info_t{id, spec.name, source, spec.deletion_time.sec(), + spec.deferment_end_time.sec()}; + return 0; +} + +template +int Trash::list(IoCtx &io_ctx, vector &entries) { + CephContext *cct((CephContext *)io_ctx.cct()); + ldout(cct, 20) << "trash_list " << &io_ctx << dendl; + + bool more_entries; + uint32_t max_read = 1024; + std::string last_read = ""; + do { + map trash_entries; + int r = cls_client::trash_list(&io_ctx, last_read, max_read, + &trash_entries); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "error listing rbd trash entries: " << cpp_strerror(r) + << dendl; + return r; + } else if (r == -ENOENT) { + break; + } + + if (trash_entries.empty()) { + break; + } + + for (const auto &entry : trash_entries) { + rbd_trash_image_source_t source = + static_cast(entry.second.source); + entries.push_back({entry.first, entry.second.name, source, + entry.second.deletion_time.sec(), + entry.second.deferment_end_time.sec()}); + } + last_read = trash_entries.rbegin()->first; + more_entries = (trash_entries.size() >= max_read); + } while (more_entries); + + return 0; +} + +template +int Trash::remove(IoCtx &io_ctx, const std::string &image_id, bool force, + ProgressContext& prog_ctx) { + CephContext *cct((CephContext *)io_ctx.cct()); + ldout(cct, 20) << "trash_remove " << &io_ctx << " " << image_id + << " " << force << dendl; + + cls::rbd::TrashImageSpec trash_spec; + int r = cls_client::trash_get(&io_ctx, image_id, &trash_spec); + if (r < 0) { + lderr(cct) << "error getting image id " << image_id + << " info from trash: " << cpp_strerror(r) << dendl; + return r; + } + + utime_t now = ceph_clock_now(); + if (now < trash_spec.deferment_end_time && !force) { + lderr(cct) << "error: deferment time has not expired." << dendl; + return -EPERM; + } + if (trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_NORMAL && + trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_REMOVING) { + lderr(cct) << "error: image is pending restoration." << dendl; + return -EBUSY; + } + + r = cls_client::trash_state_set(&io_ctx, image_id, + cls::rbd::TRASH_IMAGE_STATE_REMOVING, + cls::rbd::TRASH_IMAGE_STATE_NORMAL); + if (r < 0 && r != -EOPNOTSUPP) { + lderr(cct) << "error setting trash image state: " + << cpp_strerror(r) << dendl; + return r; + } + + r = librbd::remove(io_ctx, "", image_id, prog_ctx, false, true); + if (r < 0) { + lderr(cct) << "error removing image " << image_id + << ", which is pending deletion" << dendl; + int ret = cls_client::trash_state_set(&io_ctx, image_id, + cls::rbd::TRASH_IMAGE_STATE_NORMAL, + cls::rbd::TRASH_IMAGE_STATE_REMOVING); + if (ret < 0 && ret != -EOPNOTSUPP) { + lderr(cct) << "error setting trash image state: " + << cpp_strerror(ret) << dendl; + } + return r; + } + r = cls_client::trash_remove(&io_ctx, image_id); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "error removing image " << image_id + << " from rbd_trash object" << dendl; + return r; + } + + C_SaferCond notify_ctx; + TrashWatcher::notify_image_removed(io_ctx, image_id, ¬ify_ctx); + r = notify_ctx.wait(); + if (r < 0) { + lderr(cct) << "failed to send update notification: " << cpp_strerror(r) + << dendl; + } + + return 0; +} + +template +int Trash::restore(librados::IoCtx &io_ctx, const std::string &image_id, + const std::string &image_new_name) { + CephContext *cct((CephContext *)io_ctx.cct()); + ldout(cct, 20) << "trash_restore " << &io_ctx << " " << image_id << " " + << image_new_name << dendl; + + cls::rbd::TrashImageSpec trash_spec; + int r = cls_client::trash_get(&io_ctx, image_id, &trash_spec); + if (r < 0) { + lderr(cct) << "error getting image id " << image_id + << " info from trash: " << cpp_strerror(r) << dendl; + return r; + } + + std::string image_name = image_new_name; + if (trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_NORMAL && + trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_RESTORING) { + lderr(cct) << "error restoring image id " << image_id + << ", which is pending deletion" << dendl; + return -EBUSY; + } + r = cls_client::trash_state_set(&io_ctx, image_id, + cls::rbd::TRASH_IMAGE_STATE_RESTORING, + cls::rbd::TRASH_IMAGE_STATE_NORMAL); + if (r < 0 && r != -EOPNOTSUPP) { + lderr(cct) << "error setting trash image state: " + << cpp_strerror(r) << dendl; + return r; + } + + if (image_name.empty()) { + // if user didn't specify a new name, let's try using the old name + image_name = trash_spec.name; + ldout(cct, 20) << "restoring image id " << image_id << " with name " + << image_name << dendl; + } + + // check if no image exists with the same name + bool create_id_obj = true; + std::string existing_id; + r = cls_client::get_id(&io_ctx, util::id_obj_name(image_name), &existing_id); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "error checking if image " << image_name << " exists: " + << cpp_strerror(r) << dendl; + int ret = cls_client::trash_state_set(&io_ctx, image_id, + cls::rbd::TRASH_IMAGE_STATE_NORMAL, + cls::rbd::TRASH_IMAGE_STATE_RESTORING); + if (ret < 0 && ret != -EOPNOTSUPP) { + lderr(cct) << "error setting trash image state: " + << cpp_strerror(ret) << dendl; + } + return r; + } else if (r != -ENOENT){ + // checking if we are recovering from an incomplete restore + if (existing_id != image_id) { + ldout(cct, 2) << "an image with the same name already exists" << dendl; + int r2 = cls_client::trash_state_set(&io_ctx, image_id, + cls::rbd::TRASH_IMAGE_STATE_NORMAL, + cls::rbd::TRASH_IMAGE_STATE_RESTORING); + if (r2 < 0 && r2 != -EOPNOTSUPP) { + lderr(cct) << "error setting trash image state: " + << cpp_strerror(r2) << dendl; + } + return -EEXIST; + } + create_id_obj = false; + } + + if (create_id_obj) { + ldout(cct, 2) << "adding id object" << dendl; + librados::ObjectWriteOperation op; + op.create(true); + cls_client::set_id(&op, image_id); + r = io_ctx.operate(util::id_obj_name(image_name), &op); + if (r < 0) { + lderr(cct) << "error adding id object for image " << image_name + << ": " << cpp_strerror(r) << dendl; + return r; + } + } + + ldout(cct, 2) << "adding rbd image from v2 directory..." << dendl; + r = cls_client::dir_add_image(&io_ctx, RBD_DIRECTORY, image_name, + image_id); + if (r < 0 && r != -EEXIST) { + lderr(cct) << "error adding image to v2 directory: " + << cpp_strerror(r) << dendl; + return r; + } + + ldout(cct, 2) << "removing image from trash..." << dendl; + r = cls_client::trash_remove(&io_ctx, image_id); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "error removing image id " << image_id << " from trash: " + << cpp_strerror(r) << dendl; + return r; + } + + C_SaferCond notify_ctx; + TrashWatcher::notify_image_removed(io_ctx, image_id, ¬ify_ctx); + r = notify_ctx.wait(); + if (r < 0) { + lderr(cct) << "failed to send update notification: " << cpp_strerror(r) + << dendl; + } + + return 0; +} + +} // namespace api +} // namespace librbd + +template class librbd::api::Trash; diff --git a/src/librbd/api/Trash.h b/src/librbd/api/Trash.h new file mode 100644 index 0000000000000..cf7217de8098e --- /dev/null +++ b/src/librbd/api/Trash.h @@ -0,0 +1,42 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef LIBRBD_API_TRASH_H +#define LIBRBD_API_TRASH_H + +#include "include/rbd/librbd.hpp" +#include +#include + +namespace librados { struct IoCtx; } + +namespace librbd { + +class ProgressContext; + +struct ImageCtx; + +namespace api { + +template +struct Trash { + + static int move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source, + const std::string &image_name, uint64_t delay); + static int get(librados::IoCtx &io_ctx, const std::string &id, + trash_image_info_t *info); + static int list(librados::IoCtx &io_ctx, + std::vector &entries); + static int remove(librados::IoCtx &io_ctx, const std::string &image_id, + bool force, ProgressContext& prog_ctx); + static int restore(librados::IoCtx &io_ctx, const std::string &image_id, + const std::string &image_new_name); + +}; + +} // namespace api +} // namespace librbd + +extern template class librbd::api::Trash; + +#endif // LIBRBD_API_TRASH_H diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 81d1765e050db..903a8ce110dac 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -30,7 +30,6 @@ #include "librbd/Journal.h" #include "librbd/ObjectMap.h" #include "librbd/Operations.h" -#include "librbd/TrashWatcher.h" #include "librbd/Types.h" #include "librbd/Utils.h" #include "librbd/api/Config.h" @@ -51,7 +50,6 @@ #include "librbd/managed_lock/Types.h" #include "librbd/mirror/EnableRequest.h" #include "librbd/operation/TrimRequest.h" -#include "librbd/trash/MoveRequest.h" #include "journal/Journaler.h" @@ -1394,329 +1392,6 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) return cond.wait(); } - int trash_move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source, - const std::string &image_name, uint64_t delay) { - CephContext *cct((CephContext *)io_ctx.cct()); - ldout(cct, 20) << "trash_move " << &io_ctx << " " << image_name - << dendl; - - // try to get image id from the directory - std::string image_id; - int r = cls_client::dir_get_id(&io_ctx, RBD_DIRECTORY, image_name, - &image_id); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "failed to retrieve image id: " << cpp_strerror(r) << dendl; - return r; - } - - ImageCtx *ictx = new ImageCtx((image_id.empty() ? image_name : ""), - image_id, nullptr, io_ctx, false); - r = ictx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT); - if (r == -ENOENT) { - return r; - } else if (r < 0) { - lderr(cct) << "failed to open image: " << cpp_strerror(r) << dendl; - return r; - } else if (ictx->old_format) { - ldout(cct, 10) << "cannot move v1 image to trash" << dendl; - ictx->state->close(); - return -EOPNOTSUPP; - } - - image_id = ictx->id; - ictx->owner_lock.get_read(); - if (ictx->exclusive_lock != nullptr) { - ictx->exclusive_lock->block_requests(0); - - r = ictx->operations->prepare_image_update(false); - if (r < 0) { - lderr(cct) << "cannot obtain exclusive lock - not removing" << dendl; - ictx->owner_lock.put_read(); - ictx->state->close(); - return -EBUSY; - } - } - ictx->owner_lock.put_read(); - - if (!ictx->migration_info.empty()) { - lderr(cct) << "cannot move migrating image to trash" << dendl; - ictx->state->close(); - return -EINVAL; - } - - utime_t delete_time{ceph_clock_now()}; - utime_t deferment_end_time{delete_time}; - deferment_end_time += delay; - cls::rbd::TrashImageSpec trash_image_spec{ - static_cast(source), ictx->name, - delete_time, deferment_end_time}; - - trash_image_spec.state = cls::rbd::TRASH_IMAGE_STATE_MOVING; - C_SaferCond ctx; - auto req = trash::MoveRequest<>::create(io_ctx, ictx->id, trash_image_spec, - &ctx); - req->send(); - - r = ctx.wait(); - ictx->state->close(); - trash_image_spec.state = cls::rbd::TRASH_IMAGE_STATE_NORMAL; - int ret = cls_client::trash_state_set(&io_ctx, image_id, - trash_image_spec.state, - cls::rbd::TRASH_IMAGE_STATE_MOVING); - if (ret < 0 && ret != -EOPNOTSUPP) { - lderr(cct) << "error setting trash image state: " - << cpp_strerror(ret) << dendl; - return ret; - } - if (r < 0) { - return r; - } - - C_SaferCond notify_ctx; - TrashWatcher<>::notify_image_added(io_ctx, image_id, trash_image_spec, - ¬ify_ctx); - r = notify_ctx.wait(); - if (r < 0) { - lderr(cct) << "failed to send update notification: " << cpp_strerror(r) - << dendl; - } - - return 0; - } - - int trash_get(IoCtx &io_ctx, const std::string &id, - trash_image_info_t *info) { - CephContext *cct((CephContext *)io_ctx.cct()); - ldout(cct, 20) << __func__ << " " << &io_ctx << dendl; - - cls::rbd::TrashImageSpec spec; - int r = cls_client::trash_get(&io_ctx, id, &spec); - if (r == -ENOENT) { - return r; - } else if (r < 0) { - lderr(cct) << "error retrieving trash entry: " << cpp_strerror(r) - << dendl; - return r; - } - - rbd_trash_image_source_t source = static_cast( - spec.source); - *info = trash_image_info_t{id, spec.name, source, spec.deletion_time.sec(), - spec.deferment_end_time.sec()}; - return 0; - } - - int trash_list(IoCtx &io_ctx, vector &entries) { - CephContext *cct((CephContext *)io_ctx.cct()); - ldout(cct, 20) << "trash_list " << &io_ctx << dendl; - - bool more_entries; - uint32_t max_read = 1024; - std::string last_read = ""; - do { - map trash_entries; - int r = cls_client::trash_list(&io_ctx, last_read, max_read, - &trash_entries); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "error listing rbd trash entries: " << cpp_strerror(r) - << dendl; - return r; - } else if (r == -ENOENT) { - break; - } - - if (trash_entries.empty()) { - break; - } - - for (const auto &entry : trash_entries) { - rbd_trash_image_source_t source = - static_cast(entry.second.source); - entries.push_back({entry.first, entry.second.name, source, - entry.second.deletion_time.sec(), - entry.second.deferment_end_time.sec()}); - } - last_read = trash_entries.rbegin()->first; - more_entries = (trash_entries.size() >= max_read); - } while (more_entries); - - return 0; - } - - int trash_remove(IoCtx &io_ctx, const std::string &image_id, bool force, - ProgressContext& prog_ctx) { - CephContext *cct((CephContext *)io_ctx.cct()); - ldout(cct, 20) << "trash_remove " << &io_ctx << " " << image_id - << " " << force << dendl; - - cls::rbd::TrashImageSpec trash_spec; - int r = cls_client::trash_get(&io_ctx, image_id, &trash_spec); - if (r < 0) { - lderr(cct) << "error getting image id " << image_id - << " info from trash: " << cpp_strerror(r) << dendl; - return r; - } - - utime_t now = ceph_clock_now(); - if (now < trash_spec.deferment_end_time && !force) { - lderr(cct) << "error: deferment time has not expired." << dendl; - return -EPERM; - } - if (trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_NORMAL && - trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_REMOVING) { - lderr(cct) << "error: image is pending restoration." << dendl; - return -EBUSY; - } - - r = cls_client::trash_state_set(&io_ctx, image_id, - cls::rbd::TRASH_IMAGE_STATE_REMOVING, - cls::rbd::TRASH_IMAGE_STATE_NORMAL); - if (r < 0 && r != -EOPNOTSUPP) { - lderr(cct) << "error setting trash image state: " - << cpp_strerror(r) << dendl; - return r; - } - - r = remove(io_ctx, "", image_id, prog_ctx, false, true); - if (r < 0) { - lderr(cct) << "error removing image " << image_id - << ", which is pending deletion" << dendl; - int ret = cls_client::trash_state_set(&io_ctx, image_id, - cls::rbd::TRASH_IMAGE_STATE_NORMAL, - cls::rbd::TRASH_IMAGE_STATE_REMOVING); - if (ret < 0 && ret != -EOPNOTSUPP) { - lderr(cct) << "error setting trash image state: " - << cpp_strerror(ret) << dendl; - } - return r; - } - r = cls_client::trash_remove(&io_ctx, image_id); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "error removing image " << image_id - << " from rbd_trash object" << dendl; - return r; - } - - C_SaferCond notify_ctx; - TrashWatcher<>::notify_image_removed(io_ctx, image_id, ¬ify_ctx); - r = notify_ctx.wait(); - if (r < 0) { - lderr(cct) << "failed to send update notification: " << cpp_strerror(r) - << dendl; - } - - return 0; - } - - int trash_restore(librados::IoCtx &io_ctx, const std::string &image_id, - const std::string &image_new_name) { - CephContext *cct((CephContext *)io_ctx.cct()); - ldout(cct, 20) << "trash_restore " << &io_ctx << " " << image_id << " " - << image_new_name << dendl; - - cls::rbd::TrashImageSpec trash_spec; - int r = cls_client::trash_get(&io_ctx, image_id, &trash_spec); - if (r < 0) { - lderr(cct) << "error getting image id " << image_id - << " info from trash: " << cpp_strerror(r) << dendl; - return r; - } - - std::string image_name = image_new_name; - if (trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_NORMAL && - trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_RESTORING) { - lderr(cct) << "error restoring image id " << image_id - << ", which is pending deletion" << dendl; - return -EBUSY; - } - r = cls_client::trash_state_set(&io_ctx, image_id, - cls::rbd::TRASH_IMAGE_STATE_RESTORING, - cls::rbd::TRASH_IMAGE_STATE_NORMAL); - if (r < 0 && r != -EOPNOTSUPP) { - lderr(cct) << "error setting trash image state: " - << cpp_strerror(r) << dendl; - return r; - } - - if (image_name.empty()) { - // if user didn't specify a new name, let's try using the old name - image_name = trash_spec.name; - ldout(cct, 20) << "restoring image id " << image_id << " with name " - << image_name << dendl; - } - - // check if no image exists with the same name - bool create_id_obj = true; - std::string existing_id; - r = cls_client::get_id(&io_ctx, util::id_obj_name(image_name), &existing_id); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "error checking if image " << image_name << " exists: " - << cpp_strerror(r) << dendl; - int ret = cls_client::trash_state_set(&io_ctx, image_id, - cls::rbd::TRASH_IMAGE_STATE_NORMAL, - cls::rbd::TRASH_IMAGE_STATE_RESTORING); - if (ret < 0 && ret != -EOPNOTSUPP) { - lderr(cct) << "error setting trash image state: " - << cpp_strerror(ret) << dendl; - } - return r; - } else if (r != -ENOENT){ - // checking if we are recovering from an incomplete restore - if (existing_id != image_id) { - ldout(cct, 2) << "an image with the same name already exists" << dendl; - int r2 = cls_client::trash_state_set(&io_ctx, image_id, - cls::rbd::TRASH_IMAGE_STATE_NORMAL, - cls::rbd::TRASH_IMAGE_STATE_RESTORING); - if (r2 < 0 && r2 != -EOPNOTSUPP) { - lderr(cct) << "error setting trash image state: " - << cpp_strerror(r2) << dendl; - } - return -EEXIST; - } - create_id_obj = false; - } - - if (create_id_obj) { - ldout(cct, 2) << "adding id object" << dendl; - librados::ObjectWriteOperation op; - op.create(true); - cls_client::set_id(&op, image_id); - r = io_ctx.operate(util::id_obj_name(image_name), &op); - if (r < 0) { - lderr(cct) << "error adding id object for image " << image_name - << ": " << cpp_strerror(r) << dendl; - return r; - } - } - - ldout(cct, 2) << "adding rbd image from v2 directory..." << dendl; - r = cls_client::dir_add_image(&io_ctx, RBD_DIRECTORY, image_name, - image_id); - if (r < 0 && r != -EEXIST) { - lderr(cct) << "error adding image to v2 directory: " - << cpp_strerror(r) << dendl; - return r; - } - - ldout(cct, 2) << "removing image from trash..." << dendl; - r = cls_client::trash_remove(&io_ctx, image_id); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "error removing image id " << image_id << " from trash: " - << cpp_strerror(r) << dendl; - return r; - } - - C_SaferCond notify_ctx; - TrashWatcher<>::notify_image_removed(io_ctx, image_id, ¬ify_ctx); - r = notify_ctx.wait(); - if (r < 0) { - lderr(cct) << "failed to send update notification: " << cpp_strerror(r) - << dendl; - } - - return 0; - } - int snap_list(ImageCtx *ictx, vector& snaps) { ldout(ictx->cct, 20) << "snap_list " << ictx << dendl; diff --git a/src/librbd/internal.h b/src/librbd/internal.h index 889eff3b3aa41..27e7be8f2e2c1 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -105,16 +105,6 @@ namespace librbd { const std::string &image_id, ProgressContext& prog_ctx, bool force=false, bool from_trash_remove=false); - int trash_move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source, - const std::string &image_name, uint64_t delay); - int trash_get(IoCtx &io_ctx, const std::string &id, trash_image_info_t *info); - int trash_list(librados::IoCtx &io_ctx, - std::vector &entries); - int trash_remove(librados::IoCtx &io_ctx, const std::string &image_id, - bool force, ProgressContext& prog_ctx); - int trash_restore(librados::IoCtx &io_ctx, const std::string &image_id, - const std::string &image_new_name); - int snap_list(ImageCtx *ictx, std::vector& snaps); int snap_exists(ImageCtx *ictx, const cls::rbd::SnapshotNamespace& snap_namespace, const char *snap_name, bool *exists); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 1962179258ecc..5546cefb1054d 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -35,6 +35,7 @@ #include "librbd/api/Namespace.h" #include "librbd/api/PoolMetadata.h" #include "librbd/api/Snapshot.h" +#include "librbd/api/Trash.h" #include "librbd/io/AioCompletion.h" #include "librbd/io/ImageRequestWQ.h" #include "librbd/io/ReadResult.h" @@ -576,21 +577,21 @@ namespace librbd { TracepointProvider::initialize(get_cct(io_ctx)); tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name); - int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name, - delay); + int r = librbd::api::Trash<>::move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, + name, delay); tracepoint(librbd, trash_move_exit, r); return r; } int RBD::trash_get(IoCtx &io_ctx, const char *id, trash_image_info_t *info) { - return librbd::trash_get(io_ctx, id, info); + return librbd::api::Trash<>::get(io_ctx, id, info); } int RBD::trash_list(IoCtx &io_ctx, vector &entries) { TracepointProvider::initialize(get_cct(io_ctx)); tracepoint(librbd, trash_list_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id()); - int r = librbd::trash_list(io_ctx, entries); + int r = librbd::api::Trash<>::list(io_ctx, entries); #ifdef WITH_LTTNG if (r >= 0) { for (const auto& entry : entries) { @@ -607,7 +608,7 @@ namespace librbd { tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), image_id, force); librbd::NoOpProgressContext prog_ctx; - int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx); + int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, prog_ctx); tracepoint(librbd, trash_remove_exit, r); return r; } @@ -617,7 +618,7 @@ namespace librbd { TracepointProvider::initialize(get_cct(io_ctx)); tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), image_id, force); - int r = librbd::trash_remove(io_ctx, image_id, force, pctx); + int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, pctx); tracepoint(librbd, trash_remove_exit, r); return r; } @@ -626,7 +627,7 @@ namespace librbd { TracepointProvider::initialize(get_cct(io_ctx)); tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), id, name); - int r = librbd::trash_restore(io_ctx, id, name); + int r = librbd::api::Trash<>::restore(io_ctx, id, name); tracepoint(librbd, trash_undelete_exit, r); return r; } @@ -2829,7 +2830,8 @@ extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name, TracepointProvider::initialize(get_cct(io_ctx)); tracepoint(librbd, trash_move_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), name); - int r = librbd::trash_move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name, delay); + int r = librbd::api::Trash<>::move(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER, name, + delay); tracepoint(librbd, trash_move_exit, r); return r; } @@ -2840,7 +2842,7 @@ extern "C" int rbd_trash_get(rados_ioctx_t io, const char *id, librados::IoCtx::from_rados_ioctx_t(io, io_ctx); librbd::trash_image_info_t cpp_info; - int r = librbd::trash_get(io_ctx, id, &cpp_info); + int r = librbd::api::Trash<>::get(io_ctx, id, &cpp_info); if (r < 0) { return r; } @@ -2863,7 +2865,7 @@ extern "C" int rbd_trash_list(rados_ioctx_t p, rbd_trash_image_info_t *entries, io_ctx.get_pool_name().c_str(), io_ctx.get_id()); vector cpp_entries; - int r = librbd::trash_list(io_ctx, cpp_entries); + int r = librbd::api::Trash<>::list(io_ctx, cpp_entries); if (r < 0) { tracepoint(librbd, trash_list_exit, r, *num_entries); return r; @@ -2899,7 +2901,7 @@ extern "C" int rbd_trash_remove(rados_ioctx_t p, const char *image_id, tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), image_id, force); librbd::NoOpProgressContext prog_ctx; - int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx); + int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, prog_ctx); tracepoint(librbd, trash_remove_exit, r); return r; } @@ -2915,7 +2917,7 @@ extern "C" int rbd_trash_remove_with_progress(rados_ioctx_t p, tracepoint(librbd, trash_remove_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), image_id, force); librbd::CProgressContext prog_ctx(cb, cbdata); - int r = librbd::trash_remove(io_ctx, image_id, force, prog_ctx); + int r = librbd::api::Trash<>::remove(io_ctx, image_id, force, prog_ctx); tracepoint(librbd, trash_remove_exit, r); return r; } @@ -2927,7 +2929,7 @@ extern "C" int rbd_trash_restore(rados_ioctx_t p, const char *id, TracepointProvider::initialize(get_cct(io_ctx)); tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(), io_ctx.get_id(), id, name); - int r = librbd::trash_restore(io_ctx, id, name); + int r = librbd::api::Trash<>::restore(io_ctx, id, name); tracepoint(librbd, trash_undelete_exit, r); return r; } -- 2.39.5