]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: keep the tails when copying object to itself
authorJane Zhu <jzhu116@bloomberg.net>
Tue, 1 Apr 2025 13:45:36 +0000 (13:45 +0000)
committerYuri Weinstein <yweinste@redhat.com>
Fri, 4 Apr 2025 17:46:01 +0000 (17:46 +0000)
Signed-off-by: Jane Zhu <jzhu116@bloomberg.net>
(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
(cherry picked from commit fdea7f34829010aaf77e8bb7ae979b07887abe78)

qa/workunits/rgw/test_rgw_orphan_list.sh
src/rgw/driver/rados/rgw_rados.cc
src/rgw/driver/rados/rgw_rados.h

index 00d8ed64670b3eb66a6a44920d60b281c1637818..c66718a567ae55ae3af7e36dd41b180ef83d1f25 100755 (executable)
@@ -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
index 0f276ed6e97b28f7322513560aea99b9f6c7d75a..b1b43dbc3179ef56cd33bfc2ad59769d81923421 100644 (file)
@@ -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<string, bufferlist>& 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<RGWRados::Bucket::UpdateIndex *>(_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;
     }
index 146eac2de588a2b2dcc0510df2d1579149289c01..e04208604274bd9e0398bf34098804211c60e4c3 100644 (file)
@@ -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<std::string, bufferlist>& 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<std::string, bufferlist>& attrs, optional_yield y, bool log_op = true);
       int write_data(const char *data, uint64_t ofs, uint64_t len, bool exclusive);