diff --git src/librbd/api/Trash.cc src/librbd/api/Trash.cc index 52f79632d5..3d539ab1e2 100644 --- src/librbd/api/Trash.cc +++ src/librbd/api/Trash.cc @@ -24,7 +24,6 @@ #include <json_spirit/json_spirit.h> #include "librbd/journal/DisabledPolicy.h" #include "librbd/image/ListWatchersRequest.h" -#include <experimental/map> #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -124,48 +123,6 @@ int enable_mirroring(IoCtx &io_ctx, const std::string &image_id) { return 0; } -int list_trash_image_specs( - librados::IoCtx &io_ctx, - std::map<std::string, cls::rbd::TrashImageSpec>* trash_image_specs, - bool exclude_user_remove_source) { - CephContext *cct((CephContext *)io_ctx.cct()); - ldout(cct, 20) << "list_trash_image_specs " << &io_ctx << dendl; - - bool more_entries; - uint32_t max_read = 1024; - std::string last_read; - do { - std::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) { - if (exclude_user_remove_source && - entry.second.source == cls::rbd::TRASH_IMAGE_SOURCE_REMOVING) { - continue; - } - - trash_image_specs->insert({entry.first, entry.second}); - } - - last_read = trash_entries.rbegin()->first; - more_entries = (trash_entries.size() >= max_read); - } while (more_entries); - - return 0; -} - } // anonymous namespace template <typename I> @@ -281,37 +238,15 @@ int Trash<I>::move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source, return -EOPNOTSUPP; } - // search for an interrupted trash move request - std::map<std::string, cls::rbd::TrashImageSpec> trash_image_specs; - int r = list_trash_image_specs(io_ctx, &trash_image_specs, true); - if (r < 0) { - return r; - } - - std::experimental::erase_if( - trash_image_specs, [image_name](const auto& pair) { - const auto& spec = pair.second; - return (spec.source != cls::rbd::TRASH_IMAGE_SOURCE_USER || - spec.state != cls::rbd::TRASH_IMAGE_STATE_MOVING || - spec.name != image_name); - }); - if (trash_image_specs.empty()) { - return -ENOENT; - } - - image_id = trash_image_specs.begin()->first; - ldout(cct, 15) << "derived image id " << image_id << " from existing " - << "trash entry" << dendl; + // image doesn't exist -- perhaps already in the trash since removing + // from the directory is the last step + return -ENOENT; } else if (r < 0) { lderr(cct) << "failed to retrieve image id: " << cpp_strerror(r) << dendl; return r; } - if (image_name.empty() || image_id.empty()) { - lderr(cct) << "invalid image name/id" << dendl; - return -EINVAL; - } - + ceph_assert(!image_name.empty() && !image_id.empty()); return Trash<I>::move(io_ctx, source, image_name, image_id, delay); } @@ -342,23 +277,41 @@ template <typename I> int Trash<I>::list(IoCtx &io_ctx, vector<trash_image_info_t> &entries, bool exclude_user_remove_source) { CephContext *cct((CephContext *)io_ctx.cct()); - ldout(cct, 20) << __func__ << " " << &io_ctx << dendl; + ldout(cct, 20) << "trash_list " << &io_ctx << dendl; - std::map<std::string, cls::rbd::TrashImageSpec> trash_image_specs; - int r = list_trash_image_specs(io_ctx, &trash_image_specs, - exclude_user_remove_source); - if (r < 0) { - return r; - } + 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; + } - entries.reserve(trash_image_specs.size()); - for (const auto& [image_id, spec] : trash_image_specs) { - rbd_trash_image_source_t source = - static_cast<rbd_trash_image_source_t>(spec.source); - entries.push_back({image_id, spec.name, source, - spec.deletion_time.sec(), - spec.deferment_end_time.sec()}); - } + 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); + if (exclude_user_remove_source && + source == RBD_TRASH_IMAGE_SOURCE_REMOVING) { + continue; + } + 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; } @@ -587,12 +540,8 @@ int Trash<I>::remove(IoCtx &io_ctx, const std::string &image_id, bool force, lderr(cct) << "error: deferment time has not expired." << dendl; return -EPERM; } - if (trash_spec.state == cls::rbd::TRASH_IMAGE_STATE_MOVING) { - lderr(cct) << "error: image is pending moving to the trash." - << dendl; - return -EUCLEAN; - } else if (trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_NORMAL && - trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_REMOVING) { + 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; } @@ -750,3 +699,4 @@ int Trash<I>::restore(librados::IoCtx &io_ctx, } // namespace librbd template class librbd::api::Trash<librbd::ImageCtx>; +