diff options
author | Casey Bodley <cbodley@redhat.com> | 2023-02-17 14:47:05 +0100 |
---|---|---|
committer | Casey Bodley <cbodley@redhat.com> | 2023-11-21 17:09:23 +0100 |
commit | 01d8b4c38bdf98c2c2f8777200a1ba45a954a05d (patch) | |
tree | 063404a10ceb6b592255a578b9ca296a2344db6d /src/rgw/driver/rados | |
parent | rgw/rados: add obj_find_part() to RGWObjManifest (diff) | |
download | ceph-01d8b4c38bdf98c2c2f8777200a1ba45a954a05d.tar.xz ceph-01d8b4c38bdf98c2c2f8777200a1ba45a954a05d.zip |
rgw/rados: part support for RGWRados::Object::Read
Signed-off-by: Casey Bodley <cbodley@redhat.com>
Diffstat (limited to 'src/rgw/driver/rados')
-rw-r--r-- | src/rgw/driver/rados/rgw_rados.cc | 112 | ||||
-rw-r--r-- | src/rgw/driver/rados/rgw_rados.h | 2 | ||||
-rw-r--r-- | src/rgw/driver/rados/rgw_sal_rados.cc | 2 |
3 files changed, 115 insertions, 1 deletions
diff --git a/src/rgw/driver/rados/rgw_rados.cc b/src/rgw/driver/rados/rgw_rados.cc index fc1d7b7a685..c5624ba0171 100644 --- a/src/rgw/driver/rados/rgw_rados.cc +++ b/src/rgw/driver/rados/rgw_rados.cc @@ -6527,15 +6527,105 @@ int RGWRados::set_attrs(const DoutPrefixProvider *dpp, RGWObjectCtx* octx, RGWBu return 0; } +static int get_part_obj_state(const DoutPrefixProvider* dpp, optional_yield y, + RGWRados* store, RGWBucketInfo& bucket_info, + RGWObjectCtx* rctx, RGWObjManifest* manifest, + int part_num, int* parts_count, bool prefetch, + RGWObjState** pstate, RGWObjManifest** pmanifest) +{ + // 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 + 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; + } + ldpp_dout(dpp, 20) << "seeking to part #" << part_num + << " in the object manifest" << dendl; + RGWObjManifest::obj_iterator iter = manifest->obj_find_part(dpp, part_num); + if (iter == end) { // part number not found + ldpp_dout(dpp, 20) << "failed to find part #" << part_num + << " in the object manifest" << dendl; + return -ERR_INVALID_PART; + } + auto head_obj = iter.get_location().get_head_obj(); + if (!head_obj) { // iterator points to a tail object + ldpp_dout(dpp, 20) << "object manifest for part #" << part_num + << " points to a tail object" << dendl; + return -ERR_INVALID_PART; + } + const auto part_offset = iter.get_ofs(); + + // read the part's head object + if (prefetch) { + rctx->set_prefetch_data(*head_obj); + } + RGWObjStateManifest* sm = nullptr; + constexpr bool follow_olh = false; // parts aren't versioned + int r = store->get_obj_state(dpp, rctx, bucket_info, *head_obj, + &sm, follow_olh, y); + if (r < 0) { + return r; + } + *pstate = &sm->state; + + // if the part has its own manifest, use it directly + if (sm->manifest) { + *pmanifest = &*sm->manifest; + return 0; + } + + // create a new manifest for just this part + sm->manifest.emplace(); + RGWObjManifest& part_manifest = *sm->manifest; + part_manifest.set_multipart_part_rule(iter.get_stripe_size(), part_num); + + if (auto& prefix = iter.get_cur_override_prefix(); !prefix.empty()) { + // the part was reuploaded with a different prefix + part_manifest.set_prefix(prefix); + } else { + part_manifest.set_prefix(manifest->get_prefix()); + } + + RGWObjManifest::generator gen; + gen.create_begin(store->ctx(), &part_manifest, + manifest->get_head_placement_rule(), + &manifest->get_tail_placement().placement_rule, + head_obj->bucket, *head_obj); + + // copy each of the part's stripes into the new manifest. the final call to + // create_next() uses the starting offset of the next part + do { + ++iter; + gen.create_next(iter.get_ofs() - part_offset); + } while (iter.get_cur_part_id() == part_num); + + // update the object size + sm->state.size = part_manifest.get_obj_size(); + + *pmanifest = &part_manifest; + return 0; +} + int RGWRados::Object::Read::prepare(optional_yield y, const DoutPrefixProvider *dpp) { RGWRados *store = source->get_store(); CephContext *cct = store->ctx(); + RGWObjectCtx& obj_ctx = source->get_ctx(); bufferlist etag; map<string, bufferlist>::iterator iter; + bool part_prefetch = false; + if (params.part_num) { + // prefetch from the part's head object instead of the multipart head + auto sm = obj_ctx.get_state(source->get_obj()); + part_prefetch = std::exchange(sm->state.prefetch_data, false); + } + RGWObjState *astate; RGWObjManifest *manifest = nullptr; int r = source->get_state(dpp, &astate, &manifest, true, y); @@ -6546,7 +6636,27 @@ int RGWRados::Object::Read::prepare(optional_yield y, const DoutPrefixProvider * return -ENOENT; } - const RGWBucketInfo& bucket_info = source->get_bucket_info(); + RGWBucketInfo& bucket_info = source->get_bucket_info(); + + if (params.part_num) { + // 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, + part_prefetch, &astate, &manifest); + 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) { + ldpp_dout(dpp, 4) << "part #" << *params.part_num + << " does not exist" << dendl; + return -ERR_INVALID_PART; + } + } state.obj = astate->obj; store->obj_to_raw(bucket_info.placement_rule, state.obj, &state.head_obj); diff --git a/src/rgw/driver/rados/rgw_rados.h b/src/rgw/driver/rados/rgw_rados.h index d8cba7b9b4e..89e4576a478 100644 --- a/src/rgw/driver/rados/rgw_rados.h +++ b/src/rgw/driver/rados/rgw_rados.h @@ -769,6 +769,8 @@ public: std::map<std::string, bufferlist> *attrs; rgw_obj *target_obj; uint64_t *epoch; + int* part_num = nullptr; + int* parts_count = nullptr; Params() : lastmod(nullptr), obj_size(nullptr), attrs(nullptr), target_obj(nullptr), epoch(nullptr) diff --git a/src/rgw/driver/rados/rgw_sal_rados.cc b/src/rgw/driver/rados/rgw_sal_rados.cc index ed6e2525ac2..e619e968114 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.cc +++ b/src/rgw/driver/rados/rgw_sal_rados.cc @@ -1946,6 +1946,8 @@ int RadosObject::RadosReadOp::prepare(optional_yield y, const DoutPrefixProvider parent_op.conds.if_nomatch = params.if_nomatch; 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(); |