Skip to content

Commit 60ba07a

Browse files
committed
rgw: RGWDeleteMultiObj spawns a coroutine on null_yield
if called with null_yield, RGWDeleteMultiObj::execute() creates an io_context and spawns a coroutine to run on it. this ensures that spawn_throttle always gets a valid yield context Signed-off-by: Casey Bodley <[email protected]>
1 parent 7850229 commit 60ba07a

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

src/rgw/rgw_op.cc

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7642,6 +7642,22 @@ void RGWDeleteMultiObj::handle_individual_object(const RGWMultiDelObject& object
76427642
send_partial_response(o, del_op->result.delete_marker, del_op->result.version_id, op_ret);
76437643
}
76447644

7645+
void RGWDeleteMultiObj::handle_objects(const std::vector<RGWMultiDelObject>& objects,
7646+
uint32_t max_aio,
7647+
boost::asio::yield_context yield)
7648+
{
7649+
auto group = ceph::async::spawn_throttle{yield, max_aio};
7650+
7651+
for (const auto& object : objects) {
7652+
group.spawn([this, &object] (boost::asio::yield_context yield) {
7653+
handle_individual_object(object, yield);
7654+
});
7655+
7656+
rgw_flush_formatter(s, s->formatter);
7657+
}
7658+
group.wait();
7659+
}
7660+
76457661
void RGWDeleteMultiObj::execute(optional_yield y)
76467662
{
76477663
const char* buf = data.c_str();
@@ -7710,16 +7726,25 @@ void RGWDeleteMultiObj::execute(optional_yield y)
77107726

77117727
// process up to max_aio object deletes in parallel
77127728
const uint32_t max_aio = std::max<uint32_t>(1, s->cct->_conf->rgw_multi_obj_del_max_aio);
7713-
auto group = ceph::async::spawn_throttle{y, max_aio};
77147729

7715-
for (const auto& object : multi_delete->objects) {
7716-
group.spawn([this, &object] (boost::asio::yield_context yield) {
7717-
handle_individual_object(object, yield);
7718-
});
7719-
7720-
rgw_flush_formatter(s, s->formatter);
7730+
// if we're not already running in a coroutine, spawn one
7731+
if (!y) {
7732+
auto& objects = multi_delete->objects;
7733+
7734+
boost::asio::io_context context;
7735+
boost::asio::spawn(context,
7736+
[this, &objects, max_aio] (boost::asio::yield_context yield) {
7737+
handle_objects(objects, max_aio, yield);
7738+
},
7739+
[] (std::exception_ptr eptr) {
7740+
if (eptr) std::rethrow_exception(eptr);
7741+
});
7742+
context.run();
7743+
} else {
7744+
// use the existing coroutine's yield context
7745+
handle_objects(multi_delete->objects, max_aio,
7746+
y.get_yield_context());
77217747
}
7722-
group.wait();
77237748

77247749
/* set the return code to zero, errors at this point will be
77257750
dumped to the response */

src/rgw/rgw_op.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,6 +2178,9 @@ class RGWDeleteMultiObj : public RGWOp {
21782178
*/
21792179
void handle_individual_object(const RGWMultiDelObject& object, optional_yield y);
21802180

2181+
void handle_objects(const std::vector<RGWMultiDelObject>& objects,
2182+
uint32_t max_aio, boost::asio::yield_context yield);
2183+
21812184
protected:
21822185
std::vector<delete_multi_obj_entry> ops_log_entries;
21832186
bufferlist data;

0 commit comments

Comments
 (0)