From fdea7f34829010aaf77e8bb7ae979b07887abe78 Mon Sep 17 00:00:00 2001 From: Jane Zhu Date: Tue, 1 Apr 2025 13:45:36 +0000 Subject: [PATCH] rgw: keep the tails when copying object to itself Signed-off-by: Jane Zhu (cherry picked from commit 333e4a9b0de745cf5be40c5f6c32df7a340b007a) Conflicts: src/rgw/driver/rados/rgw_rados.cc src/rgw/driver/rados/rgw_rados.h _do_write_meta() no req_context arg complete_atomic_modification() no optional_yield arg --- qa/workunits/rgw/test_rgw_orphan_list.sh | 31 ++++++++++++++++++++++++ src/rgw/driver/rados/rgw_rados.cc | 20 +++++++-------- src/rgw/driver/rados/rgw_rados.h | 10 ++++---- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/qa/workunits/rgw/test_rgw_orphan_list.sh b/qa/workunits/rgw/test_rgw_orphan_list.sh index 00d8ed64670b3..c66718a567ae5 100755 --- a/qa/workunits/rgw/test_rgw_orphan_list.sh +++ b/qa/workunits/rgw/test_rgw_orphan_list.sh @@ -460,6 +460,37 @@ done mys3cmd rb --recursive s3://$d_bkt mys3cmd rb --recursive s3://$o_bkt +############################################################ +# copy a multipart object to itself +# run gc process after the copy, then try to get the object + +o_bkt="orig-mp-bkt-8" + +mys3cmd mb s3://$o_bkt + +mp_obj="multipart-obj-1" +mys3cmd put -q $huge_obj s3://${o_bkt}/$mp_obj + +mys3cmd cp --mime-type="text/plain" s3://${o_bkt}/$mp_obj s3://${o_bkt}/$mp_obj + +##################################################################### +# FORCE GARBAGE COLLECTION +sleep 6 # since for testing age at which gc can happen is 5 secs +radosgw-admin gc process --include-all +##################################################################### + +mp_obj_retrieved="multipart-obj-1-retrieved" +mys3cmd get s3://${o_bkt}/$mp_obj $mp_obj_retrieved --force + +if [ -f $mp_obj_retrieved ]; then + rm -f $mp_obj_retrieved +else + echo "ERROR: failed to get the object after copying to itself" + exit 1 +fi + +mys3cmd rb --recursive s3://$o_bkt + ##################################################################### # FORCE GARBAGE COLLECTION sleep 6 # since for testing age at which gc can happen is 5 secs diff --git a/src/rgw/driver/rados/rgw_rados.cc b/src/rgw/driver/rados/rgw_rados.cc index 0f276ed6e97b2..b1b43dbc3179e 100644 --- a/src/rgw/driver/rados/rgw_rados.cc +++ b/src/rgw/driver/rados/rgw_rados.cc @@ -3017,9 +3017,8 @@ int RGWRados::swift_versioning_restore(RGWObjectCtx& obj_ctx, int RGWRados::Object::Write::_do_write_meta(const DoutPrefixProvider *dpp, uint64_t size, uint64_t accounted_size, map& attrs, - bool assume_noent, bool modify_tail, - void *_index_op, optional_yield y, - bool log_op) + bool assume_noent, void *_index_op, + optional_yield y, bool log_op) { RGWRados::Bucket::UpdateIndex *index_op = static_cast(_index_op); RGWRados *store = target->get_store(); @@ -3062,7 +3061,7 @@ int RGWRados::Object::Write::_do_write_meta(const DoutPrefixProvider *dpp, if (!ptag && !index_op->get_optag()->empty()) { ptag = index_op->get_optag(); } - r = target->prepare_atomic_modification(dpp, op, reset_obj, ptag, meta.if_match, meta.if_nomatch, false, modify_tail, y); + r = target->prepare_atomic_modification(dpp, op, reset_obj, ptag, meta.if_match, meta.if_nomatch, false, meta.modify_tail, y); if (r < 0) return r; @@ -3208,7 +3207,7 @@ int RGWRados::Object::Write::_do_write_meta(const DoutPrefixProvider *dpp, poolid = ioctx.get_id(); - r = target->complete_atomic_modification(dpp); + r = target->complete_atomic_modification(dpp, meta.keep_tail); if (r < 0) { ldpp_dout(dpp, 0) << "ERROR: complete_atomic_modification returned r=" << r << dendl; } @@ -3324,13 +3323,13 @@ int RGWRados::Object::Write::write_meta(const DoutPrefixProvider *dpp, uint64_t bool assume_noent = (meta.if_match == NULL && meta.if_nomatch == NULL); int r; if (assume_noent) { - r = _do_write_meta(dpp, size, accounted_size, attrs, assume_noent, meta.modify_tail, (void *)&index_op, y, log_op); + r = _do_write_meta(dpp, size, accounted_size, attrs, assume_noent, (void *)&index_op, y, log_op); if (r == -EEXIST) { assume_noent = false; } } if (!assume_noent) { - r = _do_write_meta(dpp, size, accounted_size, attrs, assume_noent, meta.modify_tail, (void *)&index_op, y, log_op); + r = _do_write_meta(dpp, size, accounted_size, attrs, assume_noent, (void *)&index_op, y, log_op); } return r; } @@ -4622,6 +4621,7 @@ int RGWRados::copy_obj(RGWObjectCtx& src_obj_ctx, write_op.meta.olh_epoch = olh_epoch; write_op.meta.delete_at = delete_at; write_op.meta.modify_tail = !copy_itself; + write_op.meta.keep_tail = copy_itself; ret = write_op.write_meta(dpp, obj_size, astate->accounted_size, attrs, y); if (ret < 0) { @@ -5000,9 +5000,9 @@ int RGWRados::bucket_suspended(const DoutPrefixProvider *dpp, rgw_bucket& bucket return 0; } -int RGWRados::Object::complete_atomic_modification(const DoutPrefixProvider *dpp) +int RGWRados::Object::complete_atomic_modification(const DoutPrefixProvider *dpp, bool keep_tail) { - if ((!manifest)|| state->keep_tail) + if ((!manifest) || state->keep_tail || keep_tail) return 0; cls_rgw_obj_chain chain; @@ -5554,7 +5554,7 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi } r = index_op.complete_del(dpp, poolid, epoch, state->mtime, params.remove_objs, y, log_op); - int ret = target->complete_atomic_modification(dpp); + int ret = target->complete_atomic_modification(dpp, false); if (ret < 0) { ldpp_dout(dpp, 0) << "ERROR: complete_atomic_modification returned ret=" << ret << dendl; } diff --git a/src/rgw/driver/rados/rgw_rados.h b/src/rgw/driver/rados/rgw_rados.h index 146eac2de588a..e04208604274b 100644 --- a/src/rgw/driver/rados/rgw_rados.h +++ b/src/rgw/driver/rados/rgw_rados.h @@ -685,7 +685,7 @@ public: int prepare_atomic_modification(const DoutPrefixProvider *dpp, librados::ObjectWriteOperation& op, bool reset_obj, const std::string *ptag, const char *ifmatch, const char *ifnomatch, bool removal_op, bool modify_tail, optional_yield y); - int complete_atomic_modification(const DoutPrefixProvider *dpp); + int complete_atomic_modification(const DoutPrefixProvider *dpp, bool keep_tail); public: Object(RGWRados *_store, const RGWBucketInfo& _bucket_info, RGWObjectCtx& _ctx, const rgw_obj& _obj) : store(_store), bucket_info(_bucket_info), @@ -797,13 +797,14 @@ public: const std::string *user_data; rgw_zone_set *zones_trace; bool modify_tail; + bool keep_tail; bool completeMultipart; bool appendable; MetaParams() : mtime(NULL), rmattrs(NULL), data(NULL), manifest(NULL), ptag(NULL), remove_objs(NULL), category(RGWObjCategory::Main), flags(0), if_match(NULL), if_nomatch(NULL), canceled(false), user_data(nullptr), zones_trace(nullptr), - modify_tail(false), completeMultipart(false), appendable(false) {} + modify_tail(false), keep_tail(false), completeMultipart(false), appendable(false) {} } meta; explicit Write(RGWRados::Object *_target) : target(_target) {} @@ -811,9 +812,8 @@ public: int _do_write_meta(const DoutPrefixProvider *dpp, uint64_t size, uint64_t accounted_size, std::map& attrs, - bool modify_tail, bool assume_noent, - void *index_op, optional_yield y, - bool log_op = true); + bool assume_noent, void *index_op, + optional_yield y, bool log_op = true); int write_meta(const DoutPrefixProvider *dpp, uint64_t size, uint64_t accounted_size, std::map& attrs, optional_yield y, bool log_op = true); int write_data(const char *data, uint64_t ofs, uint64_t len, bool exclusive); -- 2.39.5