]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: move trash API methods to api namespace
authorJason Dillaman <dillaman@redhat.com>
Mon, 8 Oct 2018 13:55:18 +0000 (09:55 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 10 Oct 2018 13:06:59 +0000 (09:06 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/CMakeLists.txt
src/librbd/api/Migration.cc
src/librbd/api/Trash.cc [new file with mode: 0644]
src/librbd/api/Trash.h [new file with mode: 0644]
src/librbd/internal.cc
src/librbd/internal.h
src/librbd/librbd.cc

index b6f38f219cfacd40eb7fc752bc51bc9b477f3b6a..2ba963ed0db0f5a2d40e60956ecc8eabb6afe21b 100644 (file)
@@ -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
index eb8a2914c2bedd05abdc945b54067074721e7497..8561ba075006d2bc5c393bea142c58eb78d950fa 100644 (file)
@@ -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<trash_image_info_t> 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<I>::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<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;
@@ -1114,7 +1115,8 @@ template <typename I>
 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;
diff --git a/src/librbd/api/Trash.cc b/src/librbd/api/Trash.cc
new file mode 100644 (file)
index 0000000..560c5f2
--- /dev/null
@@ -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 <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,
+                                      &notify_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, &notify_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, &notify_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>;
diff --git a/src/librbd/api/Trash.h b/src/librbd/api/Trash.h
new file mode 100644 (file)
index 0000000..cf7217d
--- /dev/null
@@ -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 <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
index 81d1765e050dbb0892d35d6501fb727224599911..903a8ce110dacf9823db323c03f5d7b7e0e2aef3 100644 (file)
@@ -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<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,
-                                       &notify_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, &notify_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, &notify_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;
index 889eff3b3aa417834c65d529960cbcae770db609..27e7be8f2e2c1da6352a32d7c59b1857e99008ee 100644 (file)
@@ -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<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);
index 1962179258eccc94dedc20ad91bdd641f30f00a0..5546cefb1054dfacd7fa6121e174f8e4002e76d6 100644 (file)
@@ -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<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) {
@@ -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<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;
   }
@@ -626,7 +627,7 @@ namespace librbd {
     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;
   }
@@ -2829,7 +2830,8 @@ extern "C" int rbd_trash_move(rados_ioctx_t p, const char *name,
   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;
 }
@@ -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<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;
@@ -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<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;
 }