nixos/iosched: exclude loop devices by default; mention in release notes (#385106)

Changed files
+75 -31
nixos
doc
manual
release-notes
modules
hardware
tests
+2
nixos/doc/manual/release-notes/rl-2411.section.md
···
## New Modules {#sec-release-24.11-new-modules}
+
- [hardware.block](options.html#hardware-block.defaultScheduler) allows configuration of I/O schedulers for block devices.
+
- [KMonad](https://github.com/kmonad/kmonad), an advanced keyboard remapping utility. Available as [services.kmonad](#opt-services.kmonad.enable).
- [Coral](https://coral.ai/), hardware support for Coral.ai Edge TPU devices. Available as [hardware.coral.usb.enable](#opt-hardware.coral.usb.enable) and [hardware.coral.pcie.enable](#opt-hardware.coral.pcie.enable).
+70 -31
nixos/modules/hardware/iosched.nix
···
}:
let
+
inherit (lib)
+
concatLines
+
concatStringsSep
+
mapAttrsToList
+
optional
+
optionals
+
+
mkIf
+
mkOption
+
types
+
;
+
cfg = config.hardware.block;
escape = lib.strings.escape [ ''"'' ];
+
udevValue = types.addCheck types.nonEmptyStr (x: builtins.match "[^\n\r]*" x != null) // {
name = "udevValue";
description = "udev rule value";
descriptionClass = "noun";
};
-
inherit (lib)
-
mkIf
-
mkOption
-
types
-
-
concatLines
-
concatStringsSep
-
mapAttrsToList
-
optional
-
;
+
udevRule =
+
{
+
rotational ? null,
+
include ? null,
+
exclude ? null,
+
scheduler,
+
}:
+
concatStringsSep ", " (
+
[
+
''SUBSYSTEM=="block"''
+
''ACTION=="add|change"''
+
''TEST=="queue/scheduler"''
+
]
+
++ optionals (rotational != null) [
+
''ATTR{queue/rotational}=="${if rotational then "1" else "0"}"''
+
]
+
++ optionals (include != null) [
+
''KERNEL=="${escape include}"''
+
]
+
++ optionals (exclude != null) [
+
''KERNEL!="${escape exclude}"''
+
]
+
++ [
+
''ATTR{queue/scheduler}="${escape scheduler}"''
+
]
+
);
in
{
options.hardware.block = {
···
example = "bfq";
};
+
defaultSchedulerExclude = mkOption {
+
type = types.nullOr udevValue;
+
default = "loop[0-9]*";
+
description = ''
+
Device name pattern to exclude from default scheduler assignment
+
through {option}`config.hardware.block.defaultScheduler` and
+
{option}`config.hardware.block.defaultSchedulerRotational`.
+
+
By default this excludes loop devices which generally do not benefit
+
from extra I/O scheduling in addition to the scheduling already
+
performed for their backing devices.
+
+
This setting does not affect {option}`config.hardware.block.scheduler`.
+
'';
+
};
+
scheduler = mkOption {
type = types.attrsOf udevValue;
default = { };
···
services.udev.packages = [
(pkgs.writeTextDir "etc/udev/rules.d/98-block-io-scheduler.rules" (
concatLines (
-
map (concatStringsSep ", ") (
-
optional (cfg.defaultScheduler != null) [
-
''SUBSYSTEM=="block"''
-
''ACTION=="add|change"''
-
''TEST=="queue/scheduler"''
-
''ATTR{queue/scheduler}="${escape cfg.defaultScheduler}"''
-
]
-
++ optional (cfg.defaultSchedulerRotational != null) [
-
''SUBSYSTEM=="block"''
-
''ACTION=="add|change"''
-
''ATTR{queue/rotational}=="1"''
-
''TEST=="queue/scheduler"''
-
''ATTR{queue/scheduler}="${escape cfg.defaultSchedulerRotational}"''
-
]
-
++ mapAttrsToList (name: sched: [
-
''SUBSYSTEM=="block"''
-
''ACTION=="add|change"''
-
''KERNEL=="${escape name}"''
-
''ATTR{queue/scheduler}="${escape sched}"''
-
]) cfg.scheduler
-
)
+
optional (cfg.defaultScheduler != null) (udevRule {
+
exclude = cfg.defaultSchedulerExclude;
+
scheduler = cfg.defaultScheduler;
+
})
+
++ optional (cfg.defaultSchedulerRotational != null) (udevRule {
+
rotational = true;
+
exclude = cfg.defaultSchedulerExclude;
+
scheduler = cfg.defaultSchedulerRotational;
+
})
+
++ mapAttrsToList (
+
include: scheduler:
+
udevRule {
+
inherit include scheduler;
+
}
+
) cfg.scheduler
)
))
];
+3
nixos/tests/iosched.nix
···
check_scheduler("sdb", "mq-deadline")
check_scheduler("nvme0n1", "kyber")
check_scheduler("mmcblk0", "bfq")
+
+
machine.succeed("tmp=\"$(mktemp)\"; losetup /dev/loop0 \"$tmp\"")
+
check_scheduler("loop0", "none")
'';
}
)