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<string, bufferlist> omap_vals;
omap_vals["size"] = sizebl;
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) {
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
*
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;
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);
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) {
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<string, bufferlist> *pairs);
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,
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);
/**
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
{
cls::rbd::GroupSpec group_spec;
uint64_t stripe_unit, stripe_count;
uint64_t flags;
+ utime_t create_timestamp;
file_layout_t layout;
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,
return nullptr;
}
+ send_v2_get_create_timestamp();
+ return nullptr;
+}
+
+template <typename I>
+void OpenRequest<I>::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<I>;
+ 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 <typename I>
+Context *OpenRequest<I>::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;
}
* V2_GET_STRIPE_UNIT_COUNT |
* | |
* v |
+ * V2_GET_CREATE_TIMESTAMP |
+ * | |
+ * v |
* V2_GET_DATA_POOL |
* | |
* v |
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);
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;
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;
)
)
+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,