From: Yehuda Sadeh Date: Sat, 7 Apr 2018 00:41:37 +0000 (-0700) Subject: rgw: force last writer wins on marker writes X-Git-Tag: v12.2.9~28^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cc8817dbef4dbe166327fc28efc93b0282f16f84;p=ceph.git rgw: force last writer wins on marker writes Signed-off-by: Yehuda Sadeh (cherry picked from commit 1034a68fd12687ac81e6afc4718dbc8045648034) --- diff --git a/src/rgw/rgw_data_sync.cc b/src/rgw/rgw_data_sync.cc index 5aac1833bbe..ed9ac4a5f7b 100644 --- a/src/rgw/rgw_data_sync.cc +++ b/src/rgw/rgw_data_sync.cc @@ -932,6 +932,10 @@ public: marker_to_key[marker] = key; return true; } + + RGWOrderCallCR *allocate_order_control_cr() { + return new RGWLastCallerWinsCR(sync_env->cct); + } }; // ostream wrappers to print buckets without copying strings @@ -2330,6 +2334,10 @@ public: rgw_raw_obj(store->get_zone_params().log_pool, marker_oid), attrs); } + + RGWOrderCallCR *allocate_order_control_cr() { + return new RGWLastCallerWinsCR(sync_env->cct); + } }; class RGWBucketIncSyncShardMarkerTrack : public RGWSyncShardMarkerTrack { @@ -2415,6 +2423,10 @@ public: } return (key_to_marker.find(key) == key_to_marker.end()); } + + RGWOrderCallCR *allocate_order_control_cr() { + return new RGWLastCallerWinsCR(sync_env->cct); + } }; template diff --git a/src/rgw/rgw_sync.cc b/src/rgw/rgw_sync.cc index 474d474b0f6..7b8c5eb1ba6 100644 --- a/src/rgw/rgw_sync.cc +++ b/src/rgw/rgw_sync.cc @@ -1135,6 +1135,21 @@ public: #define META_SYNC_UPDATE_MARKER_WINDOW 10 + +int RGWLastCallerWinsCR::operate() { + RGWCoroutine *call_cr; + reenter(this) { + while (cr) { + call_cr = cr; + cr = nullptr; + yield call(call_cr); + /* cr might have been modified at this point */ + } + return set_cr_done(); + } + return 0; +} + class RGWMetaSyncShardMarkerTrack : public RGWSyncShardMarkerTrack { RGWMetaSyncEnv *sync_env; @@ -1167,6 +1182,10 @@ public: rgw_raw_obj(store->get_zone_params().log_pool, marker_oid), sync_marker); } + + RGWOrderCallCR *allocate_order_control_cr() { + return new RGWLastCallerWinsCR(sync_env->cct); + } }; int RGWMetaSyncSingleEntryCR::operate() { diff --git a/src/rgw/rgw_sync.h b/src/rgw/rgw_sync.h index c651f7a9ad1..ad27413d9b8 100644 --- a/src/rgw/rgw_sync.h +++ b/src/rgw/rgw_sync.h @@ -280,6 +280,36 @@ public: } }; +class RGWOrderCallCR : public RGWCoroutine +{ +public: + RGWOrderCallCR(CephContext *cct) : RGWCoroutine(cct) {} + + virtual void call_cr(RGWCoroutine *_cr) = 0; +}; + +class RGWLastCallerWinsCR : public RGWOrderCallCR +{ + RGWCoroutine *cr{nullptr}; + +public: + RGWLastCallerWinsCR(CephContext *cct) : RGWOrderCallCR(cct) {} + ~RGWLastCallerWinsCR() { + if (cr) { + cr->put(); + } + } + + int operate() override; + + void call_cr(RGWCoroutine *_cr) { + if (cr) { + cr->put(); + } + cr = _cr; + } +}; + template class RGWSyncShardMarkerTrack { struct marker_entry { @@ -296,16 +326,22 @@ class RGWSyncShardMarkerTrack { int window_size; int updates_since_flush; + RGWOrderCallCR *order_cr{nullptr}; protected: typename std::set need_retry_set; virtual RGWCoroutine *store_marker(const T& new_marker, uint64_t index_pos, const real_time& timestamp) = 0; + virtual RGWOrderCallCR *allocate_order_control_cr() = 0; virtual void handle_finish(const T& marker) { } public: RGWSyncShardMarkerTrack(int _window_size) : window_size(_window_size), updates_since_flush(0) {} - virtual ~RGWSyncShardMarkerTrack() {} + virtual ~RGWSyncShardMarkerTrack() { + if (order_cr) { + order_cr->put(); + } + } bool start(const T& pos, int index_pos, const real_time& timestamp) { if (pending.find(pos) != pending.end()) { @@ -372,7 +408,7 @@ public: --i; const T& high_marker = i->first; marker_entry& high_entry = i->second; - RGWCoroutine *cr = store_marker(high_marker, high_entry.pos, high_entry.timestamp); + RGWCoroutine *cr = order(store_marker(high_marker, high_entry.pos, high_entry.timestamp)); finish_markers.erase(finish_markers.begin(), last); return cr; } @@ -395,6 +431,24 @@ public: void reset_need_retry(const K& key) { need_retry_set.erase(key); } + + RGWCoroutine *order(RGWCoroutine *cr) { + /* either returns a new RGWLastWriteWinsCR, or update existing one, in which case it returns + * nothing and the existing one will call the cr + */ + if (order_cr && order_cr->is_done()) { + order_cr->put(); + order_cr = nullptr; + } + if (!order_cr) { + order_cr = allocate_order_control_cr(); + order_cr->get(); + order_cr->call_cr(cr); + return order_cr; + } + order_cr->call_cr(cr); + return nullptr; /* don't call it a second time */ + } }; class RGWMetaSyncShardMarkerTrack;