CGROUP_BLKIO_WEIGHT_MIN, CGROUP_BLKIO_WEIGHT_MAX);
}
-static void set_bfq_weight(Unit *u, const char *controller, dev_t dev, uint64_t io_weight) {
+static int set_bfq_weight(Unit *u, const char *controller, dev_t dev, uint64_t io_weight) {
static const char * const prop_names[] = {
"IOWeight",
"BlockIOWeight",
* 795fe54c2a82 ("bfq: Add per-device weight") v5.4
* are not interesting anymore. Old kernels will fail with EINVAL, while new kernels won't return
* EINVAL on properly formatted input by us. Treat EINVAL accordingly. */
- if (r == -EINVAL && major(dev) > 0 && !warned) {
- log_unit_warning(u, "Kernel version does not accept per-device setting in %s.", p);
- warned = true;
- }
- if (r < 0)
- log_unit_full_errno(u, r == -EINVAL ? LOG_DEBUG : LOG_LEVEL_CGROUP_WRITE(r),
- r, "Failed to set '%s' attribute on '%s' to '%.*s': %m",
- p, empty_to_root(u->cgroup_path), (int) strcspn(buf, NEWLINE), buf);
- else if (io_weight != bfq_weight)
+ if (r == -EINVAL && major(dev) > 0) {
+ if (!warned) {
+ log_unit_warning(u, "Kernel version does not accept per-device setting in %s.", p);
+ warned = true;
+ }
+ r = -EOPNOTSUPP; /* mask as unconfigured device */
+ } else if (r >= 0 && io_weight != bfq_weight)
log_unit_debug(u, "%s=%" PRIu64 " scaled to %s=%" PRIu64,
prop_names[2*(major(dev) > 0) + streq(controller, "blkio")],
io_weight, p, bfq_weight);
+ return r;
}
static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_t io_weight) {
char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
dev_t dev;
- int r;
+ int r, r1, r2;
- r = lookup_block_device(dev_path, &dev);
- if (r < 0)
+ if (lookup_block_device(dev_path, &dev) < 0)
return;
- /* BFQ per-device weights work since Linux kernel v5.4. */
- set_bfq_weight(u, "io", dev, io_weight);
+ r1 = 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);
+ r2 = cg_set_attribute("io", u->cgroup_path, "io.weight", buf);
+
+ /* Look at the configured device, when both fail, prefer io.weight errno. */
+ r = r2 == -EOPNOTSUPP ? r1 : r2;
+
+ if (r < 0)
+ log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r),
+ r, "Failed to set 'io[.bfq].weight' attribute on '%s' to '%.*s': %m",
+ empty_to_root(u->cgroup_path), (int) strcspn(buf, NEWLINE), buf);
}
static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint64_t blkio_weight) {
assert(u);
- set_bfq_weight(u, "io", makedev(0, 0), weight);
+ (void) 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);
assert(u);
- set_bfq_weight(u, "blkio", makedev(0, 0), weight);
+ (void) set_bfq_weight(u, "blkio", makedev(0, 0), weight);
xsprintf(buf, "%" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "blkio", "blkio.weight", buf);