From 17283ce7b6035775f125585d1b228226942daf4b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 25 Aug 2021 01:28:47 +0900 Subject: [PATCH 1/2] core/cgroup: set bfq.weight first, and fixes blkio.weight value Fixes issues introduced by 29eb0eefd14afc9a2424781a28b376db47c3c570. This also fixes the value sets to blkio.weight, that is, "default" is dropped. Moreover, This also changes the logic for mapping weight -> bfq.weight, to always matches the min, max, and default values. Fixes #20519 and #21187. --- src/core/cgroup.c | 57 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 52bdf54b5f..7d4d565343 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -38,6 +38,12 @@ #define CGROUP_CPU_QUOTA_DEFAULT_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC) +/* Special values for the bfq.weight attribute */ +#define CGROUP_BFQ_WEIGHT_INVALID UINT64_MAX +#define CGROUP_BFQ_WEIGHT_MIN UINT64_C(1) +#define CGROUP_BFQ_WEIGHT_MAX UINT64_C(1000) +#define CGROUP_BFQ_WEIGHT_DEFAULT UINT64_C(100) + /* Returns the log level to use when cgroup attribute writes fail. When an attribute is missing or we have access * problems we downgrade to LOG_DEBUG. This is supposed to be nice to container managers and kernels which want to mask * out specific attributes from us. */ @@ -1200,21 +1206,48 @@ static int cgroup_apply_devices(Unit *u) { return r; } -static void set_io_weight(Unit *u, const char *controller, uint64_t weight) { - char buf[8+DECIMAL_STR_MAX(uint64_t)+1]; - const char *p; +static void set_io_weight(Unit *u, uint64_t weight) { + char buf[STRLEN("default \n")+DECIMAL_STR_MAX(uint64_t)]; + uint64_t bfq_weight; - p = strjoina(controller, ".weight"); - xsprintf(buf, "default %" PRIu64 "\n", weight); - (void) set_attribute_and_warn(u, controller, p, buf); + assert(u); /* FIXME: drop this when distro kernels properly support BFQ through "io.weight" * See also: https://github.com/systemd/systemd/pull/13335 and * https://github.com/torvalds/linux/commit/65752aef0a407e1ef17ec78a7fc31ba4e0b360f9. - * The range is 1..1000 apparently. */ - p = strjoina(controller, ".bfq.weight"); - xsprintf(buf, "%" PRIu64 "\n", (weight + 9) / 10); - (void) set_attribute_and_warn(u, controller, p, buf); + * The range is 1..1000 apparently, and the default is 100. */ + if (weight <= CGROUP_WEIGHT_DEFAULT) + bfq_weight = CGROUP_BFQ_WEIGHT_DEFAULT - (CGROUP_WEIGHT_DEFAULT - weight) * (CGROUP_BFQ_WEIGHT_DEFAULT - CGROUP_BFQ_WEIGHT_MIN) / (CGROUP_WEIGHT_DEFAULT - CGROUP_WEIGHT_MIN); + else + bfq_weight = CGROUP_BFQ_WEIGHT_DEFAULT + (weight - CGROUP_WEIGHT_DEFAULT) * (CGROUP_BFQ_WEIGHT_MAX - CGROUP_BFQ_WEIGHT_DEFAULT) / (CGROUP_WEIGHT_MAX - CGROUP_WEIGHT_DEFAULT); + + xsprintf(buf, "%" PRIu64 "\n", bfq_weight); + (void) set_attribute_and_warn(u, "io", "io.bfq.weight", buf); + + xsprintf(buf, "default %" PRIu64 "\n", weight); + (void) set_attribute_and_warn(u, "io", "io.weight", buf); +} + +static void set_blkio_weight(Unit *u, uint64_t weight) { + char buf[STRLEN("\n")+DECIMAL_STR_MAX(uint64_t)]; + uint64_t bfq_weight; + + assert(u); + + /* FIXME: drop this when distro kernels properly support BFQ through "io.weight" + * See also: https://github.com/systemd/systemd/pull/13335 and + * https://github.com/torvalds/linux/commit/65752aef0a407e1ef17ec78a7fc31ba4e0b360f9. + * The range is 1..1000 apparently, and the default is 100. */ + if (weight <= CGROUP_BLKIO_WEIGHT_DEFAULT) + bfq_weight = CGROUP_BFQ_WEIGHT_DEFAULT - (CGROUP_BLKIO_WEIGHT_DEFAULT - weight) * (CGROUP_BFQ_WEIGHT_DEFAULT - CGROUP_BFQ_WEIGHT_MIN) / (CGROUP_BLKIO_WEIGHT_DEFAULT - CGROUP_BLKIO_WEIGHT_MIN); + else + bfq_weight = CGROUP_BFQ_WEIGHT_DEFAULT + (weight - CGROUP_BLKIO_WEIGHT_DEFAULT) * (CGROUP_BFQ_WEIGHT_MAX - CGROUP_BFQ_WEIGHT_DEFAULT) / (CGROUP_BLKIO_WEIGHT_MAX - CGROUP_BLKIO_WEIGHT_DEFAULT); + + xsprintf(buf, "%" PRIu64 "\n", bfq_weight); + (void) set_attribute_and_warn(u, "blkio", "blkio.bfq.weight", buf); + + xsprintf(buf, "%" PRIu64 "\n", weight); + (void) set_attribute_and_warn(u, "blkio", "blkio.weight", buf); } static void cgroup_apply_bpf_foreign_program(Unit *u) { @@ -1328,7 +1361,7 @@ static void cgroup_context_apply( } else weight = CGROUP_WEIGHT_DEFAULT; - set_io_weight(u, "io", weight); + set_io_weight(u, weight); if (has_io) { CGroupIODeviceLatency *latency; @@ -1398,7 +1431,7 @@ static void cgroup_context_apply( else weight = CGROUP_BLKIO_WEIGHT_DEFAULT; - set_io_weight(u, "blkio", weight); + set_blkio_weight(u, weight); if (has_io) { CGroupIODeviceWeight *w; From 311822ac28c99e2fb0e25286bdb72c9188314a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 10 Nov 2021 11:37:15 +0100 Subject: [PATCH 2/2] core/cgroup: use helper macro for bfq conversion As suggested in https://github.com/systemd/systemd/pull/20522#discussion_r696699984. --- src/core/cgroup.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 7d4d565343..fa397ba849 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1206,9 +1206,21 @@ static int cgroup_apply_devices(Unit *u) { return r; } +/* Convert the normal io.weight value to io.bfq.weight */ +#define BFQ_WEIGHT(weight) \ + (weight <= CGROUP_WEIGHT_DEFAULT ? \ + CGROUP_BFQ_WEIGHT_DEFAULT - (CGROUP_WEIGHT_DEFAULT - weight) * (CGROUP_BFQ_WEIGHT_DEFAULT - CGROUP_BFQ_WEIGHT_MIN) / (CGROUP_WEIGHT_DEFAULT - CGROUP_WEIGHT_MIN) : \ + CGROUP_BFQ_WEIGHT_DEFAULT + (weight - CGROUP_WEIGHT_DEFAULT) * (CGROUP_BFQ_WEIGHT_MAX - CGROUP_BFQ_WEIGHT_DEFAULT) / (CGROUP_WEIGHT_MAX - CGROUP_WEIGHT_DEFAULT)) + +assert_cc(BFQ_WEIGHT(1) == 1); +assert_cc(BFQ_WEIGHT(50) == 50); +assert_cc(BFQ_WEIGHT(100) == 100); +assert_cc(BFQ_WEIGHT(500) == 136); +assert_cc(BFQ_WEIGHT(5000) == 545); +assert_cc(BFQ_WEIGHT(10000) == 1000); + static void set_io_weight(Unit *u, uint64_t weight) { char buf[STRLEN("default \n")+DECIMAL_STR_MAX(uint64_t)]; - uint64_t bfq_weight; assert(u); @@ -1216,12 +1228,7 @@ static void set_io_weight(Unit *u, uint64_t weight) { * See also: https://github.com/systemd/systemd/pull/13335 and * https://github.com/torvalds/linux/commit/65752aef0a407e1ef17ec78a7fc31ba4e0b360f9. * The range is 1..1000 apparently, and the default is 100. */ - if (weight <= CGROUP_WEIGHT_DEFAULT) - bfq_weight = CGROUP_BFQ_WEIGHT_DEFAULT - (CGROUP_WEIGHT_DEFAULT - weight) * (CGROUP_BFQ_WEIGHT_DEFAULT - CGROUP_BFQ_WEIGHT_MIN) / (CGROUP_WEIGHT_DEFAULT - CGROUP_WEIGHT_MIN); - else - bfq_weight = CGROUP_BFQ_WEIGHT_DEFAULT + (weight - CGROUP_WEIGHT_DEFAULT) * (CGROUP_BFQ_WEIGHT_MAX - CGROUP_BFQ_WEIGHT_DEFAULT) / (CGROUP_WEIGHT_MAX - CGROUP_WEIGHT_DEFAULT); - - xsprintf(buf, "%" PRIu64 "\n", bfq_weight); + xsprintf(buf, "%" PRIu64 "\n", BFQ_WEIGHT(weight)); (void) set_attribute_and_warn(u, "io", "io.bfq.weight", buf); xsprintf(buf, "default %" PRIu64 "\n", weight); @@ -1230,20 +1237,11 @@ static void set_io_weight(Unit *u, uint64_t weight) { static void set_blkio_weight(Unit *u, uint64_t weight) { char buf[STRLEN("\n")+DECIMAL_STR_MAX(uint64_t)]; - uint64_t bfq_weight; assert(u); - /* FIXME: drop this when distro kernels properly support BFQ through "io.weight" - * See also: https://github.com/systemd/systemd/pull/13335 and - * https://github.com/torvalds/linux/commit/65752aef0a407e1ef17ec78a7fc31ba4e0b360f9. - * The range is 1..1000 apparently, and the default is 100. */ - if (weight <= CGROUP_BLKIO_WEIGHT_DEFAULT) - bfq_weight = CGROUP_BFQ_WEIGHT_DEFAULT - (CGROUP_BLKIO_WEIGHT_DEFAULT - weight) * (CGROUP_BFQ_WEIGHT_DEFAULT - CGROUP_BFQ_WEIGHT_MIN) / (CGROUP_BLKIO_WEIGHT_DEFAULT - CGROUP_BLKIO_WEIGHT_MIN); - else - bfq_weight = CGROUP_BFQ_WEIGHT_DEFAULT + (weight - CGROUP_BLKIO_WEIGHT_DEFAULT) * (CGROUP_BFQ_WEIGHT_MAX - CGROUP_BFQ_WEIGHT_DEFAULT) / (CGROUP_BLKIO_WEIGHT_MAX - CGROUP_BLKIO_WEIGHT_DEFAULT); - - xsprintf(buf, "%" PRIu64 "\n", bfq_weight); + /* FIXME: see comment in set_io_weight(). */ + xsprintf(buf, "%" PRIu64 "\n", BFQ_WEIGHT(weight)); (void) set_attribute_and_warn(u, "blkio", "blkio.bfq.weight", buf); xsprintf(buf, "%" PRIu64 "\n", weight);