Skip to content

Commit

Permalink
librbd: add snapshot trash namespace helper and remove_by_id
Browse files Browse the repository at this point in the history
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit c412811)
  • Loading branch information
Jason Dillaman committed Aug 14, 2018
1 parent 8878eb0 commit 3f3daf4
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 19 deletions.
5 changes: 5 additions & 0 deletions src/include/rbd/librbd.h
Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions src/include/rbd/librbd.hpp
Expand Up @@ -375,6 +375,7 @@ class CEPH_RBD_API 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);
Expand All @@ -391,6 +392,7 @@ class CEPH_RBD_API Image
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);
Expand Down
119 changes: 100 additions & 19 deletions src/librbd/api/Snapshot.cc
Expand Up @@ -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 <boost/variant.hpp>

Expand Down Expand Up @@ -72,40 +74,119 @@ class GetGroupVisitor : public boost::static_visitor<int> {
}
};

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
Expand Down
6 changes: 6 additions & 0 deletions src/librbd/api/Snapshot.h
Expand Up @@ -5,6 +5,7 @@
#define CEPH_LIBRBD_API_SNAPSHOT_H

#include "include/rbd/librbd.hpp"
#include <string>

namespace librbd {

Expand All @@ -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
Expand Down
38 changes: 38 additions & 0 deletions src/librbd/librbd.cc
Expand Up @@ -1508,6 +1508,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;
Expand Down Expand Up @@ -1655,6 +1661,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;
Expand Down Expand Up @@ -3440,6 +3453,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;
Expand Down Expand Up @@ -4905,6 +4924,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) {
Expand Down
18 changes: 18 additions & 0 deletions src/test/librbd/test_librbd.cc
Expand Up @@ -3120,6 +3120,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);
Expand Down

0 comments on commit 3f3daf4

Please sign in to comment.