From e49778e73e60defeccfcb603d55fe5df501b34f3 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Wed, 26 Jun 2024 10:52:37 -0400 Subject: [PATCH] rgw: fix multipart get part when count==1 the RGWObjManifest for multipart uploads is subtly different when there's only a single part. in that case, get_cur_part_id() for the final rule returns 1 where it otherwise returns (parts_count + 1) this caused two problems: * we returned a parts_count of 0 instead 1, and * the do-while loop got stuck in an infinite loop expecting the last rule's part id to be higher than the requested part id Fixes: https://tracker.ceph.com/issues/66705 Signed-off-by: Casey Bodley (cherry picked from commit 562e0ce9baac53e714d91a46b4f0114b82827026) --- src/rgw/driver/rados/rgw_rados.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/rgw/driver/rados/rgw_rados.cc b/src/rgw/driver/rados/rgw_rados.cc index 45d50452e03c5..f26e45a53e9b4 100644 --- a/src/rgw/driver/rados/rgw_rados.cc +++ b/src/rgw/driver/rados/rgw_rados.cc @@ -6634,12 +6634,15 @@ static int get_part_obj_state(const DoutPrefixProvider* dpp, optional_yield y, } // 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 + const int last_part_id = end.get_cur_part_id(); + if (last_part_id == 0) { // not multipart ldpp_dout(dpp, 20) << "object does not have a multipart manifest" << dendl; return -ERR_INVALID_PART; } if (parts_count) { - *parts_count = end.get_cur_part_id() - 1; + // when a multipart upload only contains a single part, the last part id + // is off by one. don't let parts_count go to 0 + *parts_count = std::max(1, last_part_id - 1); } ldpp_dout(dpp, 20) << "seeking to part #" << part_num << " in the object manifest" << dendl; @@ -6699,7 +6702,7 @@ static int get_part_obj_state(const DoutPrefixProvider* dpp, optional_yield y, do { ++iter; gen.create_next(iter.get_ofs() - part_offset); - } while (iter.get_cur_part_id() == part_num); + } while (iter != end && iter.get_cur_part_id() == part_num); // update the object size sm->state.size = part_manifest.get_obj_size(); -- 2.39.5