Skip to content

Commit 8295e3b

Browse files
committed
rgw: report copy obj progress from the frontend CR
To resolve issues with reporting progress during object copy operations, we now report progress from the frontend CR instead of from the curl thread. Reporting progress directly from the curl thread was causing issues where the final send_response() call in RGWCopyObj() would not resuming the yield after writing to client. By running the fetch_remote_obj() in a separate coroutine and reporting the progress back through the frontend coroutine, we avoid this blockage. Fixes: https://tracker.ceph.com/issues/70840 Signed-off-by: Seena Fallah <[email protected]>
1 parent 43c69a3 commit 8295e3b

File tree

3 files changed

+64
-14
lines changed

3 files changed

+64
-14
lines changed

src/rgw/driver/rados/rgw_rados.cc

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4989,19 +4989,31 @@ int RGWRados::copy_obj(RGWObjectCtx& src_obj_ctx,
49894989
ldpp_dout(dpp, 5) << "Copy object " << src_obj.bucket << ":" << src_obj.get_oid() << " => " << dest_obj.bucket << ":" << dest_obj.get_oid() << dendl;
49904990

49914991
if (remote_src || !source_zone.empty()) {
4992-
// null_yield resolves a crash when calling progress_cb(), because the beast
4993-
// frontend tried to use this same yield context to write the progress
4994-
// response to the frontend socket. call fetch_remote_obj() synchronously so
4995-
// that only one thread tries to suspend that coroutine
4996-
const req_context rctx{dpp, null_yield, nullptr};
4997-
const rgw_owner remote_user_owner(remote_user);
4998-
return fetch_remote_obj(dest_obj_ctx, &remote_user_owner, &remote_user, info, source_zone,
4999-
dest_obj, src_obj, dest_bucket_info, &src_bucket_info,
5000-
dest_placement, src_mtime, mtime, mod_ptr,
5001-
unmod_ptr, high_precision_time,
5002-
if_match, if_nomatch, attrs_mod, copy_if_newer, attrs, category,
5003-
olh_epoch, delete_at, ptag, petag, progress_cb, progress_data, rctx,
5004-
nullptr /* filter */, stat_follow_olh, stat_dest_obj, std::nullopt);
4992+
RGWCopyObj *op = static_cast<RGWCopyObj *>(progress_data);
4993+
auto& progress_tracker = op->get_progress_tracker();
4994+
4995+
int ret = 0;
4996+
boost::asio::spawn(driver->get_io_context(),
4997+
[&](boost::asio::yield_context yield) {
4998+
const req_context rctx{dpp, yield, nullptr};
4999+
const rgw_owner remote_user_owner(remote_user);
5000+
ret = fetch_remote_obj(dest_obj_ctx, &remote_user_owner, &remote_user, info, source_zone,
5001+
dest_obj, src_obj, dest_bucket_info, &src_bucket_info,
5002+
dest_placement, src_mtime, mtime, mod_ptr,
5003+
unmod_ptr, high_precision_time,
5004+
if_match, if_nomatch, attrs_mod, copy_if_newer, attrs, category,
5005+
olh_epoch, delete_at, ptag, petag, progress_cb, progress_data, rctx,
5006+
nullptr /* filter */, stat_follow_olh, stat_dest_obj, std::nullopt);
5007+
5008+
progress_tracker.done = true;
5009+
progress_tracker.cv.notify_one();
5010+
}, [] (std::exception_ptr eptr) {
5011+
if (eptr) std::rethrow_exception(eptr);
5012+
});
5013+
5014+
op->progress_cb_handler();
5015+
5016+
return ret;
50055017
}
50065018

50075019
map<string, bufferlist> src_attrs;

src/rgw/rgw_op.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5945,11 +5945,31 @@ void RGWCopyObj::progress_cb(off_t ofs)
59455945
return;
59465946
}
59475947

5948-
send_partial_response(ofs);
5948+
std::lock_guard<std::mutex> l(progress_tracker->mtx);
5949+
progress_tracker->ofs_queue.push(ofs);
5950+
progress_tracker->cv.notify_one();
59495951

59505952
last_ofs = ofs;
59515953
}
59525954

5955+
void RGWCopyObj::progress_cb_handler()
5956+
{
5957+
std::unique_lock<std::mutex> l(progress_tracker->mtx);
5958+
while(!progress_tracker->done || !progress_tracker->ofs_queue.empty()) {
5959+
progress_tracker->cv.wait(l, [&]() {
5960+
return progress_tracker->done || !progress_tracker->ofs_queue.empty();
5961+
});
5962+
5963+
while (!progress_tracker->ofs_queue.empty()) {
5964+
auto ofs = progress_tracker->ofs_queue.front();
5965+
progress_tracker->ofs_queue.pop();
5966+
l.unlock();
5967+
send_partial_response(ofs);
5968+
l.lock();
5969+
}
5970+
}
5971+
}
5972+
59535973
void RGWCopyObj::pre_exec()
59545974
{
59555975
rgw_bucket_object_pre_exec(s);

src/rgw/rgw_op.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,17 @@ class RGWCopyObj : public RGWOp {
16081608
RGWObjectRetention *obj_retention;
16091609
RGWObjectLegalHold *obj_legal_hold;
16101610

1611+
// remote copy progress helper
1612+
struct ProgressTracker {
1613+
std::mutex mtx;
1614+
std::condition_variable cv;
1615+
std::queue<off_t> ofs_queue;
1616+
std::atomic<bool> done{false};
1617+
1618+
ProgressTracker() {}
1619+
};
1620+
std::optional<ProgressTracker> progress_tracker;
1621+
16111622
int init_common();
16121623

16131624
public:
@@ -1648,6 +1659,13 @@ class RGWCopyObj : public RGWOp {
16481659
void pre_exec() override;
16491660
void execute(optional_yield y) override;
16501661
void progress_cb(off_t ofs);
1662+
void progress_cb_handler();
1663+
ProgressTracker& get_progress_tracker() {
1664+
if (!progress_tracker) {
1665+
progress_tracker.emplace();
1666+
}
1667+
return *progress_tracker;
1668+
}
16511669

16521670
virtual int check_storage_class(const rgw_placement_rule& src_placement) {
16531671
return 0;

0 commit comments

Comments
 (0)