From: Soumya Koduri Date: Sat, 5 Nov 2022 16:53:53 +0000 (+0530) Subject: rgw/cloud-transition: Fix issues with MCG endpoint X-Git-Tag: v17.2.6~211^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8009d977254168992ee5c6f41358e686bcc9fe49;p=ceph.git rgw/cloud-transition: Fix issues with MCG endpoint Few s3 endpoints (like Noobaa MCG or AWS) may return BucketAlreadyOwned or BucketAlreadyExists error if the target path (configured for cloud transition) already exists. Do not fail transition in those cases. Also fixed below issues - * with racing lc threads, when one lc thread is trying to check and create the target bucket, others may go ahead with the object transition assuming target path exists. * initialize few fields to avoid setting wrong content_len during transition Signed-off-by: Soumya Koduri --- diff --git a/src/rgw/rgw_lc.cc b/src/rgw/rgw_lc.cc index 31822d862c60..6dad16efc808 100644 --- a/src/rgw/rgw_lc.cc +++ b/src/rgw/rgw_lc.cc @@ -1454,25 +1454,16 @@ public: tier_ctx.multipart_sync_threshold = oc.tier.t.s3.multipart_sync_threshold; tier_ctx.storage_class = oc.tier.storage_class; - // check if target_path is already created std::set& cloud_targets = oc.env.worker->get_cloud_targets(); - std::pair::iterator, bool> it; - - it = cloud_targets.insert(bucket_name); - tier_ctx.target_bucket_created = !(it.second); ldpp_dout(oc.dpp, 0) << "Transitioning object(" << oc.o.key << ") to the cloud endpoint(" << endpoint << ")" << dendl; /* Transition object to cloud end point */ - int ret = rgw_cloud_tier_transfer_object(tier_ctx); + int ret = rgw_cloud_tier_transfer_object(tier_ctx, cloud_targets); if (ret < 0) { ldpp_dout(oc.dpp, 0) << "ERROR: failed to transfer object(" << oc.o.key << ") to the cloud endpoint(" << endpoint << ") ret=" << ret << dendl; return ret; - - if (!tier_ctx.target_bucket_created) { - cloud_targets.erase(it.first); - } } if (delete_object) { diff --git a/src/rgw/rgw_lc_tier.cc b/src/rgw/rgw_lc_tier.cc index 704b7dee2e27..080b99737acb 100644 --- a/src/rgw/rgw_lc_tier.cc +++ b/src/rgw/rgw_lc_tier.cc @@ -326,17 +326,17 @@ class RGWLCStreamRead rgw::sal::Object *obj; const real_time &mtime; - bool multipart; - uint64_t m_part_size; - off_t m_part_off; - off_t m_part_end; + bool multipart{false}; + uint64_t m_part_size{0}; + off_t m_part_off{0}; + off_t m_part_end{0}; std::unique_ptr read_op; - off_t ofs; - off_t end; + off_t ofs{0}; + off_t end{0}; rgw_rest_obj rest_obj; - int retcode; + int retcode{0}; public: RGWLCStreamRead(CephContext *_cct, const DoutPrefixProvider *_dpp, @@ -1246,8 +1246,7 @@ static int cloud_tier_create_bucket(RGWLCCloudTierCtx& tier_ctx) { out_bl, &bl, nullptr, null_yield); if (ret < 0 ) { - ldpp_dout(tier_ctx.dpp, 0) << "ERROR: failed to create target bucket: " << tier_ctx.target_bucket_name << ", ret:" << ret << dendl; - return ret; + ldpp_dout(tier_ctx.dpp, 0) << "create target bucket : " << tier_ctx.target_bucket_name << " returned ret:" << ret << dendl; } if (out_bl.length() > 0) { RGWXMLDecoder::XMLParser parser; @@ -1270,7 +1269,7 @@ static int cloud_tier_create_bucket(RGWLCCloudTierCtx& tier_ctx) { return -EIO; } - if (result.code != "BucketAlreadyOwnedByYou") { + if (result.code != "BucketAlreadyOwnedByYou" && result.code != "BucketAlreadyExists") { ldpp_dout(tier_ctx.dpp, 0) << "ERROR: Creating target bucket failed with error: " << result.code << dendl; return -EIO; } @@ -1279,9 +1278,15 @@ static int cloud_tier_create_bucket(RGWLCCloudTierCtx& tier_ctx) { return 0; } -int rgw_cloud_tier_transfer_object(RGWLCCloudTierCtx& tier_ctx) { +int rgw_cloud_tier_transfer_object(RGWLCCloudTierCtx& tier_ctx, std::set& cloud_targets) { int ret = 0; + // check if target_path is already created + std::set::iterator it; + + it = cloud_targets.find(tier_ctx.target_bucket_name); + tier_ctx.target_bucket_created = (it != cloud_targets.end()); + /* If run first time attempt to create the target bucket */ if (!tier_ctx.target_bucket_created) { ret = cloud_tier_create_bucket(tier_ctx); @@ -1291,6 +1296,7 @@ int rgw_cloud_tier_transfer_object(RGWLCCloudTierCtx& tier_ctx) { return ret; } tier_ctx.target_bucket_created = true; + cloud_targets.insert(tier_ctx.target_bucket_name); } /* Since multiple zones may try to transition the same object to the cloud, diff --git a/src/rgw/rgw_lc_tier.h b/src/rgw/rgw_lc_tier.h index 86df479e8280..7f38f1e02b83 100644 --- a/src/rgw/rgw_lc_tier.h +++ b/src/rgw/rgw_lc_tier.h @@ -50,6 +50,6 @@ struct RGWLCCloudTierCtx { }; /* Transition object to cloud endpoint */ -int rgw_cloud_tier_transfer_object(RGWLCCloudTierCtx& tier_ctx); +int rgw_cloud_tier_transfer_object(RGWLCCloudTierCtx& tier_ctx, std::set& cloud_targets); #endif diff --git a/src/rgw/rgw_rest_conn.cc b/src/rgw/rgw_rest_conn.cc index afcc86db11cd..d15c97757e64 100644 --- a/src/rgw/rgw_rest_conn.cc +++ b/src/rgw/rgw_rest_conn.cc @@ -409,7 +409,12 @@ int RGWRESTConn::send_resource(const DoutPrefixProvider *dpp, const std::string& return ret; } - return req.complete_request(y); + ret = req.complete_request(y); + if (ret < 0) { + ldpp_dout(dpp, 5) << __func__ << ": complete_request() resource=" << resource << " returned ret=" << ret << dendl; + } + + return ret; } RGWRESTReadResource::RGWRESTReadResource(RGWRESTConn *_conn,