From 9debf5c98a6dc1d0bce7f3b597748d3c70f4520d Mon Sep 17 00:00:00 2001 From: Pan Liu Date: Sun, 29 Jan 2017 00:43:33 +0800 Subject: [PATCH] librbd: support to list snapshot time stamp Fixes: http://tracker.ceph.com/issues/808 Signed-off-by: Pan Liu --- src/cls/rbd/cls_rbd.cc | 33 +++++++++ src/cls/rbd/cls_rbd_client.cc | 74 ++++++++++++++----- src/cls/rbd/cls_rbd_client.h | 27 +++++-- src/include/rbd/librbd.h | 9 +++ src/include/rbd/librbd.hpp | 1 + src/librbd/SnapInfo.h | 5 +- src/librbd/image/RefreshRequest.cc | 57 ++++++++++++-- src/librbd/image/RefreshRequest.h | 8 ++ src/librbd/internal.cc | 9 +++ src/librbd/internal.h | 1 + src/librbd/librbd.cc | 18 +++++ src/pybind/rbd/rbd.pyx | 18 +++++ .../librbd/image/test_mock_RefreshRequest.cc | 12 +++ src/tools/rbd/action/Snap.cc | 13 +++- src/tracing/librbd.tp | 18 +++++ 15 files changed, 269 insertions(+), 34 deletions(-) diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 8f86ca13f9713..ae8cf9185d163 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -1455,6 +1455,35 @@ int get_snapshot_name(cls_method_context_t hctx, bufferlist *in, bufferlist *out return 0; } +int get_snapshot_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + uint64_t snap_id; + + bufferlist::iterator iter = in->begin(); + try { + ::decode(snap_id, iter); + } catch (const buffer::error &err) { + return -EINVAL; + } + + CLS_LOG(20, "get_snapshot_timestamp snap_id=%llu", (unsigned long long)snap_id); + + if (snap_id == CEPH_NOSNAP) { + return -EINVAL; + } + + cls_rbd_snap snap; + string snapshot_key; + key_from_snap_id(snap_id, &snapshot_key); + int r = read_key(hctx, snapshot_key, &snap); + if (r < 0) { + return r; + } + + ::encode(snap.timestamp, *out); + return 0; +} + /** * Retrieve namespace of a snapshot. * @@ -4746,6 +4775,7 @@ CLS_INIT(rbd) cls_method_handle_t h_get_data_pool; cls_method_handle_t h_get_snapshot_name; cls_method_handle_t h_get_snapshot_namespace; + cls_method_handle_t h_get_snapshot_timestamp; cls_method_handle_t h_snapshot_add; cls_method_handle_t h_snapshot_remove; cls_method_handle_t h_snapshot_rename; @@ -4836,6 +4866,9 @@ CLS_INIT(rbd) cls_register_cxx_method(h_class, "get_snapshot_namespace", CLS_METHOD_RD, get_snapshot_namespace, &h_get_snapshot_namespace); + cls_register_cxx_method(h_class, "get_snapshot_timestamp", + CLS_METHOD_RD, + get_snapshot_timestamp, &h_get_snapshot_timestamp); cls_register_cxx_method(h_class, "snapshot_add", CLS_METHOD_RD | CLS_METHOD_WR, snapshot_add, &h_snapshot_add); diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index c0f3da7785829..517bea56809e2 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -525,9 +525,7 @@ namespace librbd { void snapshot_list_start(librados::ObjectReadOperation *op, const std::vector &ids) { - for (vector::const_iterator it = ids.begin(); - it != ids.end(); ++it) { - snapid_t snap_id = it->val; + for (auto snap_id : ids) { bufferlist bl1, bl2, bl3, bl4; ::encode(snap_id, bl1); op->exec("rbd", "get_snapshot_name", bl1); @@ -594,21 +592,63 @@ namespace librbd { protection_statuses); } - void snap_namespace_list_start(librados::ObjectReadOperation *op, - const std::vector &ids) + void snapshot_timestamp_list_start(librados::ObjectReadOperation *op, + const std::vector &ids) { - for (vector::const_iterator it = ids.begin(); - it != ids.end(); ++it) { - snapid_t snap_id = it->val; + for (auto snap_id : ids) { bufferlist bl; ::encode(snap_id, bl); - op->exec("rbd", "get_snapshot_namespace", bl); + op->exec("rbd", "get_snapshot_timestamp", bl); } } - int snap_namespace_list_finish(bufferlist::iterator *it, - const std::vector &ids, - std::vector *namespaces) + int snapshot_timestamp_list_finish(bufferlist::iterator *it, + const std::vector &ids, + std::vector *timestamps) + { + timestamps->resize(ids.size()); + try { + for (size_t i = 0; i < timestamps->size(); ++i) { + utime_t t; + ::decode(t, *it); + (*timestamps)[i] = t; + } + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int snapshot_timestamp_list(librados::IoCtx *ioctx, const std::string &oid, + const std::vector &ids, + std::vector *timestamps) + { + librados::ObjectReadOperation op; + snapshot_timestamp_list_start(&op, ids); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return snapshot_timestamp_list_finish(&it, ids, timestamps); + } + + void snapshot_namespace_list_start(librados::ObjectReadOperation *op, + const std::vector &ids) + { + for (auto snap_id : ids) { + bufferlist bl; + ::encode(snap_id, bl); + op->exec("rbd", "get_snapshot_namespace", bl); + } + } + + int snapshot_namespace_list_finish(bufferlist::iterator *it, + const std::vector &ids, + std::vector *namespaces) { namespaces->resize(ids.size()); try { @@ -623,12 +663,12 @@ namespace librbd { return 0; } - int snap_namespace_list(librados::IoCtx *ioctx, const std::string &oid, - const std::vector &ids, - std::vector *namespaces) + int snapshot_namespace_list(librados::IoCtx *ioctx, const std::string &oid, + const std::vector &ids, + std::vector *namespaces) { librados::ObjectReadOperation op; - snap_namespace_list_start(&op, ids); + snapshot_namespace_list_start(&op, ids); bufferlist out_bl; int r = ioctx->operate(oid, &op, &out_bl); @@ -637,7 +677,7 @@ namespace librbd { } bufferlist::iterator it = out_bl.begin(); - return snap_namespace_list_finish(&it, ids, namespaces); + return snapshot_namespace_list_finish(&it, ids, namespaces); } void old_snapshot_add(librados::ObjectWriteOperation *op, diff --git a/src/cls/rbd/cls_rbd_client.h b/src/cls/rbd/cls_rbd_client.h index 52f259d25c6fe..c1d1bd8bdd906 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -119,6 +119,17 @@ namespace librbd { std::vector *sizes, std::vector *parents, std::vector *protection_statuses); + void snapshot_timestamp_list_start(librados::ObjectReadOperation *op, + const std::vector &ids); + + int snapshot_timestamp_list_finish(bufferlist::iterator *it, + const std::vector &ids, + std::vector *timestamps); + + int snapshot_timestamp_list(librados::IoCtx *ioctx, const std::string &oid, + const std::vector &ids, + std::vector *timestamps); + int snapshot_list(librados::IoCtx *ioctx, const std::string &oid, const std::vector &ids, std::vector *names, @@ -126,14 +137,14 @@ namespace librbd { std::vector *parents, std::vector *protection_statuses); - void snap_namespace_list_start(librados::ObjectReadOperation *op, - const std::vector &ids); - int snap_namespace_list_finish(bufferlist::iterator *it, - const std::vector &ids, - std::vector *namespaces); - int snap_namespace_list(librados::IoCtx *ioctx, const std::string &oid, - const std::vector &ids, - std::vector *namespaces); + void snapshot_namespace_list_start(librados::ObjectReadOperation *op, + const std::vector &ids); + int snapshot_namespace_list_finish(bufferlist::iterator *it, + const std::vector &ids, + std::vector *namespaces); + int snapshot_namespace_list(librados::IoCtx *ioctx, const std::string &oid, + const std::vector &ids, + std::vector *namespaces); void get_all_features_start(librados::ObjectReadOperation *op); int get_all_features_finish(bufferlist::iterator *it, diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 45e9395a5e1b4..1bdc3551e9fd5 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -424,6 +424,15 @@ CEPH_RBD_API int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit); */ CEPH_RBD_API int rbd_snap_set_limit(rbd_image_t image, uint64_t limit); +/** + * Get the timestamp of a snapshot for an image. + * + * @param snap_id the snap id of a snapshot of input image. + * @param timestamp the timestamp of input snapshot. + * @returns 0 on success, negative error code on failure + */ +CEPH_RBD_API int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp); + CEPH_RBD_API int rbd_snap_set(rbd_image_t image, const char *snapname); 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 0ac92dea3c77f..66b62fd5cb66b 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -296,6 +296,7 @@ public: int snap_rename(const char *srcname, const char *dstname); int snap_get_limit(uint64_t *limit); int snap_set_limit(uint64_t limit); + int snap_get_timestamp(uint64_t snap_id, struct timespec *timestamp); /* I/O */ ssize_t read(uint64_t ofs, size_t len, ceph::bufferlist& bl); diff --git a/src/librbd/SnapInfo.h b/src/librbd/SnapInfo.h index 3bd0b98a629cf..f5de553f49a4a 100644 --- a/src/librbd/SnapInfo.h +++ b/src/librbd/SnapInfo.h @@ -17,11 +17,12 @@ namespace librbd { parent_info parent; uint8_t protection_status; uint64_t flags; + utime_t timestamp; SnapInfo(std::string _name, const cls::rbd::SnapshotNamespace &_snap_namespace, uint64_t _size, parent_info _parent, - uint8_t _protection_status, uint64_t _flags) + uint8_t _protection_status, uint64_t _flags, utime_t _timestamp) : name(_name), snap_namespace(_snap_namespace), size(_size), parent(_parent), - protection_status(_protection_status), flags(_flags) {} + protection_status(_protection_status), flags(_flags), timestamp(_timestamp) {} }; } diff --git a/src/librbd/image/RefreshRequest.cc b/src/librbd/image/RefreshRequest.cc index 9884a12bf9ce3..16a76def4e3bb 100644 --- a/src/librbd/image/RefreshRequest.cc +++ b/src/librbd/image/RefreshRequest.cc @@ -142,11 +142,12 @@ Context *RefreshRequest::handle_v1_get_snapshots(int *result) { } //m_snap_namespaces = {m_snap_names.size(), cls::rbd::UserSnapshotNamespace()}; - m_snap_namespaces = std::vector - ( + m_snap_namespaces = std::vector( m_snap_names.size(), cls::rbd::UserSnapshotNamespace()); + m_snap_timestamps = std::vector(m_snap_names.size(), utime_t()); + send_v1_get_locks(); return nullptr; } @@ -392,6 +393,7 @@ void RefreshRequest::send_v2_get_snapshots() { m_snap_sizes.clear(); m_snap_parents.clear(); m_snap_protection.clear(); + m_snap_timestamps.clear(); send_v2_refresh_parent(); return; } @@ -436,6 +438,49 @@ Context *RefreshRequest::handle_v2_get_snapshots(int *result) { return m_on_finish; } + send_v2_get_snap_timestamps(); + return nullptr; +} + +template +void RefreshRequest::send_v2_get_snap_timestamps() { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << this << " " << __func__ << dendl; + + librados::ObjectReadOperation op; + cls_client::snapshot_timestamp_list_start(&op, m_snapc.snaps); + + using klass = RefreshRequest; + librados::AioCompletion *comp = create_rados_ack_callback< + klass, &klass::handle_v2_get_snap_timestamps>(this); + m_out_bl.clear(); + int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op, + &m_out_bl); + assert(r == 0); + comp->release(); +} + +template +Context *RefreshRequest::handle_v2_get_snap_timestamps(int *result) { + CephContext *cct = m_image_ctx.cct; + ldout(cct, 10) << this << " " << __func__ << ": " << "r=" << *result << dendl; + + if (*result == 0) { + bufferlist::iterator it = m_out_bl.begin(); + *result = cls_client::snapshot_timestamp_list_finish(&it, m_snapc.snaps, &m_snap_timestamps); + } + if (*result == -ENOENT) { + ldout(cct, 10) << "out-of-sync snapshot state detected" << dendl; + send_v2_get_mutable_metadata(); + return nullptr; + } else if (*result == -EOPNOTSUPP) { + // Ignore it means no snap timestamps are available + } else if (*result < 0) { + lderr(cct) << "failed to retrieve snapshots: " << cpp_strerror(*result) + << dendl; + return m_on_finish; + } + send_v2_get_snap_namespaces(); return nullptr; } @@ -446,7 +491,7 @@ void RefreshRequest::send_v2_get_snap_namespaces() { ldout(cct, 10) << this << " " << __func__ << dendl; librados::ObjectReadOperation op; - cls_client::snap_namespace_list_start(&op, m_snapc.snaps); + cls_client::snapshot_namespace_list_start(&op, m_snapc.snaps); using klass = RefreshRequest; librados::AioCompletion *comp = create_rados_ack_callback< @@ -466,8 +511,8 @@ Context *RefreshRequest::handle_v2_get_snap_namespaces(int *result) { if (*result == 0) { bufferlist::iterator it = m_out_bl.begin(); - *result = cls_client::snap_namespace_list_finish(&it, m_snapc.snaps, - &m_snap_namespaces); + *result = cls_client::snapshot_namespace_list_finish(&it, m_snapc.snaps, + &m_snap_namespaces); } if (*result == -ENOENT) { ldout(cct, 10) << "out-of-sync snapshot state detected" << dendl; @@ -1004,7 +1049,7 @@ void RefreshRequest::apply() { } m_image_ctx.add_snap(m_snap_names[i], m_snap_namespaces[i], m_snapc.snaps[i].val, - m_snap_sizes[i], parent, protection_status, flags); + m_snap_sizes[i], parent, protection_status, flags, m_snap_timestamps[i]); } m_image_ctx.snapc = m_snapc; diff --git a/src/librbd/image/RefreshRequest.h b/src/librbd/image/RefreshRequest.h index 315dd7938b37b..8bc57ae10d7b6 100644 --- a/src/librbd/image/RefreshRequest.h +++ b/src/librbd/image/RefreshRequest.h @@ -6,6 +6,7 @@ #include "include/int_types.h" #include "include/buffer.h" +#include "include/utime.h" #include "common/snap_types.h" #include "cls/lock/cls_lock_types.h" #include "librbd/ImageCtx.h" @@ -60,6 +61,9 @@ private: * V2_GET_SNAPSHOTS (skip if no snaps) | * | | * v | + * V2_GET_SNAP_TIMESTAMPS | + * | | + * v | * V2_GET_SNAP_NAMESPACES | * | | * v | @@ -134,6 +138,7 @@ private: std::vector m_snap_parents; std::vector m_snap_protection; std::vector m_snap_flags; + std::vector m_snap_timestamps; std::map m_lockers; @@ -170,6 +175,9 @@ private: void send_v2_get_snap_namespaces(); Context *handle_v2_get_snap_namespaces(int *result); + void send_v2_get_snap_timestamps(); + Context *handle_v2_get_snap_timestamps(int *result); + void send_v2_refresh_parent(); Context *handle_v2_refresh_parent(int *result); diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index f946f2fa51ed5..2ac4f4329d400 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -1956,6 +1956,15 @@ void filter_out_mirror_watchers(ImageCtx *ictx, return r; } + int snap_get_timestamp(ImageCtx *ictx, uint64_t snap_id, struct timespec *timestamp) + { + std::map::iterator snap_it = ictx->snap_info.find(snap_id); + assert(snap_it != ictx->snap_info.end()); + utime_t time = snap_it->second.timestamp; + time.to_timespec(timestamp); + return 0; + } + int snap_get_limit(ImageCtx *ictx, uint64_t *limit) { int r = cls_client::snapshot_get_limit(&ictx->md_ctx, ictx->header_oid, diff --git a/src/librbd/internal.h b/src/librbd/internal.h index 550eecf9ac5c7..428c99ccd0871 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -144,6 +144,7 @@ namespace librbd { int snap_exists(ImageCtx *ictx, const char *snap_name, bool *exists); int snap_get_limit(ImageCtx *ictx, uint64_t *limit); int snap_set_limit(ImageCtx *ictx, uint64_t limit); + int snap_get_timestamp(ImageCtx *ictx, uint64_t snap_id, struct timespec *timestamp); int snap_remove(ImageCtx *ictx, const char *snap_name, uint32_t flags, ProgressContext& pctx); int get_snap_namespace(ImageCtx *ictx, const char *snap_name, diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 97c2ca589dc3f..5cac1226d308f 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1174,6 +1174,15 @@ namespace librbd { return r; } + int Image::snap_get_timestamp(uint64_t snap_id, struct timespec *timestamp) + { + ImageCtx *ictx = (ImageCtx *)ctx; + tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str()); + int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp); + tracepoint(librbd, snap_get_timestamp_exit, r); + return r; + } + int Image::snap_get_limit(uint64_t *limit) { ImageCtx *ictx = (ImageCtx *)ctx; @@ -2582,6 +2591,15 @@ extern "C" int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit) return r; } +extern "C" int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp) +{ + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + tracepoint(librbd, snap_get_timestamp_enter, ictx, ictx->name.c_str()); + int r = librbd::snap_get_timestamp(ictx, snap_id, timestamp); + tracepoint(librbd, snap_get_timestamp_exit, r); + return r; +} + extern "C" int rbd_snap_set_limit(rbd_image_t image, uint64_t limit) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 2e1fa940c3c09..b4a1cd07f9f4b 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -40,6 +40,9 @@ cdef extern from "Python.h": cdef extern from "time.h": ctypedef long int time_t + cdef struct timespec: + time_t tv_sec + long tv_nsec cdef extern from "limits.h": cdef uint64_t INT64_MAX @@ -235,6 +238,7 @@ cdef extern from "rbd/librbd.h" nogil: int *is_protected) int rbd_snap_get_limit(rbd_image_t image, uint64_t *limit) int rbd_snap_set_limit(rbd_image_t image, uint64_t limit) + int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, timespec *timestamp) int rbd_snap_set(rbd_image_t image, const char *snapname) int rbd_flatten(rbd_image_t image) int rbd_rebuild_object_map(rbd_image_t image, librbd_progress_fn_t cb, @@ -1744,6 +1748,20 @@ cdef class Image(object): raise make_ex(ret, 'error setting snapshot limit for %s' % self.name) return ret + def get_snap_timestamp(self, snap_id): + """ + Get the snapshot timestamp for an image. + :param snap_id: the snapshot id of a snap shot + """ + cdef: + timespec timestamp + uint64_t _snap_id = snap_id + with nogil: + ret = rbd_snap_get_timestamp(self.image, _snap_id, ×tamp) + if ret != 0: + raise make_ex(ret, 'error getting snapshot timestamp for image: %s, snap_id: %d' % (self.name, snap_id)) + return datetime.fromtimestamp(timestamp.tv_sec) + def remove_snap_limit(self): """ Remove the snapshot limit for an image, essentially setting diff --git a/src/test/librbd/image/test_mock_RefreshRequest.cc b/src/test/librbd/image/test_mock_RefreshRequest.cc index 5f96ddb90e9cc..e9c20434def36 100644 --- a/src/test/librbd/image/test_mock_RefreshRequest.cc +++ b/src/test/librbd/image/test_mock_RefreshRequest.cc @@ -198,6 +198,16 @@ public: } } + void expect_snap_timestamp_list(MockRefreshImageCtx &mock_image_ctx, int r) { + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _, _, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + void expect_snap_namespace_list(MockRefreshImageCtx &mock_image_ctx, int r) { auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_namespace"), _, _, _)); @@ -421,6 +431,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) { expect_get_flags(mock_image_ctx, 0); expect_get_group(mock_image_ctx, 0); expect_get_snapshots(mock_image_ctx, 0); + expect_snap_timestamp_list(mock_image_ctx, 0); expect_snap_namespace_list(mock_image_ctx, 0); expect_refresh_parent_is_required(mock_refresh_parent_request, false); if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { @@ -455,6 +466,7 @@ TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) { expect_get_flags(mock_image_ctx, 0); expect_get_group(mock_image_ctx, 0); expect_get_snapshots(mock_image_ctx, 0); + expect_snap_timestamp_list(mock_image_ctx, 0); expect_snap_namespace_list(mock_image_ctx, 0); expect_refresh_parent_is_required(mock_refresh_parent_request, false); if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { diff --git a/src/tools/rbd/action/Snap.cc b/src/tools/rbd/action/Snap.cc index 209ae1dbc1f22..15b975aabf476 100644 --- a/src/tools/rbd/action/Snap.cc +++ b/src/tools/rbd/action/Snap.cc @@ -35,18 +35,29 @@ int do_list_snaps(librbd::Image& image, Formatter *f) t.define_column("SNAPID", TextTable::RIGHT, TextTable::RIGHT); t.define_column("NAME", TextTable::LEFT, TextTable::LEFT); t.define_column("SIZE", TextTable::RIGHT, TextTable::RIGHT); + t.define_column("TIMESTAMP", TextTable::LEFT, TextTable::LEFT); } for (std::vector::iterator s = snaps.begin(); s != snaps.end(); ++s) { + struct timespec timestamp; + image.snap_get_timestamp(s->id, ×tamp); + string tt_str = ""; + if(timestamp.tv_sec != 0) { + time_t tt = timestamp.tv_sec; + tt_str = ctime(&tt); + tt_str = tt_str.substr(0, tt_str.length() - 1); + } + if (f) { f->open_object_section("snapshot"); f->dump_unsigned("id", s->id); f->dump_string("name", s->name); f->dump_unsigned("size", s->size); + f->dump_string("timestamp", tt_str); f->close_section(); } else { - t << s->id << s->name << stringify(prettybyte_t(s->size)) + t << s->id << s->name << stringify(prettybyte_t(s->size)) << tt_str << TextTable::endrow; } } diff --git a/src/tracing/librbd.tp b/src/tracing/librbd.tp index 70074ca843e60..0652210076eb0 100644 --- a/src/tracing/librbd.tp +++ b/src/tracing/librbd.tp @@ -1316,6 +1316,24 @@ TRACEPOINT_EVENT(librbd, snap_exists_exit, ) ) +TRACEPOINT_EVENT(librbd, snap_get_timestamp_enter, + TP_ARGS( + void*, imagectx, + const char*, name), + TP_FIELDS( + ctf_integer_hex(void*, imagectx, imagectx) + ctf_string(name, name) + ) +) + +TRACEPOINT_EVENT(librbd, snap_get_timestamp_exit, + TP_ARGS( + int, retval), + TP_FIELDS( + ctf_integer(int, retval, retval) + ) +) + TRACEPOINT_EVENT(librbd, snap_get_limit_enter, TP_ARGS( void*, imagectx, -- 2.39.5