Skip to content

Commit e6550c1

Browse files
authored
Merge pull request #51715 from awojno-bloomberg/replication-race-condition-fix
RGW: Pass and check destination zone trace when fetching object Reviewed-by: Casey Bodley <cbodley@redhat.com> Reviewed-by: Mark Kogan <mkogan@redhat.com>
2 parents 1e3835a + e70fcf9 commit e6550c1

7 files changed

Lines changed: 34 additions & 5 deletions

File tree

src/cls/rgw/cls_rgw_types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ struct rgw_zone_set_entry {
3838
return (location_key < e.location_key);
3939
}
4040

41+
bool operator==(const rgw_zone_set_entry& e) const {
42+
return zone == e.zone && location_key == e.location_key;
43+
}
44+
4145
rgw_zone_set_entry() {}
4246
rgw_zone_set_entry(const std::string& _zone,
4347
std::optional<std::string> _location_key) : zone(_zone),

src/rgw/driver/rados/rgw_rados.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3792,7 +3792,7 @@ int RGWRados::stat_remote_obj(const DoutPrefixProvider *dpp,
37923792
int ret = conn->get_obj(dpp, user_id, info, src_obj, pmod, unmod_ptr,
37933793
dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
37943794
prepend_meta, get_op, rgwx_stat,
3795-
sync_manifest, skip_decrypt, sync_cloudtiered,
3795+
sync_manifest, skip_decrypt, nullptr, sync_cloudtiered,
37963796
true, &cb, &in_stream_req);
37973797
if (ret < 0) {
37983798
return ret;
@@ -3989,6 +3989,7 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx,
39893989
const real_time *pmod = mod_ptr;
39903990

39913991
obj_time_weight dest_mtime_weight;
3992+
rgw_zone_set_entry dst_zone_trace(svc.zone->get_zone().id, dest_bucket_info.bucket.get_key());
39923993

39933994
if (copy_if_newer) {
39943995
/* need to get mtime for destination */
@@ -4011,8 +4012,8 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx,
40114012
ret = conn->get_obj(dpp, user_id, info, src_obj, pmod, unmod_ptr,
40124013
dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
40134014
prepend_meta, get_op, rgwx_stat,
4014-
sync_manifest, skip_decrypt, sync_cloudtiered,
4015-
true,
4015+
sync_manifest, skip_decrypt, &dst_zone_trace,
4016+
sync_cloudtiered, true,
40164017
&cb, &in_stream_req);
40174018
if (ret < 0) {
40184019
goto set_err_state;

src/rgw/rgw_op.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,6 +2308,23 @@ void RGWGetObj::execute(optional_yield y)
23082308
filter = &*decompress;
23092309
}
23102310

2311+
attr_iter = attrs.find(RGW_ATTR_OBJ_REPLICATION_TRACE);
2312+
if (attr_iter != attrs.end()) {
2313+
try {
2314+
std::vector<rgw_zone_set_entry> zones;
2315+
auto p = attr_iter->second.cbegin();
2316+
decode(zones, p);
2317+
for (const auto& zone: zones) {
2318+
if (zone == dst_zone_trace) {
2319+
op_ret = -ERR_NOT_MODIFIED;
2320+
ldpp_dout(this, 4) << "Object already has been copied to this destination. Returning "
2321+
<< op_ret << dendl;
2322+
goto done_err;
2323+
}
2324+
}
2325+
} catch (const buffer::error&) {}
2326+
}
2327+
23112328
if (get_type() == RGW_OP_GET_OBJ && get_data) {
23122329
op_ret = handle_cloudtier_obj(attrs, sync_cloudtiered);
23132330
if (op_ret < 0) {

src/rgw/rgw_op.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ class RGWGetObj : public RGWOp {
359359
std::string lo_etag;
360360
bool rgwx_stat; /* extended rgw stat operation */
361361
std::string version_id;
362+
rgw_zone_set_entry dst_zone_trace;
362363

363364
// compression attrs
364365
RGWCompressionInfo cs_info;

src/rgw/rgw_rest_conn.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ int RGWRESTConn::get_obj(const DoutPrefixProvider *dpp, const rgw_user& uid, req
203203
uint32_t mod_zone_id, uint64_t mod_pg_ver,
204204
bool prepend_metadata, bool get_op, bool rgwx_stat,
205205
bool sync_manifest, bool skip_decrypt,
206-
bool sync_cloudtiered,
206+
rgw_zone_set_entry *dst_zone_trace, bool sync_cloudtiered,
207207
bool send, RGWHTTPStreamRWRequest::ReceiveCB *cb, RGWRESTStreamRWRequest **req)
208208
{
209209
get_obj_params params;
@@ -217,6 +217,7 @@ int RGWRESTConn::get_obj(const DoutPrefixProvider *dpp, const rgw_user& uid, req
217217
params.sync_manifest = sync_manifest;
218218
params.skip_decrypt = skip_decrypt;
219219
params.sync_cloudtiered = sync_cloudtiered;
220+
params.dst_zone_trace = dst_zone_trace;
220221
params.cb = cb;
221222
return get_obj(dpp, obj, params, send, req);
222223
}
@@ -245,6 +246,9 @@ int RGWRESTConn::get_obj(const DoutPrefixProvider *dpp, const rgw_obj& obj, cons
245246
if (in_params.skip_decrypt) {
246247
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "skip-decrypt", ""));
247248
}
249+
if (in_params.dst_zone_trace) {
250+
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "if-not-replicated-to", in_params.dst_zone_trace->to_str()));
251+
}
248252
if (!obj.key.instance.empty()) {
249253
params.push_back(param_pair_t("versionId", obj.key.instance));
250254
}

src/rgw/rgw_rest_conn.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ class RGWRESTConn
162162
bool range_is_set{false};
163163
uint64_t range_start{0};
164164
uint64_t range_end{0};
165+
rgw_zone_set_entry *dst_zone_trace{nullptr};
165166
};
166167

167168
int get_obj(const DoutPrefixProvider *dpp, const rgw_obj& obj, const get_obj_params& params, bool send, RGWRESTStreamRWRequest **req);
@@ -170,7 +171,7 @@ class RGWRESTConn
170171
const ceph::real_time *mod_ptr, const ceph::real_time *unmod_ptr,
171172
uint32_t mod_zone_id, uint64_t mod_pg_ver,
172173
bool prepend_metadata, bool get_op, bool rgwx_stat, bool sync_manifest,
173-
bool skip_decrypt, bool sync_cloudtiered,
174+
bool skip_decrypt, rgw_zone_set_entry *dst_zone_trace, bool sync_cloudtiered,
174175
bool send, RGWHTTPStreamRWRequest::ReceiveCB *cb, RGWRESTStreamRWRequest **req);
175176
int complete_request(RGWRESTStreamRWRequest *req,
176177
std::string *etag,

src/rgw/rgw_rest_s3.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ int RGWGetObj_ObjStore_S3::get_params(optional_yield y)
302302
// multisite sync requests should fetch cloudtiered objects
303303
sync_cloudtiered = s->info.args.exists(RGW_SYS_PARAM_PREFIX "sync-cloudtiered");
304304

305+
dst_zone_trace = s->info.args.get(RGW_SYS_PARAM_PREFIX "if-not-replicated-to");
305306
get_torrent = s->info.args.exists("torrent");
306307

307308
return RGWGetObj_ObjStore::get_params(y);

0 commit comments

Comments
 (0)