Skip to content

Commit ed09f34

Browse files
committed
librbd: add rbd_snap_get_trash_namespace2() API to return full namespace
The existing rbd_snap_get_trash_namespace() API returns only the original name of the deleted snapshot, omitting its namespace type. While non-user snapshots have distinctive names, there is nothing preventing the user from creating user snapshots with identical names (i.e. starting with ".group" or ".mirror" prefix). After cloning from non-user snapshots is allowed, it's possible for such user snapshots to get mixed up with non-user snapshots in the trash, so let's provide means for disambiguation. Signed-off-by: Ilya Dryomov <[email protected]>
1 parent fa29a6e commit ed09f34

File tree

9 files changed

+128
-35
lines changed

9 files changed

+128
-35
lines changed

src/include/rbd/librbd.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,11 @@ typedef struct {
260260
char *group_snap_name;
261261
} rbd_snap_group_namespace_t;
262262

263+
typedef struct {
264+
rbd_snap_namespace_type_t original_namespace_type;
265+
char *original_name;
266+
} rbd_snap_trash_namespace_t;
267+
263268
typedef enum {
264269
RBD_SNAP_MIRROR_STATE_PRIMARY,
265270
RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED,
@@ -968,6 +973,11 @@ CEPH_RBD_API int rbd_snap_get_trash_namespace(rbd_image_t image,
968973
uint64_t snap_id,
969974
char* original_name,
970975
size_t max_length);
976+
CEPH_RBD_API int rbd_snap_get_trash_namespace2(
977+
rbd_image_t image, uint64_t snap_id,
978+
rbd_snap_trash_namespace_t *trash_snap, size_t trash_snap_size);
979+
CEPH_RBD_API int rbd_snap_trash_namespace_cleanup(
980+
rbd_snap_trash_namespace_t *trash_snap, size_t trash_snap_size);
971981
CEPH_RBD_API int rbd_snap_get_mirror_namespace(
972982
rbd_image_t image, uint64_t snap_id,
973983
rbd_snap_mirror_namespace_t *mirror_snap, size_t mirror_snap_size);

src/include/rbd/librbd.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ namespace librbd {
7373
std::string group_snap_name;
7474
} snap_group_namespace_t;
7575

76+
typedef struct {
77+
snap_namespace_type_t original_namespace_type;
78+
std::string original_name;
79+
} snap_trash_namespace_t;
80+
7681
typedef rbd_snap_mirror_state_t snap_mirror_state_t;
7782

7883
typedef struct {
@@ -679,6 +684,9 @@ class CEPH_RBD_API Image
679684
snap_group_namespace_t *group_namespace,
680685
size_t snap_group_namespace_size);
681686
int snap_get_trash_namespace(uint64_t snap_id, std::string* original_name);
687+
int snap_get_trash_namespace2(uint64_t snap_id,
688+
snap_trash_namespace_t *trash_namespace,
689+
size_t snap_trash_namespace_size);
682690
int snap_get_mirror_namespace(
683691
uint64_t snap_id, snap_mirror_namespace_t *mirror_namespace,
684692
size_t snap_mirror_namespace_size);

src/librbd/api/Snapshot.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ class GetGroupVisitor {
8282

8383
class GetTrashVisitor {
8484
public:
85-
std::string* original_name;
85+
snap_trash_namespace_t *trash_snap;
8686

87-
explicit GetTrashVisitor(std::string* original_name)
88-
: original_name(original_name) {
87+
explicit GetTrashVisitor(snap_trash_namespace_t *trash_snap)
88+
: trash_snap(trash_snap) {
8989
}
9090

9191
template <typename T>
@@ -95,7 +95,9 @@ class GetTrashVisitor {
9595

9696
inline int operator()(
9797
const cls::rbd::TrashSnapshotNamespace& snap_namespace) {
98-
*original_name = snap_namespace.original_name;
98+
trash_snap->original_namespace_type = static_cast<snap_namespace_type_t>(
99+
snap_namespace.original_snapshot_namespace_type);
100+
trash_snap->original_name = snap_namespace.original_name;
99101
return 0;
100102
}
101103
};
@@ -153,7 +155,7 @@ int Snapshot<I>::get_group_namespace(I *ictx, uint64_t snap_id,
153155

154156
template <typename I>
155157
int Snapshot<I>::get_trash_namespace(I *ictx, uint64_t snap_id,
156-
std::string* original_name) {
158+
snap_trash_namespace_t *trash_snap) {
157159
int r = ictx->state->refresh_if_required();
158160
if (r < 0) {
159161
return r;
@@ -165,7 +167,7 @@ int Snapshot<I>::get_trash_namespace(I *ictx, uint64_t snap_id,
165167
return -ENOENT;
166168
}
167169

168-
auto visitor = GetTrashVisitor(original_name);
170+
auto visitor = GetTrashVisitor(trash_snap);
169171
r = snap_info->snap_namespace.visit(visitor);
170172
if (r < 0) {
171173
return r;

src/librbd/api/Snapshot.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct Snapshot {
2121
snap_group_namespace_t *group_snap);
2222

2323
static int get_trash_namespace(ImageCtxT *ictx, uint64_t snap_id,
24-
std::string *original_name);
24+
snap_trash_namespace_t *trash_snap);
2525

2626
static int get_mirror_namespace(
2727
ImageCtxT *ictx, uint64_t snap_id,

src/librbd/librbd.cc

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,8 +2497,29 @@ namespace librbd {
24972497
int Image::snap_get_trash_namespace(uint64_t snap_id,
24982498
std::string* original_name) {
24992499
ImageCtx *ictx = (ImageCtx *)ctx;
2500+
2501+
snap_trash_namespace_t trash_snap;
2502+
int r = librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id,
2503+
&trash_snap);
2504+
if (r < 0) {
2505+
return r;
2506+
}
2507+
2508+
*original_name = trash_snap.original_name;
2509+
return 0;
2510+
}
2511+
2512+
int Image::snap_get_trash_namespace2(
2513+
uint64_t snap_id, snap_trash_namespace_t *trash_snap,
2514+
size_t trash_snap_size) {
2515+
ImageCtx *ictx = (ImageCtx *)ctx;
2516+
2517+
if (trash_snap_size != sizeof(snap_trash_namespace_t)) {
2518+
return -ERANGE;
2519+
}
2520+
25002521
return librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id,
2501-
original_name);
2522+
trash_snap);
25022523
}
25032524

25042525
int Image::snap_get_mirror_namespace(
@@ -7369,18 +7390,50 @@ extern "C" int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id,
73697390
size_t max_length) {
73707391
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
73717392

7372-
std::string cpp_original_name;
7393+
librbd::snap_trash_namespace_t trash_namespace;
73737394
int r = librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id,
7374-
&cpp_original_name);
7395+
&trash_namespace);
73757396
if (r < 0) {
73767397
return r;
73777398
}
73787399

7379-
if (cpp_original_name.length() >= max_length) {
7400+
if (trash_namespace.original_name.length() >= max_length) {
7401+
return -ERANGE;
7402+
}
7403+
7404+
strcpy(original_name, trash_namespace.original_name.c_str());
7405+
return 0;
7406+
}
7407+
7408+
extern "C" int rbd_snap_get_trash_namespace2(
7409+
rbd_image_t image, uint64_t snap_id,
7410+
rbd_snap_trash_namespace_t *trash_snap,
7411+
size_t trash_snap_size) {
7412+
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
7413+
7414+
if (trash_snap_size != sizeof(rbd_snap_trash_namespace_t)) {
7415+
return -ERANGE;
7416+
}
7417+
7418+
librbd::snap_trash_namespace_t trash_namespace;
7419+
int r = librbd::api::Snapshot<>::get_trash_namespace(ictx, snap_id,
7420+
&trash_namespace);
7421+
if (r < 0) {
7422+
return r;
7423+
}
7424+
7425+
trash_snap->original_namespace_type = trash_namespace.original_namespace_type;
7426+
trash_snap->original_name = strdup(trash_namespace.original_name.c_str());
7427+
return 0;
7428+
}
7429+
7430+
extern "C" int rbd_snap_trash_namespace_cleanup(
7431+
rbd_snap_trash_namespace_t *trash_snap, size_t trash_snap_size) {
7432+
if (trash_snap_size != sizeof(rbd_snap_trash_namespace_t)) {
73807433
return -ERANGE;
73817434
}
73827435

7383-
strcpy(original_name, cpp_original_name.c_str());
7436+
free(trash_snap->original_name);
73847437
return 0;
73857438
}
73867439

src/pybind/rbd/c_rbd.pxd

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ cdef extern from "rbd/librbd.h" nogil:
8686
char *group_name
8787
char *group_snap_name
8888

89+
ctypedef struct rbd_snap_trash_namespace_t:
90+
rbd_snap_namespace_type_t original_namespace_type;
91+
char *original_name;
92+
8993
ctypedef enum rbd_snap_mirror_state_t:
9094
_RBD_SNAP_MIRROR_STATE_PRIMARY "RBD_SNAP_MIRROR_STATE_PRIMARY"
9195
_RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED "RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED"
@@ -549,8 +553,11 @@ cdef extern from "rbd/librbd.h" nogil:
549553
size_t snap_group_namespace_size)
550554
void rbd_snap_group_namespace_cleanup(rbd_snap_group_namespace_t *group_spec,
551555
size_t snap_group_namespace_size)
552-
int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id,
553-
char *original_name, size_t max_length)
556+
int rbd_snap_get_trash_namespace2(rbd_image_t image, uint64_t snap_id,
557+
rbd_snap_trash_namespace_t *trash_snap,
558+
size_t trash_snap_size)
559+
void rbd_snap_trash_namespace_cleanup(rbd_snap_trash_namespace_t *trash_snap,
560+
size_t trash_snap_size)
554561
int rbd_snap_get_mirror_namespace(
555562
rbd_image_t image, uint64_t snap_id,
556563
rbd_snap_mirror_namespace_t *mirror_ns,

src/pybind/rbd/mock_rbd.pxi

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ cdef nogil:
9090
char *group_name
9191
char *group_snap_name
9292

93+
ctypedef struct rbd_snap_trash_namespace_t:
94+
rbd_snap_namespace_type_t original_namespace_type;
95+
char *original_name;
96+
9397
ctypedef enum rbd_snap_mirror_state_t:
9498
_RBD_SNAP_MIRROR_STATE_PRIMARY "RBD_SNAP_MIRROR_STATE_PRIMARY"
9599
_RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED "RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED"
@@ -677,8 +681,12 @@ cdef nogil:
677681
void rbd_snap_group_namespace_cleanup(rbd_snap_group_namespace_t *group_spec,
678682
size_t snap_group_namespace_size):
679683
pass
680-
int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id,
681-
char *original_name, size_t max_length):
684+
int rbd_snap_get_trash_namespace2(rbd_image_t image, uint64_t snap_id,
685+
rbd_snap_trash_namespace_t *trash_snap,
686+
size_t trash_snap_size):
687+
pass
688+
void rbd_snap_trash_namespace_cleanup(rbd_snap_trash_namespace_t *trash_snap,
689+
size_t trash_snap_size):
682690
pass
683691
int rbd_snap_get_mirror_namespace(
684692
rbd_image_t image, uint64_t snap_id,

src/pybind/rbd/rbd.pyx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5190,28 +5190,26 @@ written." % (self.name, ret, length))
51905190
:type key: int
51915191
:returns: dict - contains the following keys:
51925192
5193+
* ``original_namespace_type`` (int) - original snap namespace type
5194+
51935195
* ``original_name`` (str) - original snap name
51945196
"""
51955197
cdef:
5198+
rbd_snap_trash_namespace_t trash_snap
51965199
uint64_t _snap_id = snap_id
5197-
size_t _size = 512
5198-
char *_name = NULL
5199-
try:
5200-
while True:
5201-
_name = <char*>realloc_chk(_name, _size);
5202-
with nogil:
5203-
ret = rbd_snap_get_trash_namespace(self.image, _snap_id,
5204-
_name, _size)
5205-
if ret >= 0:
5206-
break
5207-
elif ret != -errno.ERANGE:
5208-
raise make_ex(ret, 'error getting snapshot trash '
5209-
'namespace image: %s, snap_id: %d' % (self.name, snap_id))
5210-
return {
5211-
'original_name' : decode_cstr(_name)
5212-
}
5213-
finally:
5214-
free(_name)
5200+
with nogil:
5201+
ret = rbd_snap_get_trash_namespace2(self.image, _snap_id,
5202+
&trash_snap, sizeof(trash_snap))
5203+
if ret != 0:
5204+
raise make_ex(ret, 'error getting snapshot trash '
5205+
'namespace for image: %s, snap_id: %d' %
5206+
(self.name, snap_id))
5207+
result = {
5208+
'original_namespace_type' : trash_snap.original_namespace_type,
5209+
'original_name' : decode_cstr(trash_snap.original_name)
5210+
}
5211+
rbd_snap_trash_namespace_cleanup(&trash_snap, sizeof(trash_snap))
5212+
return result
52155213

52165214
@requires_not_closed
52175215
def snap_get_mirror_namespace(self, snap_id):

src/test/pybind/test_rbd.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
RBD_MIRROR_IMAGE_MODE_JOURNAL, RBD_MIRROR_IMAGE_MODE_SNAPSHOT,
3535
RBD_LOCK_MODE_EXCLUSIVE, RBD_OPERATION_FEATURE_GROUP,
3636
RBD_OPERATION_FEATURE_CLONE_CHILD,
37+
RBD_SNAP_NAMESPACE_TYPE_USER,
3738
RBD_SNAP_NAMESPACE_TYPE_GROUP,
3839
RBD_SNAP_NAMESPACE_TYPE_TRASH,
3940
RBD_SNAP_NAMESPACE_TYPE_MIRROR,
@@ -1852,6 +1853,7 @@ def test_clone_by_snap_id(self):
18521853
self.image.remove_snap('snap2')
18531854
trash_snap = self.image.snap_get_trash_namespace(snap_id)
18541855
assert trash_snap == {
1856+
'original_namespace_type' : RBD_SNAP_NAMESPACE_TYPE_USER,
18551857
'original_name' : 'snap2'
18561858
}
18571859
clone_name3 = get_temp_image_name()
@@ -2148,7 +2150,11 @@ def test_trash_snapshot(self):
21482150

21492151
snaps = [s for s in self.image.list_snaps() if s['name'] != 'snap1']
21502152
eq([RBD_SNAP_NAMESPACE_TYPE_TRASH], [s['namespace'] for s in snaps])
2151-
eq([{'original_name' : 'snap2'}], [s['trash'] for s in snaps])
2153+
trash_snap = {
2154+
'original_namespace_type' : RBD_SNAP_NAMESPACE_TYPE_USER,
2155+
'original_name' : 'snap2'
2156+
}
2157+
eq([trash_snap], [s['trash'] for s in snaps])
21522158

21532159
self.rbd.remove(ioctx, clone_name)
21542160
eq([], [s for s in self.image.list_snaps() if s['name'] != 'snap1'])
@@ -2993,6 +2999,7 @@ def test_group_snap_clone(self):
29932999
trash_image_snap_name = image_snaps[0]['name']
29943000
assert image_snaps[0]['id'] == image_snap_id
29953001
assert image_snaps[0]['trash'] == {
3002+
'original_namespace_type' : RBD_SNAP_NAMESPACE_TYPE_GROUP,
29963003
'original_name' : image_snap_name
29973004
}
29983005
assert trash_image_snap_name != image_snap_name

0 commit comments

Comments
 (0)