From c4128114f1c7d3bfd84e5ff78abaacf0dd87cc73 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Fri, 22 Jun 2018 14:07:56 -0400 Subject: [PATCH] librbd: add snapshot trash namespace helper and remove_by_id Signed-off-by: Jason Dillaman --- src/include/rbd/librbd.h | 5 ++ src/include/rbd/librbd.hpp | 2 + src/librbd/api/Snapshot.cc | 119 +++++++++++++++++++++++++++------ src/librbd/api/Snapshot.h | 6 ++ src/librbd/librbd.cc | 38 +++++++++++ src/test/librbd/test_librbd.cc | 18 +++++ 6 files changed, 169 insertions(+), 19 deletions(-) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 811bccb7ea825..c7b83ac1001f1 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -486,6 +486,7 @@ CEPH_RBD_API int rbd_snap_create(rbd_image_t image, const char *snapname); CEPH_RBD_API int rbd_snap_remove(rbd_image_t image, const char *snapname); CEPH_RBD_API int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32_t flags, librbd_progress_fn_t cb, void *cbdata); +CEPH_RBD_API int rbd_snap_remove_by_id(rbd_image_t image, uint64_t snap_id); CEPH_RBD_API int rbd_snap_rollback(rbd_image_t image, const char *snapname); CEPH_RBD_API int rbd_snap_rollback_with_progress(rbd_image_t image, const char *snapname, @@ -556,6 +557,10 @@ CEPH_RBD_API int rbd_snap_get_group_namespace(rbd_image_t image, size_t group_snap_size); CEPH_RBD_API int rbd_snap_group_namespace_cleanup(rbd_snap_group_namespace_t *group_snap, size_t group_snap_size); +CEPH_RBD_API int rbd_snap_get_trash_namespace(rbd_image_t image, + uint64_t snap_id, + char* original_name, + size_t max_length); CEPH_RBD_API int rbd_flatten(rbd_image_t image); diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 5db6f44a37aa6..bf150f4747977 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -379,6 +379,7 @@ public: int snap_create(const char *snapname); int snap_remove(const char *snapname); int snap_remove2(const char *snapname, uint32_t flags, ProgressContext& pctx); + int snap_remove_by_id(uint64_t snap_id); int snap_rollback(const char *snap_name); int snap_rollback_with_progress(const char *snap_name, ProgressContext& pctx); int snap_protect(const char *snap_name); @@ -395,6 +396,7 @@ public: int snap_get_group_namespace(uint64_t snap_id, snap_group_namespace_t *group_namespace, size_t snap_group_namespace_size); + int snap_get_trash_namespace(uint64_t snap_id, std::string* original_name); /* I/O */ ssize_t read(uint64_t ofs, size_t len, ceph::bufferlist& bl); diff --git a/src/librbd/api/Snapshot.cc b/src/librbd/api/Snapshot.cc index f9f6aea524513..fb5c70ba151f2 100644 --- a/src/librbd/api/Snapshot.cc +++ b/src/librbd/api/Snapshot.cc @@ -5,6 +5,8 @@ #include "cls/rbd/cls_rbd_types.h" #include "common/errno.h" #include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "librbd/Operations.h" #include "librbd/Utils.h" #include @@ -73,40 +75,119 @@ public: } }; +class GetTrashVisitor : public boost::static_visitor { +public: + std::string* original_name; + + explicit GetTrashVisitor(std::string* original_name) + : original_name(original_name) { + } + + template + inline int operator()(const T&) const { + return -EINVAL; + } + + inline int operator()( + const cls::rbd::TrashSnapshotNamespace& snap_namespace) { + *original_name = snap_namespace.original_name; + return 0; + } +}; + } // anonymous namespace template int Snapshot::get_group_namespace(I *ictx, uint64_t snap_id, snap_group_namespace_t *group_snap) { - const SnapInfo *snap_info; - { - RWLock::RLocker snap_locker(ictx->snap_lock); - snap_info = ictx->get_snap_info(snap_id); - if (snap_info) { - GetGroupVisitor ggv = GetGroupVisitor(ictx->cct, &ictx->data_ctx, - group_snap); - int r = boost::apply_visitor(ggv, snap_info->snap_namespace); - if (r < 0) { - return r; - } - } + int r = ictx->state->refresh_if_required(); + if (r < 0) { + return r; + } + + RWLock::RLocker snap_locker(ictx->snap_lock); + auto snap_info = ictx->get_snap_info(snap_id); + if (snap_info == nullptr) { + return -ENOENT; + } + + GetGroupVisitor ggv = GetGroupVisitor(ictx->cct, &ictx->data_ctx, group_snap); + r = boost::apply_visitor(ggv, snap_info->snap_namespace); + if (r < 0) { + return r; } + + return 0; +} + +template +int Snapshot::get_trash_namespace(I *ictx, uint64_t snap_id, + std::string* original_name) { + int r = ictx->state->refresh_if_required(); + if (r < 0) { + return r; + } + + RWLock::RLocker snap_locker(ictx->snap_lock); + auto snap_info = ictx->get_snap_info(snap_id); + if (snap_info == nullptr) { + return -ENOENT; + } + + auto visitor = GetTrashVisitor(original_name); + r = boost::apply_visitor(visitor, snap_info->snap_namespace); + if (r < 0) { + return r; + } + return 0; } template int Snapshot::get_namespace_type(I *ictx, uint64_t snap_id, snap_namespace_type_t *namespace_type) { - const SnapInfo *snap_info; + int r = ictx->state->refresh_if_required(); + if (r < 0) { + return r; + } + + RWLock::RLocker l(ictx->snap_lock); + auto snap_info = ictx->get_snap_info(snap_id); + if (snap_info == nullptr) { + return -ENOENT; + } + + *namespace_type = static_cast( + cls::rbd::get_snap_namespace_type(snap_info->snap_namespace)); + return 0; +} + +template +int Snapshot::remove(I *ictx, uint64_t snap_id) { + ldout(ictx->cct, 20) << "snap_remove " << ictx << " " << snap_id << dendl; + + int r = ictx->state->refresh_if_required(); + if (r < 0) { + return r; + } + + cls::rbd::SnapshotNamespace snapshot_namespace; + std::string snapshot_name; { - RWLock::RLocker l(ictx->snap_lock); - snap_info = ictx->get_snap_info(snap_id); - if (snap_info) { - *namespace_type = static_cast( - cls::rbd::get_snap_namespace_type(snap_info->snap_namespace)); + RWLock::RLocker snap_locker(ictx->snap_lock); + auto it = ictx->snap_info.find(snap_id); + if (it == ictx->snap_info.end()) { + return -ENOENT; } + + snapshot_namespace = it->second.snap_namespace; + snapshot_name = it->second.name; } - return 0; + + C_SaferCond ctx; + ictx->operations->snap_remove(snapshot_namespace, snapshot_name, &ctx); + r = ctx.wait(); + return r; } } // namespace api diff --git a/src/librbd/api/Snapshot.h b/src/librbd/api/Snapshot.h index 6629b6973d27e..453861c40088b 100644 --- a/src/librbd/api/Snapshot.h +++ b/src/librbd/api/Snapshot.h @@ -5,6 +5,7 @@ #define CEPH_LIBRBD_API_SNAPSHOT_H #include "include/rbd/librbd.hpp" +#include namespace librbd { @@ -18,9 +19,14 @@ struct Snapshot { static int get_group_namespace(ImageCtxT *ictx, uint64_t snap_id, snap_group_namespace_t *group_snap); + static int get_trash_namespace(ImageCtxT *ictx, uint64_t snap_id, + std::string *original_name); + static int get_namespace_type(ImageCtxT *ictx, uint64_t snap_id, snap_namespace_type_t *namespace_type); + static int remove(ImageCtxT *ictx, uint64_t snap_id); + }; } // namespace api diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 68ef4303d5161..b46ceb5002f61 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1522,6 +1522,12 @@ namespace librbd { return r; } + int Image::snap_remove_by_id(uint64_t snap_id) + { + ImageCtx *ictx = (ImageCtx *)ctx; + return librbd::api::Snapshot<>::remove(ictx, snap_id); + } + int Image::snap_rollback(const char *snap_name) { ImageCtx *ictx = (ImageCtx *)ctx; @@ -1669,6 +1675,13 @@ namespace librbd { return r; } + int Image::snap_get_trash_namespace(uint64_t snap_id, + std::string* original_name) { + ImageCtx *ictx = (ImageCtx *)ctx; + return librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id, + original_name); + } + int Image::snap_set_limit(uint64_t limit) { ImageCtx *ictx = (ImageCtx *)ctx; @@ -3502,6 +3515,12 @@ extern "C" int rbd_snap_remove2(rbd_image_t image, const char *snap_name, uint32 return r; } +extern "C" int rbd_snap_remove_by_id(rbd_image_t image, uint64_t snap_id) +{ + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + return librbd::api::Snapshot<>::remove(ictx, snap_id); +} + extern "C" int rbd_snap_rollback(rbd_image_t image, const char *snap_name) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; @@ -4967,6 +4986,25 @@ extern "C" int rbd_snap_group_namespace_cleanup(rbd_snap_group_namespace_t *grou return 0; } +extern "C" int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id, + char *original_name, + size_t max_length) { + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + + std::string cpp_original_name; + int r = librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id, + &cpp_original_name); + if (r < 0) { + return r; + } + + if (cpp_original_name.length() >= max_length) { + return -ERANGE; + } + + strcpy(original_name, cpp_original_name.c_str()); + return 0; +} extern "C" int rbd_watchers_list(rbd_image_t image, rbd_image_watcher_t *watchers, size_t *max_watchers) { diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index aac06e3a59793..cde5e85096faf 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -3168,6 +3168,24 @@ TEST_F(TestLibRBD, TestClone2) ASSERT_PASSED(validate_object_map, child); ASSERT_PASSED(validate_object_map, parent); + rbd_snap_info_t snaps[2]; + int max_snaps = 2; + ASSERT_EQ(1, rbd_snap_list(parent, snaps, &max_snaps)); + rbd_snap_list_end(snaps); + + ASSERT_EQ(0, rbd_snap_remove_by_id(parent, snaps[0].id)); + + rbd_snap_namespace_type_t snap_namespace_type; + ASSERT_EQ(0, rbd_snap_get_namespace_type(parent, snaps[0].id, + &snap_namespace_type)); + ASSERT_EQ(RBD_SNAP_NAMESPACE_TYPE_TRASH, snap_namespace_type); + + char original_name[32]; + ASSERT_EQ(0, rbd_snap_get_trash_namespace(parent, snaps[0].id, + original_name, + sizeof(original_name))); + ASSERT_EQ(0, strcmp("parent_snap", original_name)); + ASSERT_EQ(0, rbd_close(child)); ASSERT_EQ(0, rbd_close(parent)); rados_ioctx_destroy(ioctx); -- 2.39.5