]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: guard versioned object removal from circular sync
authorYehuda Sadeh <yehuda@redhat.com>
Wed, 6 Jan 2016 01:01:51 +0000 (17:01 -0800)
committerYehuda Sadeh <yehuda@redhat.com>
Fri, 12 Feb 2016 00:13:49 +0000 (16:13 -0800)
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 <yehuda@redhat.com>
src/cls/rgw/cls_rgw.cc
src/cls/rgw/cls_rgw_client.cc
src/cls/rgw/cls_rgw_client.h
src/cls/rgw/cls_rgw_ops.cc
src/cls/rgw/cls_rgw_ops.h
src/cls/rgw/cls_rgw_types.h
src/rgw/rgw_cr_rados.cc
src/rgw/rgw_cr_rados.h
src/rgw/rgw_data_sync.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h

index 50faf0086c293b7b766cd1bd4f401389a0397b7f..0fd88905eb1616402c08d7570f471eba73720fc8 100644 (file)
@@ -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;
 
   /*
index c2847741713ae49ed6f4839e4086d7caed891a80..686cd6cbd672da06e2cf7a9d0feda0bffb1b0cd2 100644 (file)
@@ -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)
index 6d136a9202aee75845aba689375391598eba99cd..e1d1342e3e43a4695868bac874a0b6ded8e56029 100644 (file)
@@ -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,
index 23beb4ee429e7284d779071bddbbc8160e7032ca..38f57e0c13441c9091180a4807c34778083cfc8c 100644 (file)
@@ -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<rgw_cls_unlink_instance_op*>& o)
index 1c8f96bff2432d71eb1a83695d274bad909a068f..053d716e292ac8c8354def87770fee404f50a51a 100644 (file)
@@ -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);
   }
 
index 404aac650398d48a6cc423425edf658d16796e1f..3da746851b7ca1b8b8aee94a878288f1be25922c 100644 (file)
@@ -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<rgw_bi_log_entry*>& o);
+  
+  bool is_versioned() {
+    return ((bilog_flags & RGW_BILOG_FLAG_VERSIONED_OP) != 0);
+  }
 };
 WRITE_CLASS_ENCODER(rgw_bi_log_entry)
 
index ea5687fdc843e377bd0f081144b4a1928482568d..83b9808be0b5966d6525c1a31467df967bd861eb 100644 (file)
@@ -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) {
index 30761c9b69e3a1c06d59ba9f316fbe1e4c239def..dc1371021aeb1da305acf37bab7da81a87a10d8b 100644 (file)
@@ -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;
index df9fc472aece05886b8bef6891dad631366b5066..406cd5340a8eee68faf615ac7aec631ca10f4219 100644 (file)
@@ -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, &timestamp));
+            call(new RGWRemoveObjCR(async_rados, store, source_zone, *bucket_info, key, versioned, versioned_epoch, NULL, NULL, false, &timestamp));
           } 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, &timestamp));
+            call(new RGWRemoveObjCR(async_rados, store, source_zone, *bucket_info, key, versioned, versioned_epoch, &owner.id, &owner.display_name, true, &timestamp));
           }
         }
       } while (marker_tracker->need_retry(key));
@@ -2078,7 +2079,9 @@ int RGWBucketShardFullSyncCR::operate()
 
           yield {
             spawn(new RGWBucketSyncSingleEntryCR<rgw_obj_key, rgw_obj_key>(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<string, rgw_obj_key>(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);
           }
         // }
index 66fb781d2b9112998cfe76bf631477a14200a1ca..3d554ace634c4152dac7220d35f3a856036b8f89 100644 (file)
@@ -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) {
index f807c9979aa7ea5e7bce03906bc8d484008724f5..d2f790d278f4b833e2023d3eb91b915d1aad7991 100644 (file)
@@ -2205,8 +2205,9 @@ public:
         list<rgw_obj_key> *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<uint64_t, vector<rgw_bucket_olh_log_entry> > *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);