]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: non-multipart uploads serve entire range on partNumber=1
authorCasey Bodley <cbodley@redhat.com>
Wed, 11 Oct 2023 21:45:17 +0000 (17:45 -0400)
committerCasey Bodley <cbodley@redhat.com>
Thu, 27 Mar 2025 19:50:51 +0000 (15:50 -0400)
and omit the x-amz-mp-parts-count response header

Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit 338440ae2c04ed6a14d35825f4503d1222266ed5)

Conflicts:
src/rgw/rgw_op.cc backport of ccd241c565aa898231e4bfa4ea313c3406b55391 moved error handling

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_op.cc
src/rgw/rgw_sal.h

index bf98b65bd80721c1dc47a8af04dba4dbae6794c2..6d365499d327cb334639fbc215ba9cdebb6c8e9e 100644 (file)
@@ -6334,6 +6334,9 @@ static int get_part_obj_state(const DoutPrefixProvider* dpp, optional_yield y,
                               int part_num, int* parts_count, bool prefetch,
                               RGWObjState** pstate, RGWObjManifest** pmanifest)
 {
+  if (!manifest) {
+    return -ERR_INVALID_PART;
+  }
   // navigate to the requested part in the manifest
   RGWObjManifest::obj_iterator end = manifest->obj_end(dpp);
   if (end.get_cur_part_id() == 0) { // not multipart
@@ -6440,22 +6443,27 @@ int RGWRados::Object::Read::prepare(optional_yield y, const DoutPrefixProvider *
   RGWBucketInfo& bucket_info = source->get_bucket_info();
 
   if (params.part_num) {
+    int parts_count = 0;
     // use the manifest to redirect to the requested part number
-    if (!manifest) {
-      return -ERR_INVALID_PART;
-    }
     r = get_part_obj_state(dpp, y, store, bucket_info, &source->get_ctx(),
-                           manifest, *params.part_num, params.parts_count,
+                           manifest, *params.part_num, &parts_count,
                            part_prefetch, &astate, &manifest);
-    if (r < 0) {
+    if (r == -ERR_INVALID_PART && *params.part_num == 1) {
+      // for non-multipart uploads, treat requests for the first part as a
+      // request for the entire range. this behavior is expected by the java
+      // sdk's TransferManager.download()
+      ldpp_dout(dpp, 4) << "requested part #" << *params.part_num
+          << ": " << cpp_strerror(r) << dendl;
+    } else if (r < 0) {
       ldpp_dout(dpp, 4) << "failed to read part #" << *params.part_num
           << ": " << cpp_strerror(r) << dendl;
       return -ERR_INVALID_PART;
-    }
-    if (!astate->exists) {
+    } else if (!astate->exists) {
       ldpp_dout(dpp, 4) << "part #" << *params.part_num
           << " does not exist" << dendl;
       return -ERR_INVALID_PART;
+    } else {
+      params.parts_count = parts_count;
     }
   }
 
index a1d9b1f4b02c67f118cf88e7a43a538fa4855b6b..fd007f99ac95afb6f3d16b6d3b1af4e0e5d00437 100644 (file)
@@ -764,7 +764,7 @@ public:
         std::map<std::string, bufferlist> *attrs;
         rgw_obj *target_obj;
         int* part_num = nullptr;
-        int* parts_count = nullptr;
+        std::optional<int> parts_count;
 
         Params() : lastmod(nullptr), obj_size(nullptr), attrs(nullptr),
                 target_obj(nullptr) {}
index 4150e710479798618179b26623abfe9212abf2b5..bcc7c7752d10745caeaf37be2168c9d899249db0 100644 (file)
@@ -2222,7 +2222,6 @@ int RadosObject::RadosReadOp::prepare(optional_yield y, const DoutPrefixProvider
   parent_op.params.lastmod = params.lastmod;
   parent_op.params.target_obj = params.target_obj;
   parent_op.params.part_num = params.part_num;
-  parent_op.params.parts_count = params.parts_count;
   parent_op.params.obj_size = &obj_size;
   parent_op.params.attrs = &source->get_attrs();
 
@@ -2232,6 +2231,7 @@ int RadosObject::RadosReadOp::prepare(optional_yield y, const DoutPrefixProvider
 
   source->set_instance(parent_op.state.obj.key.instance);
   source->set_obj_size(obj_size);
+  params.parts_count = parent_op.params.parts_count;
 
   return ret;
 }
index 0d5f3154125968a6e7372ae08ce5187ff14c8a5b..da5987b703867916712b862ac1db86d95138f12a 100644 (file)
@@ -2240,14 +2240,13 @@ void RGWGetObj::execute(optional_yield y)
   read_op->params.lastmod = &lastmod;
   if (multipart_part_num) {
     read_op->params.part_num = &*multipart_part_num;
-    multipart_parts_count.emplace(0);
-    read_op->params.parts_count = &*multipart_parts_count;
   }
 
   op_ret = read_op->prepare(s->yield, this);
   version_id = s->object->get_instance();
   s->obj_size = s->object->get_obj_size();
   attrs = s->object->get_attrs();
+  multipart_parts_count = read_op->params.parts_count;
   if (op_ret < 0)
     goto done_err;
 
index e6ba8a36c01914adb1dd3dc07eadf51a65fc0440..a1ef59c1e50816e9accd5576b67e52b1338665ed 100644 (file)
@@ -901,9 +901,9 @@ class Object {
 
         /// If non-null, read data/attributes from the given multipart part.
         int* part_num{nullptr};
-        /// If part_num is specified, the total number of multipart parts is
-        /// written to this output parameter.
-        int* parts_count{nullptr};
+        /// If part_num is specified and the object is multipart, the total
+        /// number of multipart parts is assigned to this output parameter.
+        std::optional<int> parts_count;
       } params;
 
       virtual ~ReadOp() = default;