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,
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);
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);
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);
#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 <boost/variant.hpp>
}
};
+class GetTrashVisitor : public boost::static_visitor<int> {
+public:
+ std::string* original_name;
+
+ explicit GetTrashVisitor(std::string* original_name)
+ : original_name(original_name) {
+ }
+
+ template <typename T>
+ 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 <typename I>
int Snapshot<I>::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 <typename I>
+int Snapshot<I>::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 <typename I>
int Snapshot<I>::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<snap_namespace_type_t>(
+ cls::rbd::get_snap_namespace_type(snap_info->snap_namespace));
+ return 0;
+}
+
+template <typename I>
+int Snapshot<I>::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<snap_namespace_type_t>(
- 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
#define CEPH_LIBRBD_API_SNAPSHOT_H
#include "include/rbd/librbd.hpp"
+#include <string>
namespace librbd {
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
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;
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;
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;
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) {
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);