From: Julien Collet Date: Tue, 20 Feb 2018 09:14:00 +0000 (+0100) Subject: librbd: add image access/last modified timestamps X-Git-Tag: v14.0.1~528^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=809c5430c2929ea1b33d3d1ab7c0023fbb2ce7a5;p=ceph.git librbd: add image access/last modified timestamps Add access and modify timestamps and associated tests to RBD images. Access (resp. modify) timestamps are updated on read (resp. write) operations. A configurable throttling mechanism is implemented (default to 60s). Signed-off-by: Julien Collet --- diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index b357957969406..ed2163dbf4c43 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -520,15 +520,15 @@ int create(cls_method_context_t hctx, bufferlist *in, bufferlist *out) bufferlist featuresbl; bufferlist object_prefixbl; bufferlist snap_seqbl; - bufferlist create_timestampbl; + bufferlist timestampbl; uint64_t snap_seq = 0; - utime_t create_timestamp = ceph_clock_now(); + utime_t 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); + encode(timestamp, timestampbl); map omap_vals; omap_vals["size"] = sizebl; @@ -536,7 +536,9 @@ 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; + omap_vals["create_timestamp"] = timestampbl; + omap_vals["access_timestamp"] = timestampbl; + omap_vals["modify_timestamp"] = timestampbl; if ((features & RBD_FEATURE_OPERATIONS) != 0ULL) { CLS_ERR("Attempting to set internal feature: operations"); @@ -1093,6 +1095,81 @@ int get_create_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist * return 0; } +/** + * get the image access timestamp + * + * Input: + * @param none + * + * Output: + * @param timestamp the image access timestamp + * + * @returns 0 on success, negative error code upon failure + */ +int get_access_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + CLS_LOG(20, "get_access_timestamp"); + + utime_t timestamp; + bufferlist bl; + int r = cls_cxx_map_get_val(hctx, "access_timestamp", &bl); + if (r < 0) { + if (r != -ENOENT) { + CLS_ERR("error reading access_timestamp: %s", cpp_strerror(r).c_str()); + return r; + } + } else { + try { + auto it = bl.cbegin(); + decode(timestamp, it); + } catch (const buffer::error &err) { + CLS_ERR("could not decode access_timestamp"); + return -EIO; + } + } + + encode(timestamp, *out); + return 0; +} + +/** + * get the image modify timestamp + * + * Input: + * @param none + * + * Output: + * @param timestamp the image modify timestamp + * + * @returns 0 on success, negative error code upon failure + */ +int get_modify_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + CLS_LOG(20, "get_modify_timestamp"); + + utime_t timestamp; + bufferlist bl; + int r = cls_cxx_map_get_val(hctx, "modify_timestamp", &bl); + if (r < 0) { + if (r != -ENOENT) { + CLS_ERR("error reading modify_timestamp: %s", cpp_strerror(r).c_str()); + return r; + } + } else { + try { + auto it = bl.cbegin(); + decode(timestamp, it); + } catch (const buffer::error &err) { + CLS_ERR("could not decode modify_timestamp"); + return -EIO; + } + } + + encode(timestamp, *out); + return 0; +} + + /** * get the image flags * @@ -2393,6 +2470,59 @@ int set_id(cls_method_context_t hctx, bufferlist *in, bufferlist *out) return cls_cxx_write(hctx, 0, write_bl.length(), &write_bl); } +/** + * Update the access timestamp of an image + * + * Input: + * @param none + * + * Output: + * @returns 0 on success, negative error code on other error + */ +int set_access_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + int r = check_exists(hctx); + if(r < 0) + return r; + + utime_t timestamp = ceph_clock_now(); + r = write_key(hctx, "access_timestamp", timestamp); + if(r < 0) { + CLS_ERR("error setting access_timestamp"); + return r; + } + + return 0; +} + +/** + * Update the modify timestamp of an image + * + * Input: + * @param none + * + * Output: + * @returns 0 on success, negative error code on other error + */ + +int set_modify_timestamp(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + int r = check_exists(hctx); + if(r < 0) + return r; + + utime_t timestamp = ceph_clock_now(); + r = write_key(hctx, "modify_timestamp", timestamp); + if(r < 0) { + CLS_ERR("error setting modify_timestamp"); + return r; + } + + return 0; +} + + + /*********************** methods for rbd_directory ***********************/ static const string dir_key_for_id(const string &id) @@ -6651,6 +6781,8 @@ CLS_INIT(rbd) 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_access_timestamp; + cls_method_handle_t h_get_modify_timestamp; cls_method_handle_t h_get_flags; cls_method_handle_t h_set_flags; cls_method_handle_t h_op_features_get; @@ -6673,6 +6805,8 @@ CLS_INIT(rbd) cls_method_handle_t h_copyup; cls_method_handle_t h_get_id; cls_method_handle_t h_set_id; + cls_method_handle_t h_set_modify_timestamp; + cls_method_handle_t h_set_access_timestamp; cls_method_handle_t h_dir_get_id; cls_method_handle_t h_dir_get_name; cls_method_handle_t h_dir_list; @@ -6828,6 +6962,12 @@ CLS_INIT(rbd) 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_access_timestamp", + CLS_METHOD_RD, + get_access_timestamp, &h_get_access_timestamp); + cls_register_cxx_method(h_class, "get_modify_timestamp", + CLS_METHOD_RD, + get_modify_timestamp, &h_get_modify_timestamp); cls_register_cxx_method(h_class, "get_flags", CLS_METHOD_RD, get_flags, &h_get_flags); @@ -6883,6 +7023,14 @@ CLS_INIT(rbd) assert_snapc_seq, &h_assert_snapc_seq); + cls_register_cxx_method(h_class, "set_modify_timestamp", + CLS_METHOD_RD | CLS_METHOD_WR, + set_modify_timestamp, &h_set_modify_timestamp); + + cls_register_cxx_method(h_class, "set_access_timestamp", + CLS_METHOD_RD | CLS_METHOD_WR, + set_access_timestamp, &h_set_access_timestamp); + /* methods for the rbd_children object */ cls_register_cxx_method(h_class, "add_child", CLS_METHOD_RD | CLS_METHOD_WR, diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index 087ed597b23b1..88317f893bc3d 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -1065,6 +1065,32 @@ namespace librbd { return ioctx->operate(oid, &op); } + void set_modify_timestamp(librados::ObjectWriteOperation *op) + { + bufferlist empty_bl; + op->exec("rbd","set_modify_timestamp",empty_bl); + } + + int set_modify_timestamp(librados::IoCtx *ioctx, const std::string &oid) + { + librados::ObjectWriteOperation op; + set_modify_timestamp(&op); + return ioctx->operate(oid, &op); + } + + void set_access_timestamp(librados::ObjectWriteOperation *op) + { + bufferlist empty_bl; + op->exec("rbd","set_access_timestamp",empty_bl); + } + + int set_access_timestamp(librados::IoCtx *ioctx, const std::string &oid) + { + librados::ObjectWriteOperation op; + set_access_timestamp(&op); + return ioctx->operate(oid, &op); + } + void get_create_timestamp_start(librados::ObjectReadOperation *op) { bufferlist empty_bl; op->exec("rbd", "get_create_timestamp", empty_bl); @@ -1098,6 +1124,72 @@ namespace librbd { return get_create_timestamp_finish(&it, timestamp); } + void get_access_timestamp_start(librados::ObjectReadOperation *op) { + bufferlist empty_bl; + op->exec("rbd", "get_access_timestamp", empty_bl); + } + + int get_access_timestamp_finish(bufferlist::const_iterator *it, + utime_t *timestamp) { + assert(timestamp); + + try { + decode(*timestamp, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_access_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp) + { + librados::ObjectReadOperation op; + get_access_timestamp_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + auto it = out_bl.cbegin(); + return get_access_timestamp_finish(&it, timestamp); + } + + void get_modify_timestamp_start(librados::ObjectReadOperation *op) { + bufferlist empty_bl; + op->exec("rbd", "get_modify_timestamp", empty_bl); + } + + int get_modify_timestamp_finish(bufferlist::const_iterator *it, + utime_t *timestamp) { + assert(timestamp); + + try { + decode(*timestamp, *it); + } catch (const buffer::error &err) { + return -EBADMSG; + } + return 0; + } + + int get_modify_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp) + { + librados::ObjectReadOperation op; + get_modify_timestamp_start(&op); + + bufferlist out_bl; + int r = ioctx->operate(oid, &op, &out_bl); + if (r < 0) { + return r; + } + + auto it = out_bl.cbegin(); + return get_modify_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 2acc5be47437a..c9c362bb53689 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -222,6 +222,25 @@ namespace librbd { utime_t *timestamp); int get_create_timestamp(librados::IoCtx *ioctx, const std::string &oid, utime_t *timestamp); + + void get_access_timestamp_start(librados::ObjectReadOperation *op); + int get_access_timestamp_finish(bufferlist::const_iterator *it, + utime_t *timestamp); + int get_access_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp); + + void get_modify_timestamp_start(librados::ObjectReadOperation *op); + int get_modify_timestamp_finish(bufferlist::const_iterator *it, + utime_t *timestamp); + int get_modify_timestamp(librados::IoCtx *ioctx, const std::string &oid, + utime_t *timestamp); + + void set_modify_timestamp(librados::ObjectWriteOperation *op); + int set_modify_timestamp(librados::IoCtx *ioctx, const std::string &oid); + + void set_access_timestamp(librados::ObjectWriteOperation *op); + int set_access_timestamp(librados::IoCtx *ioctx, const std::string &oid); + int metadata_list(librados::IoCtx *ioctx, const std::string &oid, const std::string &start, uint64_t max_return, map *pairs); diff --git a/src/common/options.cc b/src/common/options.cc index 7d52edd0a47fc..ef57318c92bb4 100644 --- a/src/common/options.cc +++ b/src/common/options.cc @@ -6632,6 +6632,16 @@ static std::vector