diff options
author | Florian Klink <flokli@flokli.de> | 2023-02-06 12:53:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-06 12:53:19 +0100 |
commit | 5aa52365e724f6dcccad9961f3da775947496b0e (patch) | |
tree | f44888d70d3c1f417e49de2d30c06f1f2446aa8b | |
parent | c326033c381ae71ed5a81cc07c6619017d4bfff4 (diff) | |
parent | 989b9901dc7d1d72f1591d05c3cef074798eb896 (diff) |
Merge pull request #214103 from NickCao/zram
nixos/zram: use zram-generator
-rw-r--r-- | nixos/doc/manual/from_md/release-notes/rl-2305.section.xml | 8 | ||||
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2305.section.md | 2 | ||||
-rw-r--r-- | nixos/modules/config/zram.nix | 162 | ||||
-rw-r--r-- | nixos/tests/zram-generator.nix | 24 |
4 files changed, 64 insertions, 132 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml index 27b7feaef838a..d573acfdd3b7f 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml @@ -841,6 +841,14 @@ </listitem> <listitem> <para> + The <literal>zramSwap</literal> is now implemented with + <literal>zram-generator</literal>, and the option + <literal>zramSwap.numDevices</literal> for using ZRAM devices + as general purpose ephemeral block devices has been removed. + </para> + </listitem> + <listitem> + <para> The <literal>unifi-poller</literal> package and corresponding NixOS module have been renamed to <literal>unpoller</literal> to match upstream. diff --git a/nixos/doc/manual/release-notes/rl-2305.section.md b/nixos/doc/manual/release-notes/rl-2305.section.md index 0f827b4a6db4a..27bfdd5df66ff 100644 --- a/nixos/doc/manual/release-notes/rl-2305.section.md +++ b/nixos/doc/manual/release-notes/rl-2305.section.md @@ -209,6 +209,8 @@ In addition to numerous new and upgraded packages, this release has the followin - The `services.fwupd` module now allows arbitrary daemon settings to be configured in a structured manner ([`services.fwupd.daemonSettings`](#opt-services.fwupd.daemonSettings)). +- The `zramSwap` is now implemented with `zram-generator`, and the option `zramSwap.numDevices` for using ZRAM devices as general purpose ephemeral block devices has been removed. + - The `unifi-poller` package and corresponding NixOS module have been renamed to `unpoller` to match upstream. - The new option `services.tailscale.useRoutingFeatures` controls various settings for using Tailscale features like exit nodes and subnet routers. If you wish to use your machine as an exit node, you can set this setting to `server`, otherwise if you wish to use an exit node you can set this setting to `client`. The strict RPF warning has been removed as the RPF will be loosened automatically based on the value of this setting. diff --git a/nixos/modules/config/zram.nix b/nixos/modules/config/zram.nix index 87ac53a60b7ed..7b4639d8b1c8a 100644 --- a/nixos/modules/config/zram.nix +++ b/nixos/modules/config/zram.nix @@ -1,45 +1,27 @@ { config, lib, pkgs, ... }: -with lib; - let cfg = config.zramSwap; - - # don't set swapDevices as mkDefault, so we can detect user had read our warning - # (see below) and made an action (or not) - devicesCount = if cfg.swapDevices != null then cfg.swapDevices else cfg.numDevices; - - devices = map (nr: "zram${toString nr}") (range 0 (devicesCount - 1)); - - modprobe = "${pkgs.kmod}/bin/modprobe"; - - warnings = - assert cfg.swapDevices != null -> cfg.numDevices >= cfg.swapDevices; - flatten [ - (optional (cfg.numDevices > 1 && cfg.swapDevices == null) '' - Using several small zram devices as swap is no better than using one large. - Set either zramSwap.numDevices = 1 or explicitly set zramSwap.swapDevices. - - Previously multiple zram devices were used to enable multithreaded - compression. Linux supports multithreaded compression for 1 device - since 3.15. See https://lkml.org/lkml/2014/2/28/404 for details. - '') - ]; + devices = map (nr: "zram${toString nr}") (lib.range 0 (cfg.swapDevices - 1)); in { + imports = [ + (lib.mkRemovedOptionModule [ "zramSwap" "numDevices" ] "Using ZRAM devices as general purpose ephemeral block devices is no longer supported") + ]; + ###### interface options = { zramSwap = { - enable = mkOption { + enable = lib.mkOption { default = false; - type = types.bool; + type = lib.types.bool; description = lib.mdDoc '' Enable in-memory compressed devices and swap space provided by the zram kernel module. @@ -49,29 +31,18 @@ in ''; }; - numDevices = mkOption { - default = 1; - type = types.int; - description = lib.mdDoc '' - Number of zram devices to create. See also - `zramSwap.swapDevices` - ''; - }; - - swapDevices = mkOption { - default = null; + swapDevices = lib.mkOption { + default = 0; example = 1; - type = with types; nullOr int; + type = lib.types.int; description = lib.mdDoc '' - Number of zram devices to be used as swap. Must be - `<= zramSwap.numDevices`. - Default is same as `zramSwap.numDevices`, recommended is 1. + Number of zram devices to be used as swap, recommended is 1. ''; }; - memoryPercent = mkOption { + memoryPercent = lib.mkOption { default = 50; - type = types.int; + type = lib.types.int; description = lib.mdDoc '' Maximum total amount of memory that can be stored in the zram swap devices (as a percentage of your total memory). Defaults to 1/2 of your total @@ -80,9 +51,9 @@ in ''; }; - memoryMax = mkOption { + memoryMax = lib.mkOption { default = null; - type = with types; nullOr int; + type = with lib.types; nullOr int; description = lib.mdDoc '' Maximum total amount of memory (in bytes) that can be stored in the zram swap devices. @@ -90,9 +61,9 @@ in ''; }; - priority = mkOption { + priority = lib.mkOption { default = 5; - type = types.int; + type = lib.types.int; description = lib.mdDoc '' Priority of the zram swap devices. It should be a number higher than the priority of your disk-based swap devices (so that the system will @@ -100,10 +71,10 @@ in ''; }; - algorithm = mkOption { + algorithm = lib.mkOption { default = "zstd"; example = "lz4"; - type = with types; either (enum [ "lzo" "lz4" "zstd" ]) str; + type = with lib.types; either (enum [ "lzo" "lz4" "zstd" ]) str; description = lib.mdDoc '' Compression algorithm. `lzo` has good compression, but is slow. `lz4` has bad compression, but is fast. @@ -116,9 +87,7 @@ in }; - config = mkIf cfg.enable { - - inherit warnings; + config = lib.mkIf cfg.enable { system.requiredKernelConfig = with config.lib.kernelConfig; [ (isModule "ZRAM") @@ -128,78 +97,25 @@ in # once in stage 2 boot, and again when the zram-reloader service starts. # boot.kernelModules = [ "zram" ]; - boot.extraModprobeConfig = '' - options zram num_devices=${toString cfg.numDevices} - ''; - - boot.kernelParams = ["zram.num_devices=${toString cfg.numDevices}"]; - - services.udev.extraRules = '' - KERNEL=="zram[0-9]*", ENV{SYSTEMD_WANTS}="zram-init-%k.service", TAG+="systemd" - ''; - - systemd.services = - let - createZramInitService = dev: - nameValuePair "zram-init-${dev}" { - description = "Init swap on zram-based device ${dev}"; - after = [ "dev-${dev}.device" "zram-reloader.service" ]; - requires = [ "dev-${dev}.device" "zram-reloader.service" ]; - before = [ "dev-${dev}.swap" ]; - requiredBy = [ "dev-${dev}.swap" ]; - unitConfig.DefaultDependencies = false; # needed to prevent a cycle - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStop = "${pkgs.runtimeShell} -c 'echo 1 > /sys/class/block/${dev}/reset'"; - }; - script = '' - set -euo pipefail - - # Calculate memory to use for zram - mem=$(${pkgs.gawk}/bin/awk '/MemTotal: / { - value=int($2*${toString cfg.memoryPercent}/100.0/${toString devicesCount}*1024); - ${lib.optionalString (cfg.memoryMax != null) '' - memory_max=int(${toString cfg.memoryMax}/${toString devicesCount}); - if (value > memory_max) { value = memory_max } - ''} - print value - }' /proc/meminfo) - - ${pkgs.util-linux}/sbin/zramctl --size $mem --algorithm ${cfg.algorithm} /dev/${dev} - ${pkgs.util-linux}/sbin/mkswap /dev/${dev} - ''; - restartIfChanged = false; - }; - in listToAttrs ((map createZramInitService devices) ++ [(nameValuePair "zram-reloader" - { - description = "Reload zram kernel module when number of devices changes"; - wants = [ "systemd-udevd.service" ]; - after = [ "systemd-udevd.service" ]; - unitConfig.DefaultDependencies = false; # needed to prevent a cycle - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStartPre = "-${modprobe} -r zram"; - ExecStart = "-${modprobe} zram"; - ExecStop = "-${modprobe} -r zram"; - }; - restartTriggers = [ - cfg.numDevices - cfg.algorithm - cfg.memoryPercent - ]; - restartIfChanged = true; - })]); - - swapDevices = - let - useZramSwap = dev: - { - device = "/dev/${dev}"; - priority = cfg.priority; - }; - in map useZramSwap devices; + systemd.packages = [ pkgs.zram-generator ]; + systemd.services."systemd-zram-setup@".path = [ pkgs.util-linux ]; # for mkswap + + environment.etc."systemd/zram-generator.conf".source = + (pkgs.formats.ini { }).generate "zram-generator.conf" (lib.listToAttrs + (builtins.map + (dev: { + name = dev; + value = + let + size = "${toString cfg.memoryPercent} / 100 * ram"; + in + { + zram-size = if cfg.memoryMax != null then "min(${size}, ${toString cfg.memoryMax} / 1024 / 1024)" else size; + compression-algorithm = cfg.algorithm; + swap-priority = cfg.priority; + }; + }) + devices)); }; diff --git a/nixos/tests/zram-generator.nix b/nixos/tests/zram-generator.nix index affa081bcc353..3407361d2824f 100644 --- a/nixos/tests/zram-generator.nix +++ b/nixos/tests/zram-generator.nix @@ -1,18 +1,24 @@ import ./make-test-python.nix { name = "zram-generator"; - nodes.machine = { pkgs, ... }: { - environment.etc."systemd/zram-generator.conf".text = '' - [zram0] - zram-size = ram / 2 - ''; - systemd.packages = [ pkgs.zram-generator ]; - systemd.services."systemd-zram-setup@".path = [ pkgs.util-linux ]; # for mkswap + nodes.machine = { ... }: { + zramSwap = { + enable = true; + priority = 10; + algorithm = "lz4"; + swapDevices = 2; + memoryPercent = 30; + memoryMax = 10 * 1024 * 1024; + }; }; testScript = '' machine.wait_for_unit("systemd-zram-setup@zram0.service") - assert "zram0" in machine.succeed("zramctl -n") - assert "zram0" in machine.succeed("swapon --show --noheadings") + machine.wait_for_unit("systemd-zram-setup@zram1.service") + zram = machine.succeed("zramctl --noheadings --raw") + swap = machine.succeed("swapon --show --noheadings") + for i in range(2): + assert f"/dev/zram{i} lz4 10M" in zram + assert f"/dev/zram{i} partition 10M" in swap ''; } |