]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/cgroup: Apply IODeviceWeight= through BFQ attributes as well
authorMichal Koutný <mkoutny@suse.com>
Fri, 10 Dec 2021 17:41:09 +0000 (18:41 +0100)
committerMichal Koutný <mkoutny@suse.com>
Wed, 23 Mar 2022 18:20:51 +0000 (19:20 +0100)
There are two possible IO control mechanisms (io.cost and BFQ) that
expose separate weights APIs. In systemd units we configure only a
single device weight value so we need to write it to both attribute
files.
This patch extends to devices what is already done for default cgroup IO
weight in commit 2dbc45aea747 ("cgroup: Also set io.bfq.weight"). This
is possible with kernels >= v5.4 with commit 795fe54c2a82 ("bfq: Add
per-device weight"). A warning is logged if the write fails on older kernels.

Since per-device weight of a particular device cannot use both io.cost
policy and BFQ scheduler, at least one warning is always expected with
this approach (the method that is unconfigured).

src/core/cgroup.c

index 42055e4e418ae701b5dbc0dfa60a2eccab7235b7..35edeac2adf2db09c9ebf58b8840dca843dec9b4 100644 (file)
@@ -1063,8 +1063,8 @@ static uint64_t cgroup_weight_io_to_blkio(uint64_t io_weight) {
                      CGROUP_BLKIO_WEIGHT_MIN, CGROUP_BLKIO_WEIGHT_MAX);
 }
 
-static void set_bfq_weight(Unit *u, const char *controller, uint64_t io_weight) {
-        char buf[DECIMAL_STR_MAX(uint64_t)+STRLEN("\n")];
+static void set_bfq_weight(Unit *u, const char *controller, dev_t dev, uint64_t io_weight) {
+        char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+STRLEN("\n")];
         const char *p;
         uint64_t bfq_weight;
 
@@ -1075,11 +1075,15 @@ static void set_bfq_weight(Unit *u, const char *controller, uint64_t io_weight)
         /* Adjust to kernel range is 1..1000, the default is 100. */
         bfq_weight = BFQ_WEIGHT(io_weight);
 
-        xsprintf(buf, "%" PRIu64 "\n", bfq_weight);
+        if (major(dev) > 0)
+                xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), bfq_weight);
+        else
+                xsprintf(buf, "%" PRIu64 "\n", bfq_weight);
 
         if (set_attribute_and_warn(u, controller, p, buf) >= 0 && io_weight != bfq_weight)
-                log_unit_debug(u, "%sIOWeight=%" PRIu64 " scaled to %s=%" PRIu64,
+                log_unit_debug(u, "%sIO%sWeight=%" PRIu64 " scaled to %s=%" PRIu64,
                                streq(controller, "blkio") ? "Block" : "",
+                               major(dev) > 0 ? "Device" : "",
                                io_weight, p, bfq_weight);
 }
 
@@ -1092,6 +1096,9 @@ static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_
         if (r < 0)
                 return;
 
+        /* BFQ per-device weights work since Linux kernel v5.4. */
+        set_bfq_weight(u, "io", dev, io_weight);
+
         xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), io_weight);
         (void) set_attribute_and_warn(u, "io", "io.weight", buf);
 }
@@ -1298,7 +1305,7 @@ static void set_io_weight(Unit *u, uint64_t weight) {
 
         assert(u);
 
-        set_bfq_weight(u, "io", weight);
+        set_bfq_weight(u, "io", makedev(0, 0), weight);
 
         xsprintf(buf, "default %" PRIu64 "\n", weight);
         (void) set_attribute_and_warn(u, "io", "io.weight", buf);
@@ -1309,7 +1316,7 @@ static void set_blkio_weight(Unit *u, uint64_t weight) {
 
         assert(u);
 
-        set_bfq_weight(u, "blkio", weight);
+        set_bfq_weight(u, "blkio", makedev(0, 0), weight);
 
         xsprintf(buf, "%" PRIu64 "\n", weight);
         (void) set_attribute_and_warn(u, "blkio", "blkio.weight", buf);