From: Mark Kogan Date: Wed, 30 Jul 2025 12:54:19 +0000 (+0000) Subject: rgw: add rate limit for LIST & DELETE ops, hotfix syncup X-Git-Tag: testing/wip-pdonnell-testing-20260323.122957-tentacle~503 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a5a3361364d074867b0cc0cab52a48a921c72fcb;p=ceph-ci.git rgw: add rate limit for LIST & DELETE ops, hotfix syncup Add rate limiting specific to LIST ops, similar to the current rate-limiting (https://docs.ceph.com/en/latest/radosgw/admin/#rate-limit-management) Example usage: ``` ./bin/radosgw-admin ratelimit set --ratelimit-scope=user --uid= --max_list_ops=2 ./bin/radosgw-admin ratelimit set --ratelimit-scope=user --uid= --max_delete_ops=2 ./bin/radosgw-admin ratelimit enable --ratelimit-scope=user --uid= ./bin/radosgw-admin ratelimit get --ratelimit-scope=user --uid= { "user_ratelimit": { "max_read_ops": 0, "max_write_ops": 0, "max_list_ops": 2, "max_delete_ops": 2, "max_read_bytes": 0, "max_write_bytes": 0, "enabled": true } } pkill -9 radosgw ./bin/radosgw -c ./ceph.conf ... aws --endpoint-url 'http://0:8000' s3 mb s3://bkt aws --endpoint-url 'http://0:8000' s3 cp ./ceph.conf s3://bkt aws --endpoint-url http://0:8000 s3api list-objects-v2 --bucket bkt --prefix 'ceph.conf' --delimiter '/' { "Contents": [ { "Key": "ceph.conf", "LastModified": "2025-07-30T13:59:38+00:00", "ETag": "\"13d11d431ae290134562c019d9e40c0e\"", "Size": 32346, "StorageClass": "STANDARD" } ], "RequestCharged": null } aws --endpoint-url http://0:8000 s3api list-objects-v2 --bucket bkt --prefix 'ceph.conf' --delimiter '/' { "Contents": [ { "Key": "ceph.conf", "LastModified": "2025-07-30T13:59:38+00:00", "ETag": "\"13d11d431ae290134562c019d9e40c0e\"", "Size": 32346, "StorageClass": "STANDARD" } ], "RequestCharged": null } aws --endpoint-url http://0:8000 s3api list-objects-v2 --bucket bkt --prefix 'ceph.conf' --delimiter '/' argument of type 'NoneType' is not iterable tail -F ./out/radosgw.8000.log | grep beast ... beast: 0x7fffbbe09780: [30/Jul/2025:15:44:50.359 +0000] " GET /bkt?list-type=2&delimiter=%2F&prefix=ceph.conf&encoding-type=url HTTP/1.1" 200 535 - "aws-cli/2.15.31 Python/3.9.21 Linux/5.14.0-570.28.1.el9_6.x86_64 source/x86_64.rhel.9 prompt/off command/s3api.list-objects-v2" - latency=0.000999995s beast: 0x7fffbbe09780: [30/Jul/2025:15:44:53.904 +0000] " GET /bkt?list-type=2&delimiter=%2F&prefix=ceph.conf&encoding-type=url HTTP/1.1" 200 535 - "aws-cli/2.15.31 Python/3.9.21 Linux/5.14.0-570.28.1.el9_6.x86_64 source/x86_64.rhel.9 prompt/off command/s3api.list-objects-v2" - latency=0.000999995s vvv beast: 0x7fffbbe09780: [30/Jul/2025:15:44:58.192 +0000] " GET /bkt?list-type=2&delimiter=%2F&prefix=ceph.conf&encoding-type=url HTTP/1.1" 503 228 - "aws-cli/2.15.31 Python/3.9.21 Linux/5.14.0-570.28.1.el9_6.x86_64 source/x86_64.rhel.9 prompt/off command/s3api.list-objects-v2" - latency=0.000000000s beast: 0x7fffbbe09780: [30/Jul/2025:15:44:58.798 +0000] " GET /bkt?list-type=2&delimiter=%2F&prefix=ceph.conf&encoding-type=url HTTP/1.1" 503 228 - "aws-cli/2.15.31 Python/3.9.21 Linux/5.14.0-570.28.1.el9_6.x86_64 source/x86_64.rhel.9 prompt/off command/s3api.list-objects-v2" - latency=0.000999994s beast: 0x7fffbbe09780: [30/Jul/2025:15:44:59.807 +0000] " GET /bkt?list-type=2&delimiter=%2F&prefix=ceph.conf&encoding-type=url HTTP/1.1" 503 228 - "aws-cli/2.15.31 Python/3.9.21 Linux/5.14.0-570.28.1.el9_6.x86_64 source/x86_64.rhel.9 prompt/off command/s3api.list-objects-v2" - latency=0.000000000s s3cmd put ./ceph.conf s3://bkt/1 s3cmd put ./ceph.conf s3://bkt/2 s3cmd put ./ceph.conf s3://bkt/3 s3cmd rm s3://bkt/1 s3cmd rm s3://bkt/2 s3cmd rm s3://bkt/3 delete: 's3://bkt/1' delete: 's3://bkt/2' WARNING: Retrying failed request: /3 (503 (SlowDown)) WARNING: Waiting 3 sec... WARNING: Retrying failed request: /3 (503 (SlowDown)) ^^^ ``` Resolves: rhbz#2393774 Resolves: rhbz#2393477 Resolves: rhbz#2395642 Resolves: rhbz#2391529 Resolves: rhbz#2389280 Signed-off-by: Mark Kogan Update PendingReleaseNotes Co-authored-by: Yuval Lifshitz Signed-off-by: Mark Kogan <31659604+mkogan1@users.noreply.github.com> --- diff --git a/doc/radosgw/admin.rst b/doc/radosgw/admin.rst index a2307344eb7..79191b7cad5 100644 --- a/doc/radosgw/admin.rst +++ b/doc/radosgw/admin.rst @@ -18,7 +18,7 @@ to `Accounts`_ for ease of management. There are two types of user: -- **User:** The term "user" refers to user of the S3 interface. +- **User:** The term "user" refers to user of the S3 interface. - **Subuser:** The term "subuser" refers to a user of the Swift interface. A subuser is associated with a user. @@ -631,6 +631,14 @@ The accumulation interval is configured by the :confval:`rgw_ratelimit_interval` The default value is 60 seconds. (Note: S3 Multi-Object Delete operation are currently not supported by rate limiting) +The configured limits should be divided by the number of active object gateways. For example, +if "user A" is to be be limited to 10 ops per minute and there are two object gateways in the cluster, +then the limit on "user A" should be 5 (10 ops per minute / 2 RGWs). +If the requests are not balanced between RGWs, the rate limit might be underutilized. +For example: if the ops limit is 5 and there are two RGWs, +but the Load Balancer sends load to only one of those RGWs, +the effective limit is 5 ops, because this limit is enforced per RGW. + Read Requests and Write Requests -------------------------------- Operations that use the ``GET`` method or the ``HEAD`` method in their REST diff --git a/src/common/options/rgw.yaml.in b/src/common/options/rgw.yaml.in index 8adefd71384..204c075ee09 100644 --- a/src/common/options/rgw.yaml.in +++ b/src/common/options/rgw.yaml.in @@ -4438,6 +4438,7 @@ options: Requests that exceed the configured rate limits within this time window will be rejected. The default is a 60 second token bucket. default: 60 + min: 1 services: - rgw flags: diff --git a/src/rgw/radosgw-admin/radosgw-admin.cc b/src/rgw/radosgw-admin/radosgw-admin.cc index 029c8a48240..c1aeb7bf3df 100644 --- a/src/rgw/radosgw-admin/radosgw-admin.cc +++ b/src/rgw/radosgw-admin/radosgw-admin.cc @@ -6774,7 +6774,8 @@ int main(int argc, const char **argv) OPT::ROLE_CREATE, OPT::ROLE_DELETE, OPT::ROLE_POLICY_PUT, OPT::ROLE_POLICY_DELETE, OPT::ROLE_POLICY_ATTACH, OPT::ROLE_POLICY_DETACH, - OPT::USER_POLICY_ATTACH, OPT::USER_POLICY_DETACH}; + OPT::USER_POLICY_ATTACH, OPT::USER_POLICY_DETACH, + OPT::RATELIMIT_SET, OPT::RATELIMIT_ENABLE, OPT::RATELIMIT_DISABLE}; bool print_warning_message = (non_master_ops_list.find(opt_cmd) != non_master_ops_list.end() && non_master_cmd); diff --git a/src/rgw/rgw_process.cc b/src/rgw/rgw_process.cc index e70b68c0794..101ed2af681 100644 --- a/src/rgw/rgw_process.cc +++ b/src/rgw/rgw_process.cc @@ -112,6 +112,14 @@ bool rate_limit(rgw::sal::Driver* driver, req_state* s) { s->ratelimit_bucket_marker = bucketfind; const char *method = s->info.method; + bool is_sts_user = (s->auth.identity && s->auth.identity->get_identity_type() == TYPE_ROLE); + if (is_sts_user) { + ldpp_dout(s, 21) << "STS user detected: uid=" << std::quoted(s->user->get_id().to_str()) << dendl; + auto op_ret = s->user->read_attrs(s, s->yield); + if (op_ret < 0) { + ldpp_dout(s, 0) << "checking rate_limit: uid=" << std::quoted(s->user->get_id().to_str()) << " failed to read user attrs" << dendl; + } + } auto iter = s->user->get_attrs().find(RGW_ATTR_RATELIMIT); if(iter != s->user->get_attrs().end()) { try { @@ -126,6 +134,8 @@ bool rate_limit(rgw::sal::Driver* driver, req_state* s) { ldpp_dout(s, 0) << "ERROR: failed to decode rate limit" << dendl; return -EIO; } + } else { + ldpp_dout(s, 21) << "checking rate_limit: uid=" << std::quoted(s->user->get_id().to_str()) << " does not have a rate limit attribute" << dendl; } if (s->user->get_id().id == RGW_USER_ANON_ID && global_anon.enabled) { *user_ratelimit = global_anon; diff --git a/src/rgw/rgw_ratelimit.h b/src/rgw/rgw_ratelimit.h index e1b877378ff..4207f1fef8c 100644 --- a/src/rgw/rgw_ratelimit.h +++ b/src/rgw/rgw_ratelimit.h @@ -80,7 +80,7 @@ class RateLimiterEntry { del.ops -= fixed_point_rgw_ratelimit; return false; } - bool should_rate_limit_write(int64_t ops_limit, int64_t bw_limit) + bool should_rate_limit_write(int64_t ops_limit, int64_t bw_limit) { //check if tenants did not reach their bw or ops limits and that the limits are not 0 (which is unlimited) if(((write_ops() - 1 < 0) && (ops_limit > 0)) || @@ -193,7 +193,7 @@ class RateLimiterEntry { } }; -class RateLimiter { +class RateLimiter : public DoutPrefix { static constexpr size_t map_size = 2000000; // will create it with the closest upper prime number std::shared_mutex insert_lock; @@ -256,14 +256,15 @@ class RateLimiter { RateLimiter(RateLimiter&&) = delete; RateLimiter& operator =(RateLimiter&&) = delete; RateLimiter() = delete; - RateLimiter(std::atomic_bool& replacing, std::condition_variable& cv) - : replacing(replacing), cv(cv) + RateLimiter(CephContext* cct, std::atomic_bool& replacing, std::condition_variable& cv) + : DoutPrefix(cct, ceph_subsys_rgw, "rate limiter: "), replacing(replacing), cv(cv) { // prevents rehash, so no iterators invalidation ratelimit_entries.max_load_factor(1000); }; bool should_rate_limit(const char *method, const std::string& key, ceph::coarse_real_time curr_timestamp, const RGWRateLimitInfo* ratelimit_info, const std::string& resource) { + ldpp_dout(this, 21) << "checking should_rate_limit: key=" << std::quoted(key) << " enabled=" << ratelimit_info->enabled << dendl; if (key.empty() || key.length() == 1 || !ratelimit_info->enabled) { return false; @@ -345,8 +346,8 @@ class ActiveRateLimiter : public DoutPrefix { ActiveRateLimiter(CephContext* cct) : DoutPrefix(cct, ceph_subsys_rgw, "rate limiter: ") { - ratelimit[0] = std::make_shared(replacing, cv); - ratelimit[1] = std::make_shared(replacing, cv); + ratelimit[0] = std::make_shared(cct, replacing, cv); + ratelimit[1] = std::make_shared(cct, replacing, cv); } ~ActiveRateLimiter() { ldpp_dout(this, 20) << "stopping ratelimit_gc thread" << dendl; diff --git a/src/rgw/rgw_rest_ratelimit.cc b/src/rgw/rgw_rest_ratelimit.cc index 60ae5dd3d20..26a0179721d 100644 --- a/src/rgw/rgw_rest_ratelimit.cc +++ b/src/rgw/rgw_rest_ratelimit.cc @@ -1,6 +1,11 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab ft=cpp #include "rgw_rest_ratelimit.h" +#include "rgw_sal.h" +#include "rgw_sal_config.h" +#include "rgw_process_env.h" +#include "rgw_op.h" + class RGWOp_Ratelimit_Info : public RGWRESTOp { int check_caps(const RGWUserCaps& caps) override { return caps.check_cap("ratelimit", RGW_CAP_READ); @@ -247,6 +252,15 @@ void RGWOp_Ratelimit_Set::execute(optional_yield y) } } RESTArgs::get_bool(s, "global", false, &global, nullptr); + + // forward to master zonegroup + op_ret = rgw_forward_request_to_master(this, *s->penv.site, s->user->get_id(), + nullptr, nullptr, s->info, s->err, y); + if (op_ret < 0) { + ldpp_dout(this, 0) << "ERROR: forward_request_to_master returned ret=" << op_ret << dendl; + return; + } + set_ratelimit_info(have_max_read_ops, max_read_ops, have_max_write_ops, max_write_ops, have_max_read_bytes, max_read_bytes, have_max_write_bytes, max_write_bytes, have_max_list_ops, max_list_ops, have_max_delete_ops, max_delete_ops, diff --git a/src/test/rgw/test_rgw_ratelimit.cc b/src/test/rgw/test_rgw_ratelimit.cc index c2ffa92b5ce..fd305fdfad0 100644 --- a/src/test/rgw/test_rgw_ratelimit.cc +++ b/src/test/rgw/test_rgw_ratelimit.cc @@ -13,7 +13,7 @@ TEST(RGWRateLimit, op_limit_not_enabled) // info.enabled = false, so no limit std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; auto time = ceph::coarse_real_clock::now(); std::string key = "uuser123"; @@ -25,7 +25,7 @@ TEST(RGWRateLimit, reject_op_over_limit) // check that request is being rejected because there are not enough tokens std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_read_ops = 1; @@ -41,7 +41,7 @@ TEST(RGWRateLimit, accept_op_after_giveback) // check that giveback is working fine std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_read_ops = 1; @@ -58,7 +58,7 @@ TEST(RGWRateLimit, accept_op_after_refill) // check that tokens are being filled properly std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_read_ops = 1; @@ -74,7 +74,7 @@ TEST(RGWRateLimit, reject_bw_over_limit) // check that a newer request is rejected if there is no enough tokens (bw) std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_read_bytes = 1; @@ -91,7 +91,7 @@ TEST(RGWRateLimit, accept_bw) // check that when there are enough tokens (bw) the request is still being served std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_read_bytes = 2; @@ -108,7 +108,7 @@ TEST(RGWRateLimit, check_bw_debt_at_max_120secs) // check that the bandwidth debt is not larger than 120 seconds std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_read_bytes = 2; @@ -125,7 +125,7 @@ TEST(RGWRateLimit, check_that_bw_limit_not_affect_ops) // check that high read bytes limit, does not affect ops limit std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_read_ops = 1; @@ -143,7 +143,7 @@ TEST(RGWRateLimit, read_limit_does_not_affect_writes) // read limit does not affect writes std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_read_ops = 1; @@ -161,7 +161,7 @@ TEST(RGWRateLimit, write_limit_does_not_affect_reads) // write limit does not affect reads std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_write_ops = 1; @@ -180,7 +180,7 @@ TEST(RGWRateLimit, allow_unlimited_access) // 0 values in RGWRateLimitInfo should allow unlimited access std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; auto time = ceph::coarse_real_clock::now(); @@ -388,7 +388,7 @@ TEST(RGWRateLimit, reject_list_op_over_limit) // check that LIST op is being rejected because there are not enough tokens std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -405,7 +405,7 @@ TEST(RGWRateLimit, accept_list_op_after_giveback) // check that giveback is working for LIST ops std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -423,7 +423,7 @@ TEST(RGWRateLimit, accept_list_op_after_refill) // check that tokens are being filled properly for LIST ops std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -440,7 +440,7 @@ TEST(RGWRateLimit, list_limit_does_not_affect_reads) // list limit does not affect reads std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -458,7 +458,7 @@ TEST(RGWRateLimit, read_limit_does_not_affect_lists) // read limit does not affect lists std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -476,7 +476,7 @@ TEST(RGWRateLimit, list_limit_does_not_affect_writes) // list limit does not affect writes std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -494,7 +494,7 @@ TEST(RGWRateLimit, write_limit_does_not_affect_lists) // write limit does not affect lists std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -512,7 +512,7 @@ TEST(RGWRateLimit, list_limit_does_not_affect_deletes) // list limit does not affect deletes std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -530,7 +530,7 @@ TEST(RGWRateLimit, delete_limit_does_not_affect_lists) // delete limit does not affect lists std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -549,7 +549,7 @@ TEST(RGWRateLimit, reject_delimiter_op_over_limit) // check that DELIMITER op is being rejected because there are not enough tokens std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -566,7 +566,7 @@ TEST(RGWRateLimit, accept_delimiter_op_after_giveback) // check that giveback is working for DELIMITER ops std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -584,7 +584,7 @@ TEST(RGWRateLimit, accept_delimiter_op_after_refill) // check that tokens are being filled properly for DELIMITER ops std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -602,7 +602,7 @@ TEST(RGWRateLimit, reject_prefix_op_over_limit) // check that PREFIX op is being rejected because there are not enough tokens std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -619,7 +619,7 @@ TEST(RGWRateLimit, accept_prefix_op_after_giveback) // check that giveback is working for PREFIX ops std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -637,7 +637,7 @@ TEST(RGWRateLimit, accept_prefix_op_after_refill) // check that tokens are being filled properly for PREFIX ops std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_list_ops = 1; @@ -789,7 +789,7 @@ TEST(RGWRateLimit, reject_delete_op_over_limit) // check that DELETE op is being rejected because there are not enough tokens std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_delete_ops = 1; @@ -806,7 +806,7 @@ TEST(RGWRateLimit, accept_delete_op_after_giveback) // check that giveback is working for DELETE ops std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_delete_ops = 1; @@ -824,7 +824,7 @@ TEST(RGWRateLimit, accept_delete_op_after_refill) // check that tokens are being filled properly for DELETE ops std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_delete_ops = 1; @@ -841,7 +841,7 @@ TEST(RGWRateLimit, delete_limit_does_not_affect_reads) // delete limit does not affect reads std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_delete_ops = 1; @@ -859,7 +859,7 @@ TEST(RGWRateLimit, read_limit_does_not_affect_deletes) // read limit does not affect deletes std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_delete_ops = 1; @@ -877,7 +877,7 @@ TEST(RGWRateLimit, write_limit_does_not_affect_deletes) // write limit does not affect deletes std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_delete_ops = 1; @@ -895,7 +895,7 @@ TEST(RGWRateLimit, delete_limit_does_not_affect_writes) // delete limit does not affect writes std::atomic_bool replacing; std::condition_variable cv; - RateLimiter ratelimit(replacing, cv); + RateLimiter ratelimit(g_ceph_context, replacing, cv); RGWRateLimitInfo info; info.enabled = true; info.max_delete_ops = 1;