From 0358f29c9d46dc98fd63173dae78cfa33c5f75bf Mon Sep 17 00:00:00 2001 From: runsisi Date: Fri, 21 Apr 2017 16:32:33 +0800 Subject: [PATCH] librbd: add create timestamp metadata for image Signed-off-by: runsisi --- src/cls/rbd/cls_rbd.cc | 34 ++++++++++++++++++++++++++++ src/cls/rbd/cls_rbd_client.cc | 33 ++++++++++++++++++++++++++++ src/cls/rbd/cls_rbd_client.h | 5 +++++ src/include/rbd/librbd.h | 4 ++++ src/include/rbd/librbd.hpp | 2 ++ src/librbd/ImageCtx.cc | 5 +++++ src/librbd/ImageCtx.h | 2 ++ src/librbd/image/OpenRequest.cc | 39 +++++++++++++++++++++++++++++++++ src/librbd/image/OpenRequest.h | 6 +++++ src/librbd/librbd.cc | 23 +++++++++++++++++++ src/tracing/librbd.tp | 22 +++++++++++++++++++ 11 files changed, 175 insertions(+) diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index cb0d1fdcddacf..3eb64a45a5c88 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -223,12 +223,15 @@ int create(cls_method_context_t hctx, bufferlist *in, bufferlist *out) bufferlist featuresbl; bufferlist object_prefixbl; bufferlist snap_seqbl; + bufferlist create_timestampbl; uint64_t snap_seq = 0; + utime_t create_timestamp = ceph_clock_now(); ::encode(size, sizebl); ::encode(order, orderbl); ::encode(features, featuresbl); ::encode(object_prefix, object_prefixbl); ::encode(snap_seq, snap_seqbl); + ::encode(create_timestamp, create_timestampbl); map omap_vals; omap_vals["size"] = sizebl; @@ -236,6 +239,7 @@ int create(cls_method_context_t hctx, bufferlist *in, bufferlist *out) omap_vals["features"] = featuresbl; omap_vals["object_prefix"] = object_prefixbl; omap_vals["snap_seq"] = snap_seqbl; + omap_vals["create_timestamp"] = create_timestampbl; if (features & RBD_FEATURE_DATA_POOL) { if (data_pool_id == -1) { @@ -769,6 +773,32 @@ int set_stripe_unit_count(cls_method_context_t hctx, bufferlist *in, bufferlist return 0; } +int get_create_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + CLS_LOG(20, "get_create_timestamp"); + + utime_t timestamp; + bufferlist bl; + int r = cls_cxx_map_get_val(hctx, "create_timestamp", &bl); + if (r < 0) { + if (r != -ENOENT) { + CLS_ERR("error reading create_timestamp: %s", cpp_strerror(r).c_str()); + return r; + } + } else { + try { + bufferlist::iterator it = bl.begin(); + ::decode(timestamp, it); + } catch (const buffer::error &err) { + CLS_ERR("could not decode create_timestamp"); + return -EIO; + } + } + + ::encode(timestamp, *out); + return 0; +} + /** * get the image flags * @@ -5079,6 +5109,7 @@ CLS_INIT(rbd) cls_method_handle_t h_set_protection_status; cls_method_handle_t h_get_stripe_unit_count; cls_method_handle_t h_set_stripe_unit_count; + cls_method_handle_t h_get_create_timestamp; cls_method_handle_t h_get_flags; cls_method_handle_t h_set_flags; cls_method_handle_t h_remove_parent; @@ -5227,6 +5258,9 @@ CLS_INIT(rbd) cls_register_cxx_method(h_class, "set_stripe_unit_count", CLS_METHOD_RD | CLS_METHOD_WR, set_stripe_unit_count, &h_set_stripe_unit_count); + cls_register_cxx_method(h_class, "get_create_timestamp", + CLS_METHOD_RD, + get_create_timestamp, &h_get_create_timestamp); cls_register_cxx_method(h_class, "get_flags", CLS_METHOD_RD, get_flags, &h_get_flags); diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index c1fd48a0d0493..88b5b3d0340e8 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -915,6 +915,39 @@ namespace librbd { return ioctx->operate(oid, &op); } + void get_create_timestamp_start(librados::ObjectReadOperation *op) { + bufferlist empty_bl; + op->exec("rbd", "get_create_timestamp", empty_bl); + } + + int get_create_timestamp_finish(bufferlist::iterator *it, + utime_t *timestamp) { + assert(timestamp); + + try { + ::decode(*timestamp, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_create_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp) + { + librados::ObjectReadOperation op; + get_create_timestamp_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + bufferlist::iterator it = out_bl.begin(); + return get_create_timestamp_finish(&it, timestamp); + } + /************************ rbd_id object methods ************************/ void get_id_start(librados::ObjectReadOperation *op) { diff --git a/src/cls/rbd/cls_rbd_client.h b/src/cls/rbd/cls_rbd_client.h index f43e16e381fd1..754017f2deaf8 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -179,6 +179,11 @@ namespace librbd { uint64_t stripe_unit, uint64_t stripe_count); int set_stripe_unit_count(librados::IoCtx *ioctx, const std::string &oid, uint64_t stripe_unit, uint64_t stripe_count); + void get_create_timestamp_start(librados::ObjectReadOperation *op); + int get_create_timestamp_finish(bufferlist::iterator *it, + utime_t *timestamp); + int get_create_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp); int metadata_list(librados::IoCtx *ioctx, const std::string &oid, const std::string &start, uint64_t max_return, map *pairs); diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 87d04eb44706b..dca8f42370413 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -364,6 +364,10 @@ CEPH_RBD_API int rbd_update_features(rbd_image_t image, uint64_t features, CEPH_RBD_API int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit); CEPH_RBD_API int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count); + +CEPH_RBD_API int rbd_get_create_timestamp(rbd_image_t image, + struct timespec *timestamp); + CEPH_RBD_API int rbd_get_overlap(rbd_image_t image, uint64_t *overlap); CEPH_RBD_API int rbd_get_id(rbd_image_t image, char *id, size_t id_len); CEPH_RBD_API int rbd_get_block_name_prefix(rbd_image_t image, diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index f03ca9f362209..b8e7456920531 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -297,6 +297,8 @@ public: uint64_t get_stripe_unit() const; uint64_t get_stripe_count() const; + int get_create_timestamp(struct timespec *timestamp); + int flatten(); int flatten_with_progress(ProgressContext &prog_ctx); /** diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index e03259ee35c19..fd2333ee105e6 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -527,6 +527,11 @@ struct C_InvalidateCache : public Context { return stripe_count * (1ull << order); } + utime_t ImageCtx::get_create_timestamp() const + { + return create_timestamp; + } + int ImageCtx::is_snap_protected(snap_t in_snap_id, bool *is_protected) const { diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 23b577ab6e66c..99a02748ef665 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -128,6 +128,7 @@ namespace librbd { cls::rbd::GroupSpec group_spec; uint64_t stripe_unit, stripe_count; uint64_t flags; + utime_t create_timestamp; file_layout_t layout; @@ -254,6 +255,7 @@ namespace librbd { uint64_t get_stripe_unit() const; uint64_t get_stripe_count() const; uint64_t get_stripe_period() const; + utime_t get_create_timestamp() const; void add_snap(cls::rbd::SnapshotNamespace in_snap_namespace, std::string in_snap_name, diff --git a/src/librbd/image/OpenRequest.cc b/src/librbd/image/OpenRequest.cc index 579088b3cf03f..5b13f519602b1 100644 --- a/src/librbd/image/OpenRequest.cc +++ b/src/librbd/image/OpenRequest.cc @@ -322,6 +322,45 @@ Context *OpenRequest::handle_v2_get_stripe_unit_count(int *result) { return nullptr; } + send_v2_get_create_timestamp(); + return nullptr; +} + +template +void OpenRequest::send_v2_get_create_timestamp() { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 10) << this << " " << __func__ << dendl; + + librados::ObjectReadOperation op; + cls_client::get_create_timestamp_start(&op); + + using klass = OpenRequest; + librados::AioCompletion *comp = create_rados_callback< + klass, &klass::handle_v2_get_create_timestamp>(this); + m_out_bl.clear(); + m_image_ctx->md_ctx.aio_operate(m_image_ctx->header_oid, comp, &op, + &m_out_bl); + comp->release(); +} + +template +Context *OpenRequest::handle_v2_get_create_timestamp(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::get_create_timestamp_finish(&it, + &m_image_ctx->create_timestamp); + } + if (*result < 0 && *result != -EOPNOTSUPP) { + lderr(cct) << "failed to retrieve create_timestamp: " + << cpp_strerror(*result) + << dendl; + send_close_image(*result); + return nullptr; + } + send_v2_get_data_pool(); return nullptr; } diff --git a/src/librbd/image/OpenRequest.h b/src/librbd/image/OpenRequest.h index 3ae8602fb4bc9..5dd088770b710 100644 --- a/src/librbd/image/OpenRequest.h +++ b/src/librbd/image/OpenRequest.h @@ -52,6 +52,9 @@ private: * V2_GET_STRIPE_UNIT_COUNT | * | | * v | + * V2_GET_CREATE_TIMESTAMP | + * | | + * v | * V2_GET_DATA_POOL | * | | * v | @@ -105,6 +108,9 @@ private: void send_v2_get_stripe_unit_count(); Context *handle_v2_get_stripe_unit_count(int *result); + void send_v2_get_create_timestamp(); + Context *handle_v2_get_create_timestamp(int *result); + void send_v2_get_data_pool(); Context *handle_v2_get_data_pool(int *result); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 86ddd0a857354..1d5920fccb308 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1011,6 +1011,17 @@ namespace librbd { return stripe_count; } + int Image::get_create_timestamp(struct timespec *timestamp) + { + ImageCtx *ictx = (ImageCtx *)ctx; + tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(), + ictx->read_only); + utime_t time = ictx->get_create_timestamp(); + time.to_timespec(timestamp); + tracepoint(librbd, get_create_timestamp_exit, 0, timestamp); + return 0; + } + int Image::overlap(uint64_t *overlap) { ImageCtx *ictx = (ImageCtx *)ctx; @@ -2817,6 +2828,18 @@ extern "C" int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count) return 0; } +extern "C" int rbd_get_create_timestamp(rbd_image_t image, + struct timespec *timestamp) +{ + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + tracepoint(librbd, get_create_timestamp_enter, ictx, ictx->name.c_str(), + ictx->read_only); + utime_t time = ictx->get_create_timestamp(); + time.to_timespec(timestamp); + tracepoint(librbd, get_create_timestamp_exit, 0, timestamp); + return 0; +} + extern "C" int rbd_get_overlap(rbd_image_t image, uint64_t *overlap) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; diff --git a/src/tracing/librbd.tp b/src/tracing/librbd.tp index 7078390daed9c..f8c77142a7842 100644 --- a/src/tracing/librbd.tp +++ b/src/tracing/librbd.tp @@ -1934,6 +1934,28 @@ TRACEPOINT_EVENT(librbd, get_stripe_count_exit, ) ) +TRACEPOINT_EVENT(librbd, get_create_timestamp_enter, + TP_ARGS( + void*, imagectx, + const char*, name, + char, read_only), + TP_FIELDS( + ctf_integer_hex(void*, imagectx, imagectx) + ctf_string(name, name) + ctf_integer(char, read_only, read_only) + ) +) + +TRACEPOINT_EVENT(librbd, get_create_timestamp_exit, + TP_ARGS( + int, retval, + struct timespec*, timestamp), + TP_FIELDS( + ctf_integer(int, retval, retval) + ctf_integer(uint64_t, timestamp, timestamp->tv_sec) + ) +) + TRACEPOINT_EVENT(librbd, get_features_enter, TP_ARGS( void*, imagectx, -- 2.39.5