From: Cory Snyder Date: Fri, 4 Nov 2022 08:04:32 +0000 (+0000) Subject: rgw: add configurable max aio limit for multi-object delete requests X-Git-Tag: v18.1.0~717^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=63e41fb8a58717d404b436096079d4fc09f30682;p=ceph.git rgw: add configurable max aio limit for multi-object delete requests Adds the 'rgw_multi_obj_del_max_aio' configuration parameter to bound aio on multi-object delete requests. Signed-off-by: Cory Snyder --- diff --git a/src/common/options/rgw.yaml.in b/src/common/options/rgw.yaml.in index 33fe0a60794..5d7a4513009 100644 --- a/src/common/options/rgw.yaml.in +++ b/src/common/options/rgw.yaml.in @@ -175,6 +175,14 @@ options: services: - rgw with_legacy: true +- name: rgw_multi_obj_del_max_aio + type: uint + level: advanced + desc: Max number of concurrent RADOS requests per multi-object delete request. + default: 128 + services: + - rgw + with_legacy: true # whether or not the quota/gc threads should be started - name: rgw_enable_quota_threads type: bool diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 9dba03d0ed0..0554618ac72 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -6839,21 +6839,14 @@ void RGWDeleteMultiObj::write_ops_log_entry(rgw_log_entry& entry) const { entry.delete_multi_obj_meta.objects = std::move(ops_log_entries); } -void RGWDeleteMultiObj::wait_flush(optional_yield y, size_t n) +void RGWDeleteMultiObj::wait_flush(optional_yield y, std::function predicate) { if (y) { - if (ops_log_entries.size() == n) { - rgw_flush_formatter(s, s->formatter); - return; - } auto yc = y.get_yield_context(); - for (;;) { + while (!predicate()) { boost::system::error_code error; formatter_flush_cond->async_wait(yc[error]); rgw_flush_formatter(s, s->formatter); - if (ops_log_entries.size() == n) { - break; - } } } } @@ -7002,6 +6995,8 @@ void RGWDeleteMultiObj::execute(optional_yield y) RGWMultiDelDelete *multi_delete; vector::iterator iter; RGWMultiDelXMLParser parser; + uint32_t aio_count = 0; + uint32_t max_aio = s->cct->_conf->rgw_multi_obj_del_max_aio; char* buf; if (y) { formatter_flush_cond = std::make_unique(y.get_io_context()); @@ -7067,16 +7062,22 @@ void RGWDeleteMultiObj::execute(optional_yield y) iter != multi_delete->objects.end(); ++iter) { rgw_obj_key* obj_key = &*iter; - if (y) { - spawn::spawn(y.get_yield_context(), [this, &y, obj_key] (yield_context yield) { + if (y && max_aio > 1) { + wait_flush(y, [&aio_count, max_aio] { + return aio_count < max_aio; + }); + aio_count++; + spawn::spawn(y.get_yield_context(), [this, &y, &aio_count, obj_key] (yield_context yield) { handle_individual_object(obj_key, optional_yield { y.get_io_context(), yield }); + aio_count--; }); } else { handle_individual_object(obj_key, y); } } - - wait_flush(y, multi_delete->objects.size()); + wait_flush(y, [this, n=multi_delete->objects.size()] { + return n == ops_log_entries.size(); + }); /* set the return code to zero, errors at this point will be dumped to the response */ diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index e7eee104db1..692cb5c50ab 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -2046,7 +2046,7 @@ class RGWDeleteMultiObj : public RGWOp { * and saved on the req_state vs. one that is passed on the stack. * This is a no-op in the case where we're not executing as a coroutine. */ - void wait_flush(optional_yield y, size_t n); + void wait_flush(optional_yield y, std::function predicate); protected: std::vector ops_log_entries;