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
#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"
const std::string &image_name, std::string *image_id) {
std::vector<trash_image_info_t> entries;
- int r = trash_list(io_ctx, entries);
+ int r = Trash<>::list(io_ctx, entries);
if (r < 0) {
return r;
}
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<I>::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;
int Migration<I>::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<I>::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;
--- /dev/null
+// -*- 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 <typename I>
+int Trash<I>::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<cls::rbd::TrashImageSource>(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<I>::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<I>::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 <typename I>
+int Trash<I>::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<rbd_trash_image_source_t>(
+ spec.source);
+ *info = trash_image_info_t{id, spec.name, source, spec.deletion_time.sec(),
+ spec.deferment_end_time.sec()};
+ return 0;
+}
+
+template <typename I>
+int Trash<I>::list(IoCtx &io_ctx, vector<trash_image_info_t> &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<string, cls::rbd::TrashImageSpec> 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<rbd_trash_image_source_t>(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 <typename I>
+int Trash<I>::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<I>::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 <typename I>
+int Trash<I>::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<I>::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<librbd::ImageCtx>;
--- /dev/null
+// -*- 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 <string>
+#include <vector>
+
+namespace librados { struct IoCtx; }
+
+namespace librbd {
+
+class ProgressContext;
+
+struct ImageCtx;
+
+namespace api {
+
+template <typename ImageCtxT = librbd::ImageCtx>
+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<trash_image_info_t> &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<librbd::ImageCtx>;
+
+#endif // LIBRBD_API_TRASH_H
#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"
#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"
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<cls::rbd::TrashImageSource>(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<rbd_trash_image_source_t>(
- 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<trash_image_info_t> &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<string, cls::rbd::TrashImageSpec> 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<rbd_trash_image_source_t>(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<snap_info_t>& snaps)
{
ldout(ictx->cct, 20) << "snap_list " << ictx << dendl;
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<trash_image_info_t> &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<snap_info_t>& snaps);
int snap_exists(ImageCtx *ictx, const cls::rbd::SnapshotNamespace& snap_namespace,
const char *snap_name, bool *exists);
#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"
TracepointProvider::initialize<tracepoint_traits>(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<trash_image_info_t> &entries) {
TracepointProvider::initialize<tracepoint_traits>(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) {
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;
}
TracepointProvider::initialize<tracepoint_traits>(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;
}
TracepointProvider::initialize<tracepoint_traits>(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;
}
TracepointProvider::initialize<tracepoint_traits>(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;
}
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;
}
io_ctx.get_pool_name().c_str(), io_ctx.get_id());
vector<librbd::trash_image_info_t> 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;
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;
}
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;
}
TracepointProvider::initialize<tracepoint_traits>(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;
}