From 8a457f0d78b5a283479cad0298f210e8c31089da Mon Sep 17 00:00:00 2001 From: Ali Masarwa Date: Sun, 3 Aug 2025 14:00:11 +0300 Subject: [PATCH] RGW | fix conditional MultiWrite Signed-off-by: Ali Masarwa --- src/rgw/driver/d4n/rgw_sal_d4n.cc | 4 +++- src/rgw/driver/d4n/rgw_sal_d4n.h | 4 +++- src/rgw/driver/motr/rgw_sal_motr.cc | 4 +++- src/rgw/driver/motr/rgw_sal_motr.h | 4 +++- src/rgw/driver/posix/rgw_sal_posix.cc | 4 +++- src/rgw/driver/posix/rgw_sal_posix.h | 4 +++- src/rgw/driver/rados/rgw_putobj_processor.cc | 4 ++++ src/rgw/driver/rados/rgw_sal_rados.cc | 6 +++++- src/rgw/driver/rados/rgw_sal_rados.h | 4 +++- src/rgw/rgw_op.cc | 2 +- src/rgw/rgw_op.h | 2 ++ src/rgw/rgw_rest_s3.cc | 3 +++ src/rgw/rgw_sal.h | 4 +++- src/rgw/rgw_sal_dbstore.cc | 4 +++- src/rgw/rgw_sal_dbstore.h | 4 +++- src/rgw/rgw_sal_filter.cc | 4 +++- src/rgw/rgw_sal_filter.h | 4 +++- 17 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/rgw/driver/d4n/rgw_sal_d4n.cc b/src/rgw/driver/d4n/rgw_sal_d4n.cc index 1b118726f1e..6c6700d7f1a 100644 --- a/src/rgw/driver/d4n/rgw_sal_d4n.cc +++ b/src/rgw/driver/d4n/rgw_sal_d4n.cc @@ -2891,7 +2891,9 @@ int D4NFilterMultipartUpload::complete(const DoutPrefixProvider *dpp, std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) + prefix_map_t& processed_prefixes, + const char *if_match, + const char *if_nomatch) { //call next->complete to complete writing the object to the backend store auto ret = next->complete(dpp, y, cct, part_etags, remove_objs, accounted_size, diff --git a/src/rgw/driver/d4n/rgw_sal_d4n.h b/src/rgw/driver/d4n/rgw_sal_d4n.h index 1478aa5f40f..473a03a4260 100644 --- a/src/rgw/driver/d4n/rgw_sal_d4n.h +++ b/src/rgw/driver/d4n/rgw_sal_d4n.h @@ -355,7 +355,9 @@ public: std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) override; + prefix_map_t& processed_prefixes, + const char *if_match = nullptr, + const char *if_nomatch = nullptr) override; }; } } // namespace rgw::sal diff --git a/src/rgw/driver/motr/rgw_sal_motr.cc b/src/rgw/driver/motr/rgw_sal_motr.cc index 3cb654fe41b..f156ab2d4ab 100644 --- a/src/rgw/driver/motr/rgw_sal_motr.cc +++ b/src/rgw/driver/motr/rgw_sal_motr.cc @@ -2675,7 +2675,9 @@ int MotrMultipartUpload::complete(const DoutPrefixProvider *dpp, std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) + prefix_map_t& processed_prefixes, + const char *if_match, + const char *if_nomatch) { char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE]; char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16]; diff --git a/src/rgw/driver/motr/rgw_sal_motr.h b/src/rgw/driver/motr/rgw_sal_motr.h index 709b77c34a5..cf4cf1069b0 100644 --- a/src/rgw/driver/motr/rgw_sal_motr.h +++ b/src/rgw/driver/motr/rgw_sal_motr.h @@ -939,7 +939,9 @@ public: std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) override; + prefix_map_t& processed_prefixes, + const char *if_match = nullptr, + const char *if_nomatch = nullptr) override; virtual int cleanup_orphaned_parts(const DoutPrefixProvider *dpp, CephContext *cct, optional_yield y, const rgw_obj& obj, diff --git a/src/rgw/driver/posix/rgw_sal_posix.cc b/src/rgw/driver/posix/rgw_sal_posix.cc index b309d0b203f..9fe4fe3d0ca 100644 --- a/src/rgw/driver/posix/rgw_sal_posix.cc +++ b/src/rgw/driver/posix/rgw_sal_posix.cc @@ -3918,7 +3918,9 @@ int POSIXMultipartUpload::complete(const DoutPrefixProvider *dpp, std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) + prefix_map_t& processed_prefixes, + const char *if_match, + const char *if_nomatch) { char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE]; char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16]; diff --git a/src/rgw/driver/posix/rgw_sal_posix.h b/src/rgw/driver/posix/rgw_sal_posix.h index fe664574d2d..f9193eb4aa3 100644 --- a/src/rgw/driver/posix/rgw_sal_posix.h +++ b/src/rgw/driver/posix/rgw_sal_posix.h @@ -1284,7 +1284,9 @@ public: std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) override; + prefix_map_t& processed_prefixes, + const char *if_match = nullptr, + const char *if_nomatch = nullptr) override; virtual int cleanup_orphaned_parts(const DoutPrefixProvider *dpp, CephContext *cct, optional_yield y, const rgw_obj& obj, diff --git a/src/rgw/driver/rados/rgw_putobj_processor.cc b/src/rgw/driver/rados/rgw_putobj_processor.cc index 645f744be44..c892d9c1dff 100644 --- a/src/rgw/driver/rados/rgw_putobj_processor.cc +++ b/src/rgw/driver/rados/rgw_putobj_processor.cc @@ -560,6 +560,8 @@ int MultipartObjectProcessor::complete( obj_op.meta.delete_at = delete_at; obj_op.meta.zones_trace = zones_trace; obj_op.meta.modify_tail = true; + obj_op.meta.if_match = if_match; + obj_op.meta.if_nomatch = if_nomatch; r = obj_op.write_meta(actual_size, accounted_size, attrs, rctx, writer.get_trace(), flags & rgw::sal::FLAG_LOG_OP); @@ -791,6 +793,8 @@ int AppendObjectProcessor::complete( obj_op.meta.modify_tail = true; obj_op.meta.keep_tail = keep_tail; obj_op.meta.appendable = true; + obj_op.meta.if_match = if_match; + obj_op.meta.if_nomatch = if_nomatch; //Add the append part number bufferlist cur_part_num_bl; using ceph::encode; diff --git a/src/rgw/driver/rados/rgw_sal_rados.cc b/src/rgw/driver/rados/rgw_sal_rados.cc index 6c74ccde9c9..de0d37f046c 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.cc +++ b/src/rgw/driver/rados/rgw_sal_rados.cc @@ -4149,7 +4149,9 @@ int RadosMultipartUpload::complete(const DoutPrefixProvider *dpp, std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) + prefix_map_t& processed_prefixes, + const char *if_match, + const char *if_nomatch) { char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE]; char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16]; @@ -4340,6 +4342,8 @@ int RadosMultipartUpload::complete(const DoutPrefixProvider *dpp, obj_op.meta.modify_tail = true; obj_op.meta.completeMultipart = true; obj_op.meta.olh_epoch = olh_epoch; + obj_op.meta.if_match = if_match; + obj_op.meta.if_nomatch = if_nomatch; const req_context rctx{dpp, y, nullptr}; ret = obj_op.write_meta(ofs, accounted_size, attrs, rctx, get_trace()); diff --git a/src/rgw/driver/rados/rgw_sal_rados.h b/src/rgw/driver/rados/rgw_sal_rados.h index eb48cc31634..4ab9141e18b 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.h +++ b/src/rgw/driver/rados/rgw_sal_rados.h @@ -875,7 +875,9 @@ public: std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) override; + prefix_map_t& processed_prefixes, + const char *if_match = nullptr, + const char *if_nomatch = nullptr) override; virtual int cleanup_orphaned_parts(const DoutPrefixProvider *dpp, CephContext *cct, optional_yield y, const rgw_obj& obj, diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 36fc34961e5..8a7af75f920 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -7197,7 +7197,7 @@ void RGWCompleteMultipart::execute(optional_yield y) op_ret = upload->complete(this, y, s->cct, parts->parts, remove_objs, accounted_size, compressed, cs_info, ofs, s->req_id, s->owner, olh_epoch, - s->object.get(), processed_prefixes); + s->object.get(), processed_prefixes, if_match, if_nomatch); if (op_ret < 0) { ldpp_dout(this, 0) << "ERROR: upload complete failed ret=" << op_ret << dendl; return; diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 85f283551ee..f3068fe5551 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -2015,6 +2015,8 @@ protected: std::optional cksum; std::optional armored_cksum; off_t ofs = 0; + const char *if_match{nullptr}; + const char *if_nomatch{nullptr}; public: RGWCompleteMultipart() {} diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 73bd030bbaa..df17c2d1277 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -4668,6 +4668,9 @@ int RGWCompleteMultipart_ObjStore_S3::get_params(optional_yield y) return ret; } + if_match = s->info.env->get("HTTP_IF_MATCH"); + if_nomatch = s->info.env->get("HTTP_IF_NONE_MATCH"); + map_qs_metadata(s, true); return do_aws4_auth_completion(); diff --git a/src/rgw/rgw_sal.h b/src/rgw/rgw_sal.h index 42626160c13..2d6d1bed276 100644 --- a/src/rgw/rgw_sal.h +++ b/src/rgw/rgw_sal.h @@ -1530,7 +1530,9 @@ public: std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) = 0; + prefix_map_t& processed_prefixes, + const char *if_match = nullptr, + const char *if_nomatch = nullptr) = 0; /** Cleanup orphaned parts caused by racing condition involving part upload retry */ virtual int cleanup_orphaned_parts(const DoutPrefixProvider *dpp, CephContext *cct, optional_yield y, diff --git a/src/rgw/rgw_sal_dbstore.cc b/src/rgw/rgw_sal_dbstore.cc index 3b456b46366..2bb397c35a5 100644 --- a/src/rgw/rgw_sal_dbstore.cc +++ b/src/rgw/rgw_sal_dbstore.cc @@ -926,7 +926,9 @@ namespace rgw::sal { std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) + prefix_map_t& processed_prefixes, + const char *if_match, + const char *if_nomatch) { char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE]; char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16]; diff --git a/src/rgw/rgw_sal_dbstore.h b/src/rgw/rgw_sal_dbstore.h index 1fa10e0c70b..c676b77cf74 100644 --- a/src/rgw/rgw_sal_dbstore.h +++ b/src/rgw/rgw_sal_dbstore.h @@ -461,7 +461,9 @@ protected: std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) override; + prefix_map_t& processed_prefixes, + const char *if_match = nullptr, + const char *if_nomatch = nullptr) override; virtual int cleanup_orphaned_parts(const DoutPrefixProvider *dpp, CephContext *cct, optional_yield y, const rgw_obj& obj, diff --git a/src/rgw/rgw_sal_filter.cc b/src/rgw/rgw_sal_filter.cc index 99c5168fdde..2dbaa49d1af 100644 --- a/src/rgw/rgw_sal_filter.cc +++ b/src/rgw/rgw_sal_filter.cc @@ -1334,7 +1334,9 @@ int FilterMultipartUpload::complete(const DoutPrefixProvider *dpp, std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) + prefix_map_t& processed_prefixes, + const char *if_match, + const char *if_nomatch) { return next->complete(dpp, y, cct, part_etags, remove_objs, accounted_size, compressed, cs_info, ofs, tag, owner, olh_epoch, diff --git a/src/rgw/rgw_sal_filter.h b/src/rgw/rgw_sal_filter.h index 8607712f6f1..086e8bc733a 100644 --- a/src/rgw/rgw_sal_filter.h +++ b/src/rgw/rgw_sal_filter.h @@ -978,7 +978,9 @@ public: std::string& tag, ACLOwner& owner, uint64_t olh_epoch, rgw::sal::Object* target_obj, - prefix_map_t& processed_prefixes) override; + prefix_map_t& processed_prefixes, + const char *if_match = nullptr, + const char *if_nomatch = nullptr) override; virtual int cleanup_orphaned_parts(const DoutPrefixProvider *dpp, CephContext *cct, optional_yield y, const rgw_obj& obj, -- 2.39.5