summaryrefslogtreecommitdiffstats
path: root/src/rgw/driver/rados
diff options
context:
space:
mode:
authorCasey Bodley <cbodley@redhat.com>2023-02-17 14:47:05 +0100
committerCasey Bodley <cbodley@redhat.com>2023-11-21 17:09:23 +0100
commit01d8b4c38bdf98c2c2f8777200a1ba45a954a05d (patch)
tree063404a10ceb6b592255a578b9ca296a2344db6d /src/rgw/driver/rados
parentrgw/rados: add obj_find_part() to RGWObjManifest (diff)
downloadceph-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.cc112
-rw-r--r--src/rgw/driver/rados/rgw_rados.h2
-rw-r--r--src/rgw/driver/rados/rgw_sal_rados.cc2
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();