From 4b48b9fe68623f1d9283eec0fd7a38ee60c18ce5 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Fri, 28 Apr 2017 10:05:57 -0400 Subject: [PATCH] librbd: extended parent info API to retrieve parent id Signed-off-by: Jason Dillaman --- src/include/rbd/librbd.h | 9 +++++- src/include/rbd/librbd.hpp | 4 ++- src/librbd/internal.cc | 6 +++- src/librbd/internal.h | 3 +- src/librbd/librbd.cc | 63 +++++++++++++++++++++++++++++-------- src/pybind/rbd/rbd.pyx | 39 +++++++++++++++++++---- src/test/pybind/test_rbd.py | 5 +++ src/tracing/librbd.tp | 2 ++ 8 files changed, 108 insertions(+), 23 deletions(-) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index b435feac1ee1d..289640a499da1 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -1,4 +1,4 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* * Ceph - scalable distributed file system @@ -370,6 +370,13 @@ CEPH_RBD_API int rbd_get_parent_info(rbd_image_t image, char *parent_name, size_t pnamelen, char *parent_snapname, size_t psnapnamelen); +CEPH_RBD_API int rbd_get_parent_info2(rbd_image_t image, + char *parent_poolname, + size_t ppoolnamelen, + char *parent_name, size_t pnamelen, + char *parent_id, size_t pidlen, + char *parent_snapname, + size_t psnapnamelen); CEPH_RBD_API int rbd_get_flags(rbd_image_t image, uint64_t *flags); CEPH_RBD_API int rbd_set_image_notification(rbd_image_t image, int fd, int type); diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index f404494b1be6b..d774b9d10ae6b 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -253,7 +253,9 @@ public: std::string get_block_name_prefix(); int64_t get_data_pool_id(); int parent_info(std::string *parent_poolname, std::string *parent_name, - std::string *parent_snapname); + std::string *parent_snapname); + int parent_info2(std::string *parent_poolname, std::string *parent_name, + std::string *parent_id, std::string *parent_snapname); int old_format(uint8_t *old); int size(uint64_t *size); int get_group(group_spec_t *group_spec); diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index af7a3c60fc692..1168afac7f730 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -1045,7 +1045,8 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { } int get_parent_info(ImageCtx *ictx, string *parent_pool_name, - string *parent_name, string *parent_snap_name) + string *parent_name, string *parent_id, + string *parent_snap_name) { int r = ictx->state->refresh_if_required(); if (r < 0) @@ -1097,6 +1098,9 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { RWLock::RLocker snap_locker(ictx->parent->snap_lock); *parent_name = ictx->parent->name; } + if (parent_id) { + *parent_id = ictx->parent->id; + } return 0; } diff --git a/src/librbd/internal.h b/src/librbd/internal.h index 59c9fad926a3a..cf07472b1af0e 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -128,7 +128,8 @@ namespace librbd { int get_features(ImageCtx *ictx, uint64_t *features); int get_overlap(ImageCtx *ictx, uint64_t *overlap); int get_parent_info(ImageCtx *ictx, std::string *parent_pool_name, - std::string *parent_name, std::string *parent_snap_name); + std::string *parent_name, std::string *parent_id, + std::string *parent_snap_name); int get_flags(ImageCtx *ictx, uint64_t *flags); int set_image_notification(ImageCtx *ictx, int fd, int type); int is_exclusive_lock_owner(ImageCtx *ictx, bool *is_owner); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 5a4bf51d5ba33..a2180170cf3e2 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1029,12 +1029,24 @@ namespace librbd { int Image::parent_info(string *parent_pool_name, string *parent_name, string *parent_snap_name) + { + return parent_info2(parent_pool_name, parent_name, nullptr, + parent_snap_name); + } + + int Image::parent_info2(string *parent_pool_name, string *parent_name, + string *parent_id, string *parent_snap_name) { ImageCtx *ictx = (ImageCtx *)ctx; - tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only); + tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(), + ictx->snap_name.c_str(), ictx->read_only); int r = librbd::get_parent_info(ictx, parent_pool_name, parent_name, - parent_snap_name); - tracepoint(librbd, get_parent_info_exit, r, parent_pool_name ? parent_pool_name->c_str() : NULL, parent_name ? parent_name->c_str() : NULL, parent_snap_name ? parent_snap_name->c_str() : NULL); + parent_id, parent_snap_name); + tracepoint(librbd, get_parent_info_exit, r, + parent_pool_name ? parent_pool_name->c_str() : NULL, + parent_name ? parent_name->c_str() : NULL, + parent_id ? parent_id->c_str() : NULL, + parent_snap_name ? parent_snap_name->c_str() : NULL); return r; } @@ -2825,22 +2837,38 @@ extern "C" int64_t rbd_get_data_pool_id(rbd_image_t image) } extern "C" int rbd_get_parent_info(rbd_image_t image, - char *parent_pool_name, size_t ppool_namelen, char *parent_name, - size_t pnamelen, char *parent_snap_name, size_t psnap_namelen) + char *parent_pool_name, size_t ppool_namelen, + char *parent_name, size_t pnamelen, + char *parent_snap_name, size_t psnap_namelen) +{ + return rbd_get_parent_info2(image, parent_pool_name, ppool_namelen, + parent_name, pnamelen, nullptr, 0, + parent_snap_name, psnap_namelen); +} + +extern "C" int rbd_get_parent_info2(rbd_image_t image, + char *parent_pool_name, + size_t ppool_namelen, + char *parent_name, size_t pnamelen, + char *parent_id, size_t pidlen, + char *parent_snap_name, + size_t psnap_namelen) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; - tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only); - string p_pool_name, p_name, p_snap_name; + tracepoint(librbd, get_parent_info_enter, ictx, ictx->name.c_str(), + ictx->snap_name.c_str(), ictx->read_only); + string p_pool_name, p_name, p_id, p_snap_name; - int r = librbd::get_parent_info(ictx, &p_pool_name, &p_name, &p_snap_name); + int r = librbd::get_parent_info(ictx, &p_pool_name, &p_name, &p_id, + &p_snap_name); if (r < 0) { - tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL); + tracepoint(librbd, get_parent_info_exit, r, NULL, NULL, NULL, NULL); return r; } if (parent_pool_name) { if (p_pool_name.length() + 1 > ppool_namelen) { - tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL); + tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL); return -ERANGE; } @@ -2848,22 +2876,31 @@ extern "C" int rbd_get_parent_info(rbd_image_t image, } if (parent_name) { if (p_name.length() + 1 > pnamelen) { - tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL); + tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL); return -ERANGE; } strcpy(parent_name, p_name.c_str()); } + if (parent_id) { + if (p_id.length() + 1 > pidlen) { + tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL); + return -ERANGE; + } + + strcpy(parent_id, p_id.c_str()); + } if (parent_snap_name) { if (p_snap_name.length() + 1 > psnap_namelen) { - tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL); + tracepoint(librbd, get_parent_info_exit, -ERANGE, NULL, NULL, NULL, NULL); return -ERANGE; } strcpy(parent_snap_name, p_snap_name.c_str()); } - tracepoint(librbd, get_parent_info_exit, 0, parent_pool_name, parent_name, parent_snap_name); + tracepoint(librbd, get_parent_info_exit, 0, parent_pool_name, parent_name, + parent_id, parent_snap_name); return 0; } diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 08d067bf53479..3457fcc0a675a 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -229,10 +229,11 @@ cdef extern from "rbd/librbd.h" nogil: int rbd_get_id(rbd_image_t image, char *id, size_t id_len) int rbd_get_block_name_prefix(rbd_image_t image, char *prefix, size_t prefix_len) - int rbd_get_parent_info(rbd_image_t image, - char *parent_poolname, size_t ppoolnamelen, - char *parent_name, size_t pnamelen, - char *parent_snapname, size_t psnapnamelen) + int rbd_get_parent_info2(rbd_image_t image, + char *parent_poolname, size_t ppoolnamelen, + char *parent_name, size_t pnamelen, + char *parent_id, size_t pidlen, + char *parent_snapname, size_t psnapnamelen) int rbd_get_flags(rbd_image_t image, uint64_t *flags) ssize_t rbd_read2(rbd_image_t image, uint64_t ofs, size_t len, char *buf, int op_flags) @@ -1506,8 +1507,8 @@ cdef class Image(object): name = realloc_chk(name, size) snapname = realloc_chk(snapname, size) with nogil: - ret = rbd_get_parent_info(self.image, pool, size, name, - size, snapname, size) + ret = rbd_get_parent_info2(self.image, pool, size, name, + size, NULL, 0, snapname, size) if ret == -errno.ERANGE: size *= 2 @@ -1519,6 +1520,32 @@ cdef class Image(object): free(name) free(snapname) + def parent_id(self): + """ + Get image id of a cloned image's parent (if any) + + :returns: str - the parent id + :raises: :class:`ImageNotFound` if the image doesn't have a parent + """ + cdef: + int ret = -errno.ERANGE + size_t size = 32 + char *parent_id = NULL + try: + while ret == -errno.ERANGE and size <= 4096: + parent_id = realloc_chk(parent_id, size) + with nogil: + ret = rbd_get_parent_info2(self.image, NULL, 0, NULL, 0, + parent_id, size, NULL, 0) + if ret == -errno.ERANGE: + size *= 2 + + if ret != 0: + raise make_ex(ret, 'error getting parent id for image %s' % (self.name,)) + return decode_cstr(parent_id) + finally: + free(parent_id) + def old_format(self): """ Find out whether the image uses the old RBD format. diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index c3eb371d5e623..57c35fd82c817 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -938,6 +938,7 @@ class TestClone(object): eq(pool, pool_name) eq(image, image_name) eq(snap, 'snap1') + eq(self.image.id(), self.clone.parent_id()) # create a new pool... pool_name2 = get_temp_pool_name() @@ -954,6 +955,7 @@ class TestClone(object): eq(pool, pool_name) eq(image, image_name) eq(snap, 'snap1') + eq(self.image.id(), self.other_clone.parent_id()) # can't unprotect snap with children assert_raises(ImageBusy, self.image.unprotect_snap, 'snap1') @@ -1127,6 +1129,8 @@ class TestClone(object): clone.flatten() assert_raises(ImageNotFound, clone.parent_info) assert_raises(ImageNotFound, clone2.parent_info) + assert_raises(ImageNotFound, clone.parent_id) + assert_raises(ImageNotFound, clone2.parent_id) after_flatten = clone.read(IMG_SIZE // 2, 256) eq(data, after_flatten) after_flatten = clone2.read(IMG_SIZE // 2, 256) @@ -1220,6 +1224,7 @@ class TestExclusiveLock(object): image1.write(data, 0) image2.flatten() assert_raises(ImageNotFound, image1.parent_info) + assert_raises(ImageNotFound, image1.parent_id) parent = True for x in range(30): try: diff --git a/src/tracing/librbd.tp b/src/tracing/librbd.tp index 95ccaa6695531..7078390daed9c 100644 --- a/src/tracing/librbd.tp +++ b/src/tracing/librbd.tp @@ -1851,11 +1851,13 @@ TRACEPOINT_EVENT(librbd, get_parent_info_exit, int, retval, const char*, parent_pool_name, const char*, parent_name, + const char*, parent_id, const char*, parent_snap_name), TP_FIELDS( ctf_integer(int, retval, retval) ceph_ctf_string(parent_pool_name, parent_pool_name) ceph_ctf_string(parent_name, parent_name) + ceph_ctf_string(parent_id, parent_id) ceph_ctf_string(parent_snap_name, parent_snap_name) ) ) -- 2.39.5