From 5e93a6869d3dcf619cf0d1b9dfdc529cf4a80822 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 5 Jan 2016 17:01:51 -0800 Subject: [PATCH] rgw: guard versioned object removal from circular sync check if marker instance already exists, only apply (and update bi log) if does not exist. Propagate the versioning flag so that we apply the appropriate operation on the object. Signed-off-by: Yehuda Sadeh --- src/cls/rgw/cls_rgw.cc | 9 +++++++++ src/cls/rgw/cls_rgw_client.cc | 3 ++- src/cls/rgw/cls_rgw_client.h | 2 +- src/cls/rgw/cls_rgw_ops.cc | 1 + src/cls/rgw/cls_rgw_ops.h | 9 +++++++-- src/cls/rgw/cls_rgw_types.h | 4 ++++ src/rgw/rgw_cr_rados.cc | 4 ++++ src/rgw/rgw_cr_rados.h | 8 +++++++- src/rgw/rgw_data_sync.cc | 15 +++++++++------ src/rgw/rgw_rados.cc | 19 +++++++++++++------ src/rgw/rgw_rados.h | 8 +++++--- 11 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/cls/rgw/cls_rgw.cc b/src/cls/rgw/cls_rgw.cc index 50faf0086c293..0fd88905eb161 100644 --- a/src/cls/rgw/cls_rgw.cc +++ b/src/cls/rgw/cls_rgw.cc @@ -1183,6 +1183,9 @@ public: return 0; } + time_t mtime() { + return instance_entry.meta.mtime; + } }; @@ -1386,6 +1389,12 @@ static int rgw_bucket_link_olh(cls_method_context_t hctx, bufferlist *in, buffer return ret; } + if (existed && op.unmod_since > 0) { + if (obj.mtime() >= op.unmod_since) { + return 0; /* no need to set error, we just return 0 and avoid writing to the bi log */ + } + } + bool removing; /* diff --git a/src/cls/rgw/cls_rgw_client.cc b/src/cls/rgw/cls_rgw_client.cc index c2847741713ae..686cd6cbd672d 100644 --- a/src/cls/rgw/cls_rgw_client.cc +++ b/src/cls/rgw/cls_rgw_client.cc @@ -306,7 +306,7 @@ int cls_rgw_bi_list(librados::IoCtx& io_ctx, const string oid, int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, const string& oid, const cls_rgw_obj_key& key, bufferlist& olh_tag, bool delete_marker, const string& op_tag, struct rgw_bucket_dir_entry_meta *meta, - uint64_t olh_epoch, bool log_op) + uint64_t olh_epoch, time_t unmod_since, bool log_op) { bufferlist in, out; struct rgw_cls_link_olh_op call; @@ -319,6 +319,7 @@ int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, const string& oid, const cl } call.olh_epoch = olh_epoch; call.log_op = log_op; + call.unmod_since = unmod_since; ::encode(call, in); int r = io_ctx.exec(oid, "rgw", "bucket_link_olh", in, out); if (r < 0) diff --git a/src/cls/rgw/cls_rgw_client.h b/src/cls/rgw/cls_rgw_client.h index 6d136a9202aee..e1d1342e3e43a 100644 --- a/src/cls/rgw/cls_rgw_client.h +++ b/src/cls/rgw/cls_rgw_client.h @@ -330,7 +330,7 @@ int cls_rgw_bi_list(librados::IoCtx& io_ctx, const string oid, int cls_rgw_bucket_link_olh(librados::IoCtx& io_ctx, const string& oid, const cls_rgw_obj_key& key, bufferlist& olh_tag, bool delete_marker, const string& op_tag, struct rgw_bucket_dir_entry_meta *meta, - uint64_t olh_epoch, bool log_op); + uint64_t olh_epoch, time_t unmod_since, bool log_op); int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, const string& oid, const cls_rgw_obj_key& key, const string& op_tag, uint64_t olh_epoch, bool log_op); int cls_rgw_get_olh_log(librados::IoCtx& io_ctx, string& oid, librados::ObjectReadOperation& op, const cls_rgw_obj_key& olh, uint64_t ver_marker, diff --git a/src/cls/rgw/cls_rgw_ops.cc b/src/cls/rgw/cls_rgw_ops.cc index 23beb4ee429e7..38f57e0c13441 100644 --- a/src/cls/rgw/cls_rgw_ops.cc +++ b/src/cls/rgw/cls_rgw_ops.cc @@ -175,6 +175,7 @@ void rgw_cls_link_olh_op::dump(Formatter *f) const ::encode_json("olh_epoch", olh_epoch, f); ::encode_json("log_op", log_op, f); ::encode_json("bilog_flags", (uint32_t)bilog_flags, f); + ::encode_json("unmod_since", unmod_since, f); } void rgw_cls_unlink_instance_op::generate_test_instances(list& o) diff --git a/src/cls/rgw/cls_rgw_ops.h b/src/cls/rgw/cls_rgw_ops.h index 1c8f96bff2432..053d716e292ac 100644 --- a/src/cls/rgw/cls_rgw_ops.h +++ b/src/cls/rgw/cls_rgw_ops.h @@ -164,11 +164,12 @@ struct rgw_cls_link_olh_op { uint64_t olh_epoch; bool log_op; uint16_t bilog_flags; + time_t unmod_since; /* only create delete marker if newer then this */ rgw_cls_link_olh_op() : delete_marker(false), olh_epoch(0), log_op(false), bilog_flags(0) {} void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); + ENCODE_START(2, 1, bl); ::encode(key, bl); ::encode(olh_tag, bl); ::encode(delete_marker, bl); @@ -177,11 +178,12 @@ struct rgw_cls_link_olh_op { ::encode(olh_epoch, bl); ::encode(log_op, bl); ::encode(bilog_flags, bl); + ::encode(unmod_since, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START(1, bl); + DECODE_START(2, bl); ::decode(key, bl); ::decode(olh_tag, bl); ::decode(delete_marker, bl); @@ -190,6 +192,9 @@ struct rgw_cls_link_olh_op { ::decode(olh_epoch, bl); ::decode(log_op, bl); ::decode(bilog_flags, bl); + if (struct_v >= 2) { + ::decode(unmod_since, bl); + } DECODE_FINISH(bl); } diff --git a/src/cls/rgw/cls_rgw_types.h b/src/cls/rgw/cls_rgw_types.h index 404aac650398d..3da746851b7ca 100644 --- a/src/cls/rgw/cls_rgw_types.h +++ b/src/cls/rgw/cls_rgw_types.h @@ -528,6 +528,10 @@ struct rgw_bi_log_entry { void dump(Formatter *f) const; void decode_json(JSONObj *obj); static void generate_test_instances(list& o); + + bool is_versioned() { + return ((bilog_flags & RGW_BILOG_FLAG_VERSIONED_OP) != 0); + } }; WRITE_CLASS_ENCODER(rgw_bi_log_entry) diff --git a/src/rgw/rgw_cr_rados.cc b/src/rgw/rgw_cr_rados.cc index ea5687fdc843e..83b9808be0b59 100644 --- a/src/rgw/rgw_cr_rados.cc +++ b/src/rgw/rgw_cr_rados.cc @@ -523,10 +523,14 @@ int RGWAsyncRemoveObj::_send_request() if (del_if_older) { del_op.params.unmod_since = timestamp; } + if (versioned) { + del_op.params.versioning_status = BUCKET_VERSIONED; + } del_op.params.olh_epoch = versioned_epoch; del_op.params.marker_version_id = marker_version_id; del_op.params.obj_owner.set_id(owner); del_op.params.obj_owner.set_name(owner_display_name); + del_op.params.mtime = timestamp; ret = del_op.delete_obj(); if (ret < 0) { diff --git a/src/rgw/rgw_cr_rados.h b/src/rgw/rgw_cr_rados.h index 30761c9b69e3a..dc1371021aeb1 100644 --- a/src/rgw/rgw_cr_rados.h +++ b/src/rgw/rgw_cr_rados.h @@ -677,6 +677,7 @@ class RGWAsyncRemoveObj : public RGWAsyncRadosRequest { rgw_obj_key key; string owner; string owner_display_name; + bool versioned; uint64_t versioned_epoch; string marker_version_id; @@ -692,6 +693,7 @@ public: const rgw_obj_key& _key, const string& _owner, const string& _owner_display_name, + bool _versioned, uint64_t _versioned_epoch, bool _delete_marker, bool _if_older, @@ -701,6 +703,7 @@ public: key(_key), owner(_owner), owner_display_name(_owner_display_name), + versioned(_versioned), versioned_epoch(_versioned_epoch), del_if_older(_if_older), timestamp(_timestamp) { @@ -719,6 +722,7 @@ class RGWRemoveObjCR : public RGWSimpleCoroutine { RGWBucketInfo bucket_info; rgw_obj_key key; + bool versioned; uint64_t versioned_epoch; bool delete_marker; string owner; @@ -734,6 +738,7 @@ public: const string& _source_zone, RGWBucketInfo& _bucket_info, const rgw_obj_key& _key, + bool _versioned, uint64_t _versioned_epoch, string *_owner, string *_owner_display_name, @@ -743,6 +748,7 @@ public: source_zone(_source_zone), bucket_info(_bucket_info), key(_key), + versioned(_versioned), versioned_epoch(_versioned_epoch), delete_marker(_delete_marker) { del_if_older = (_timestamp != NULL); @@ -765,7 +771,7 @@ public: int send_request() { req = new RGWAsyncRemoveObj(stack->create_completion_notifier(), store, source_zone, bucket_info, - key, owner, owner_display_name, versioned_epoch, + key, owner, owner_display_name, versioned, versioned_epoch, delete_marker, del_if_older, timestamp); async_rados->queue(req); return 0; diff --git a/src/rgw/rgw_data_sync.cc b/src/rgw/rgw_data_sync.cc index df9fc472aece0..406cd5340a8ee 100644 --- a/src/rgw/rgw_data_sync.cc +++ b/src/rgw/rgw_data_sync.cc @@ -1881,6 +1881,7 @@ class RGWBucketSyncSingleEntryCR : public RGWCoroutine { int shard_id; rgw_obj_key key; + bool versioned; uint64_t versioned_epoch; bucket_entry_owner owner; utime_t timestamp; @@ -1896,7 +1897,7 @@ class RGWBucketSyncSingleEntryCR : public RGWCoroutine { public: RGWBucketSyncSingleEntryCR(RGWRados *_store, RGWAsyncRadosProcessor *_async_rados, const string& _source_zone, RGWBucketInfo *_bucket_info, int _shard_id, - const rgw_obj_key& _key, uint64_t _versioned_epoch, + const rgw_obj_key& _key, bool _versioned, uint64_t _versioned_epoch, utime_t& _timestamp, const bucket_entry_owner& _owner, RGWModifyOp _op, RGWPendingState _op_state, @@ -1904,7 +1905,7 @@ public: async_rados(_async_rados), source_zone(_source_zone), bucket_info(_bucket_info), shard_id(_shard_id), - key(_key), versioned_epoch(_versioned_epoch), + key(_key), versioned(_versioned), versioned_epoch(_versioned_epoch), owner(_owner), timestamp(_timestamp), op(_op), op_state(_op_state), @@ -1940,11 +1941,11 @@ public: true)); } else if (op == CLS_RGW_OP_DEL) { set_status("removing obj"); - call(new RGWRemoveObjCR(async_rados, store, source_zone, *bucket_info, key, versioned_epoch, NULL, NULL, false, ×tamp)); + call(new RGWRemoveObjCR(async_rados, store, source_zone, *bucket_info, key, versioned, versioned_epoch, NULL, NULL, false, ×tamp)); } else if (op == CLS_RGW_OP_LINK_OLH_DM) { set_status("creating delete marker"); ldout(store->ctx(), 10) << "creating delete marker: obj: " << source_zone << "/" << bucket_info->bucket << "/" << key << "[" << versioned_epoch << "]" << dendl; - call(new RGWRemoveObjCR(async_rados, store, source_zone, *bucket_info, key, versioned_epoch, &owner.id, &owner.display_name, true, ×tamp)); + call(new RGWRemoveObjCR(async_rados, store, source_zone, *bucket_info, key, versioned, versioned_epoch, &owner.id, &owner.display_name, true, ×tamp)); } } } while (marker_tracker->need_retry(key)); @@ -2078,7 +2079,9 @@ int RGWBucketShardFullSyncCR::operate() yield { spawn(new RGWBucketSyncSingleEntryCR(store, async_rados, source_zone, bucket_info, shard_id, - entry->key, entry->versioned_epoch, entry->mtime, + entry->key, + false, /* versioned, only matters for object removal */ + entry->versioned_epoch, entry->mtime, entry->owner, op, CLS_RGW_STATE_COMPLETE, entry->key, marker_tracker), false); } } @@ -2271,7 +2274,7 @@ int RGWBucketShardIncrementalSyncCR::operate() versioned_epoch = entry->ver.epoch; } spawn(new RGWBucketSyncSingleEntryCR(store, async_rados, source_zone, bucket_info, shard_id, - key, versioned_epoch, entry->timestamp, owner, entry->op, + key, entry->is_versioned(), versioned_epoch, entry->timestamp, owner, entry->op, entry->state, entry->id, marker_tracker), false); } // } diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 66fb781d2b911..3d554ace634c4 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -5751,7 +5751,7 @@ int RGWRados::Object::Write::write_meta(uint64_t size, state = NULL; if (versioned_op) { - r = store->set_olh(target->get_ctx(), target->get_bucket_info(), obj, false, NULL, meta.olh_epoch); + r = store->set_olh(target->get_ctx(), target->get_bucket_info(), obj, false, NULL, meta.olh_epoch, 0); if (r < 0) { return r; } @@ -7199,9 +7199,14 @@ int RGWRados::Object::Delete::delete_obj() meta.owner = params.obj_owner.get_id().to_str(); meta.owner_display_name = params.obj_owner.get_display_name(); - meta.mtime = ceph_clock_now(store->ctx()); - int r = store->set_olh(target->get_ctx(), target->get_bucket_info(), marker, true, &meta, params.olh_epoch); + if (params.mtime == 0) { + meta.mtime = ceph_clock_now(store->ctx()); + } else { + meta.mtime = utime_t(params.mtime, 0); + } + + int r = store->set_olh(target->get_ctx(), target->get_bucket_info(), marker, true, &meta, params.olh_epoch, params.unmod_since); if (r < 0) { return r; } @@ -9129,7 +9134,8 @@ int RGWRados::olh_init_modification(RGWObjState& state, rgw_obj& obj, string *op int RGWRados::bucket_index_link_olh(RGWObjState& olh_state, rgw_obj& obj_instance, bool delete_marker, const string& op_tag, struct rgw_bucket_dir_entry_meta *meta, - uint64_t olh_epoch) + uint64_t olh_epoch, + time_t unmod_since) { rgw_rados_ref ref; rgw_bucket bucket; @@ -9147,6 +9153,7 @@ int RGWRados::bucket_index_link_olh(RGWObjState& olh_state, rgw_obj& obj_instanc cls_rgw_obj_key key(obj_instance.get_index_key_name(), obj_instance.get_instance()); ret = cls_rgw_bucket_link_olh(bs.index_ctx, bs.bucket_obj, key, olh_state.olh_tag, delete_marker, op_tag, meta, olh_epoch, + unmod_since, get_zone().log_data); if (ret < 0) { return ret; @@ -9428,7 +9435,7 @@ int RGWRados::update_olh(RGWObjectCtx& obj_ctx, RGWObjState *state, RGWBucketInf } int RGWRados::set_olh(RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, rgw_obj& target_obj, bool delete_marker, rgw_bucket_dir_entry_meta *meta, - uint64_t olh_epoch) + uint64_t olh_epoch, time_t unmod_since) { string op_tag; @@ -9459,7 +9466,7 @@ int RGWRados::set_olh(RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, rgw_obj } return ret; } - ret = bucket_index_link_olh(*state, target_obj, delete_marker, op_tag, meta, olh_epoch); + ret = bucket_index_link_olh(*state, target_obj, delete_marker, op_tag, meta, olh_epoch, unmod_since); if (ret < 0) { ldout(cct, 20) << "bucket_index_link_olh() target_obj=" << target_obj << " delete_marker=" << (int)delete_marker << " returned " << ret << dendl; if (ret == -ECANCELED) { diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index f807c9979aa7e..d2f790d278f4b 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -2205,8 +2205,9 @@ public: list *remove_objs; utime_t expiration_time; time_t unmod_since; + time_t mtime; /* for setting delete marker mtime */ - DeleteParams() : versioning_status(0), olh_epoch(0), bilog_flags(0), remove_objs(NULL), unmod_since(0) {} + DeleteParams() : versioning_status(0), olh_epoch(0), bilog_flags(0), remove_objs(NULL), unmod_since(0), mtime(0) {} } params; struct DeleteResult { @@ -2585,7 +2586,8 @@ public: int olh_init_modification_impl(RGWObjState& state, rgw_obj& olh_obj, string *op_tag); int bucket_index_link_olh(RGWObjState& olh_state, rgw_obj& obj_instance, bool delete_marker, const string& op_tag, struct rgw_bucket_dir_entry_meta *meta, - uint64_t olh_epoch); + uint64_t olh_epoch, + time_t unmod_since); int bucket_index_unlink_instance(rgw_obj& obj_instance, const string& op_tag, uint64_t olh_epoch); int bucket_index_read_olh_log(RGWObjState& state, rgw_obj& obj_instance, uint64_t ver_marker, map > *log, bool *is_truncated); @@ -2596,7 +2598,7 @@ public: uint64_t *plast_ver); int update_olh(RGWObjectCtx& obj_ctx, RGWObjState *state, RGWBucketInfo& bucket_info, rgw_obj& obj); int set_olh(RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, rgw_obj& target_obj, bool delete_marker, rgw_bucket_dir_entry_meta *meta, - uint64_t olh_epoch); + uint64_t olh_epoch, time_t unmod_since); int unlink_obj_instance(RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, rgw_obj& target_obj, uint64_t olh_epoch); -- 2.39.5