Skip to content

Commit ab30392

Browse files
committed
rgw/period: move realm notify out of period commit
require the callers to trigger the realm notify manually. RGWOp_Period_Post takes advantage of this to delay the realm notify until after it's sent its response to the client. this avoids racing with realm reload which will close the connection commit returns EEXIST errors directly so the caller can avoid the realm notify Signed-off-by: Casey Bodley <[email protected]>
1 parent ba8be21 commit ab30392

File tree

4 files changed

+24
-14
lines changed

4 files changed

+24
-14
lines changed

src/rgw/driver/rados/rgw_period.cc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,6 @@ int RGWPeriod::commit(const DoutPrefixProvider *dpp,
271271
}
272272
ldpp_dout(dpp, 4) << "Promoted to master zone and committed new period "
273273
<< id << dendl;
274-
realm.notify_new_period(dpp, *this, y);
275274
return 0;
276275
}
277276
// period must be based on current epoch
@@ -295,10 +294,6 @@ int RGWPeriod::commit(const DoutPrefixProvider *dpp,
295294
}
296295
// set as latest epoch
297296
r = update_latest_epoch(dpp, epoch, y);
298-
if (r == -EEXIST) {
299-
// already have this epoch (or a more recent one)
300-
return 0;
301-
}
302297
if (r < 0) {
303298
ldpp_dout(dpp, 0) << "failed to set latest epoch: " << cpp_strerror(-r) << dendl;
304299
return r;
@@ -310,7 +305,6 @@ int RGWPeriod::commit(const DoutPrefixProvider *dpp,
310305
}
311306
ldpp_dout(dpp, 4) << "Committed new epoch " << epoch
312307
<< " for period " << id << dendl;
313-
realm.notify_new_period(dpp, *this, y);
314308
return 0;
315309
}
316310

src/rgw/driver/rados/rgw_rest_realm.cc

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
22
// vim: ts=8 sw=2 smarttab ft=cpp
33

4+
#include <optional>
45
#include "common/errno.h"
56
#include "rgw_rest_realm.h"
67
#include "rgw_rest_s3.h"
@@ -81,14 +82,17 @@ void RGWOp_Period_Get::execute(optional_yield y)
8182

8283
// POST /admin/realm/period
8384
class RGWOp_Period_Post : public RGWOp_Period_Base {
85+
std::optional<RGWRealm> notify_realm;
8486
public:
8587
void execute(optional_yield y) override;
88+
void send_response() override;
8689
int check_caps(const RGWUserCaps& caps) override {
8790
return caps.check_cap("zone", RGW_CAP_WRITE);
8891
}
8992
int verify_permission(optional_yield) override {
9093
return check_caps(s->user->get_caps());
9194
}
95+
9296
const char* name() const override { return "post_period"; }
9397
RGWOpType get_type() override { return RGW_OP_PERIOD_POST; }
9498
};
@@ -139,9 +143,15 @@ void RGWOp_Period_Post::execute(optional_yield y)
139143
// if period id is empty, handle as 'period commit'
140144
if (period.get_id().empty()) {
141145
op_ret = period.commit(this, driver, realm, current_period, error_stream, y);
146+
if (op_ret == -EEXIST) {
147+
op_ret = 0; // succeed on retries so the op is idempotent
148+
return;
149+
}
142150
if (op_ret < 0) {
143151
ldpp_dout(this, -1) << "master zone failed to commit period" << dendl;
152+
return;
144153
}
154+
notify_realm = std::move(realm); // trigger realm reload
145155
return;
146156
}
147157

@@ -221,7 +231,7 @@ void RGWOp_Period_Post::execute(optional_yield y)
221231
ldpp_dout(this, 4) << "period " << period.get_id()
222232
<< " is newer than current period " << current_period.get_id()
223233
<< ", updating realm's current period and notifying zone" << dendl;
224-
realm.notify_new_period(this, period, y);
234+
notify_realm = std::move(realm); // trigger realm reload
225235
return;
226236
}
227237
// reflect the period into our local objects
@@ -234,11 +244,22 @@ void RGWOp_Period_Post::execute(optional_yield y)
234244
ldpp_dout(this, 4) << "period epoch " << period.get_epoch()
235245
<< " is newer than current epoch " << current_period.get_epoch()
236246
<< ", updating period's latest epoch and notifying zone" << dendl;
237-
realm.notify_new_period(this, period, y);
247+
notify_realm = std::move(realm); // trigger realm reload
238248
// update the period history
239249
period_history->insert(RGWPeriod{period});
240250
}
241251

252+
void RGWOp_Period_Post::send_response()
253+
{
254+
RGWOp_Period_Base::send_response();
255+
256+
if (notify_realm) {
257+
// trigger realm reload after sending the response, because reload may
258+
// race to close this connection
259+
notify_realm->notify_new_period(this, period, s->yield);
260+
}
261+
}
262+
242263
class RGWHandler_Period : public RGWHandler_Auth_S3 {
243264
protected:
244265
using RGWHandler_Auth_S3::RGWHandler_Auth_S3;

src/rgw/driver/rados/rgw_zone.cc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,6 @@ int commit_period(const DoutPrefixProvider* dpp, optional_yield y,
769769
}
770770
ldpp_dout(dpp, 4) << "Promoted to master zone and committed new period "
771771
<< info.id << dendl;
772-
(void) cfgstore->realm_notify_new_period(dpp, y, info);
773772
return 0;
774773
}
775774
// period must be based on current epoch
@@ -788,10 +787,6 @@ int commit_period(const DoutPrefixProvider* dpp, optional_yield y,
788787
// write the period
789788
constexpr bool exclusive = true;
790789
int r = cfgstore->create_period(dpp, y, exclusive, info);
791-
if (r == -EEXIST) {
792-
// already have this epoch (or a more recent one)
793-
return 0;
794-
}
795790
if (r < 0) {
796791
ldpp_dout(dpp, 0) << "failed to store period: " << cpp_strerror(r) << dendl;
797792
return r;
@@ -803,7 +798,6 @@ int commit_period(const DoutPrefixProvider* dpp, optional_yield y,
803798
}
804799
ldpp_dout(dpp, 4) << "Committed new epoch " << info.epoch
805800
<< " for period " << info.id << dendl;
806-
(void) cfgstore->realm_notify_new_period(dpp, y, info);
807801
return 0;
808802
}
809803

src/rgw/rgw_admin.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,7 @@ static int commit_period(rgw::sal::ConfigStore* cfgstore,
19421942
if (ret < 0) {
19431943
cerr << "failed to commit period: " << cpp_strerror(-ret) << std::endl;
19441944
}
1945+
(void) cfgstore->realm_notify_new_period(dpp(), null_yield, period);
19451946
return ret;
19461947
}
19471948

0 commit comments

Comments
 (0)