]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/lc: Fix issues with non-current objects with instance empty 63030/head
authorSoumya Koduri <skoduri@redhat.com>
Mon, 7 Oct 2024 11:24:02 +0000 (16:54 +0530)
committerSoumya Koduri <skoduri@redhat.com>
Tue, 29 Apr 2025 06:13:45 +0000 (11:43 +0530)
When the bucket versioning is enabled, old plain object entry is converted
to versioned by updating its instance as "null" in its raw head/old object.
However its instance remains empty in the bi list entry. Same is the case for
the entries created after versioning is suspended and re-enabled.

So to access such objects which are non-current, we need to set rgw_obj_key.instance as
1) "null" to read the actual raw obj and
2) empty while accessing/updating their bi entry.

Fixes: https://tracker.ceph.com/issues/71120
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
(cherry picked from commit 60149ade9d5193a78fa5fd83e28919f8f36fe05d)

src/rgw/driver/rados/rgw_lc_tier.cc
src/rgw/driver/rados/rgw_rados.cc
src/rgw/driver/rados/rgw_rados.h
src/rgw/driver/rados/rgw_sal_rados.cc
src/rgw/rgw_lc.cc

index 34dba346eba7d5f0ca2d667c60a0ed8680a93144..3add373e2791918bebc935cc3be7065e3a961ca6 100644 (file)
@@ -76,8 +76,9 @@ WRITE_CLASS_ENCODER(rgw_lc_multipart_upload_info)
 
 static inline string get_key_instance(const rgw_obj_key& key)
 {
-  if (!key.instance.empty() &&
-      !key.have_null_instance()) {
+  // if non-current entry, add versionID to the
+  // transitioned object name including "null".
+  if (!key.instance.empty()) {
     return "-" + key.instance;
   }
   return "";
index d29ae6a1116319e5c710cd7017611898cc1073a8..b75abc29dda9cc17d177c90c9720af3af4ad0b99 100644 (file)
@@ -5112,7 +5112,7 @@ int RGWRados::copy_obj_data(RGWObjectCtx& obj_ctx,
 
 int RGWRados::transition_obj(RGWObjectCtx& obj_ctx,
                              RGWBucketInfo& bucket_info,
-                             const rgw_obj& obj,
+                             rgw_obj obj,
                              const rgw_placement_rule& placement_rule,
                              const real_time& mtime,
                              uint64_t olh_epoch,
@@ -5143,6 +5143,11 @@ int RGWRados::transition_obj(RGWObjectCtx& obj_ctx,
     return -ECANCELED;
   }
 
+  // bi expects empty instance for the entries created when bucket versioning
+  // is not enabled or suspended.
+  if (obj.key.instance == "null") {
+    obj.key.instance.clear();
+  }
   attrs.erase(RGW_ATTR_ID_TAG);
   attrs.erase(RGW_ATTR_TAIL_TAG);
 
index a4365b2dbefa94e088d33b144ceab10508a77ecd..4ed23f893bce61bbc0ad22299c1921a19f127b59 100644 (file)
@@ -1236,7 +1236,7 @@ public:
 
   int transition_obj(RGWObjectCtx& obj_ctx,
                      RGWBucketInfo& bucket_info,
-                     const rgw_obj& obj,
+                     rgw_obj obj,
                      const rgw_placement_rule& placement_rule,
                      const real_time& mtime,
                      uint64_t olh_epoch,
index f773dac938599f294fedb4e5beaba4b7e6e4b177..dec0fcb4d4dab70fa4609f5eb51cdcd634f6d410 100644 (file)
@@ -2665,6 +2665,13 @@ int RadosObject::write_cloud_tier(const DoutPrefixProvider* dpp,
 {
   rgw::sal::RadosPlacementTier* rtier = static_cast<rgw::sal::RadosPlacementTier*>(tier);
   map<string, bufferlist> attrs = get_attrs();
+  rgw_obj_key& obj_key = get_key();
+  // bi expects empty instance for the entries created when bucket versioning
+  // is not enabled or suspended.
+  if (obj_key.instance == "null") {
+      obj_key.instance.clear();
+  }
+
   RGWRados::Object op_target(store->getRados(), bucket->get_info(), *rados_ctx, get_obj());
   RGWRados::Object::Write obj_op(&op_target);
 
index 489960bdbf88f3d69ab06d5142086877e9d09554..5e6b9f182d96e884d5fbd79dc2dcdd8c67a4f6fa 100644 (file)
@@ -495,6 +495,14 @@ struct lc_op_ctx {
       octx(env.driver), dpp(dpp), wq(wq)
     {
       obj = bucket->get_object(o.key);
+      /* once bucket versioning is enabled, the non-current entries with
+       * instance empty should have instance set to "null" to be able
+       * to correctly read its olh version entry.
+       */
+      if (o.key.instance.empty() && bucket->versioned() && !o.is_current()) {
+        rgw_obj_key& obj_key = obj->get_key();
+        obj_key.instance = "null";
+      }
     }
 
   bool next_has_same_name(const std::string& key_name) {
@@ -1358,9 +1366,9 @@ public:
   int delete_tier_obj(lc_op_ctx& oc) {
     int ret = 0;
 
-    /* If bucket is versioned, create delete_marker for current version
+    /* If bucket has versioning enabled, create delete_marker for current version
      */
-    if (! oc.bucket->versioned()) {
+    if (! oc.bucket->versioning_enabled()) {
       ret =
           remove_expired_obj(oc.dpp, oc, true, {rgw::notify::ObjectTransition});
       ldpp_dout(oc.dpp, 20) << "delete_tier_obj Object(key:" << oc.o.key
@@ -1390,9 +1398,10 @@ public:
 
   int transition_obj_to_cloud(lc_op_ctx& oc) {
     int ret{0};
-    /* If CurrentVersion object, remove it & create delete marker */
+    /* If CurrentVersion object & bucket has versioning enabled, remove it &
+     * create delete marker */
     bool delete_object = (!oc.tier->retain_head_object() ||
-                     (oc.o.is_current() && oc.bucket->versioned()));
+                     (oc.o.is_current() && oc.bucket->versioning_enabled()));
 
     /* notifications */
     auto& bucket = oc.bucket;