···841 </listitem>
842 <listitem>
843 <para>
00000000844 The <literal>unifi-poller</literal> package and corresponding
845 NixOS module have been renamed to <literal>unpoller</literal>
846 to match upstream.
···841 </listitem>
842 <listitem>
843 <para>
844+ The <literal>zramSwap</literal> is now implemented with
845+ <literal>zram-generator</literal>, and the option
846+ <literal>zramSwap.numDevices</literal> for using ZRAM devices
847+ as general purpose ephemeral block devices has been removed.
848+ </para>
849+ </listitem>
850+ <listitem>
851+ <para>
852 The <literal>unifi-poller</literal> package and corresponding
853 NixOS module have been renamed to <literal>unpoller</literal>
854 to match upstream.
+2
nixos/doc/manual/release-notes/rl-2305.section.md
···209210- The `services.fwupd` module now allows arbitrary daemon settings to be configured in a structured manner ([`services.fwupd.daemonSettings`](#opt-services.fwupd.daemonSettings)).
21100212- The `unifi-poller` package and corresponding NixOS module have been renamed to `unpoller` to match upstream.
213214- 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.
···209210- The `services.fwupd` module now allows arbitrary daemon settings to be configured in a structured manner ([`services.fwupd.daemonSettings`](#opt-services.fwupd.daemonSettings)).
211212+- 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.
213+214- The `unifi-poller` package and corresponding NixOS module have been renamed to `unpoller` to match upstream.
215216- 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.
+38-122
nixos/modules/config/zram.nix
···1{ config, lib, pkgs, ... }:
23-with lib;
4-5let
67 cfg = config.zramSwap;
8-9- # don't set swapDevices as mkDefault, so we can detect user had read our warning
10- # (see below) and made an action (or not)
11- devicesCount = if cfg.swapDevices != null then cfg.swapDevices else cfg.numDevices;
12-13- devices = map (nr: "zram${toString nr}") (range 0 (devicesCount - 1));
14-15- modprobe = "${pkgs.kmod}/bin/modprobe";
16-17- warnings =
18- assert cfg.swapDevices != null -> cfg.numDevices >= cfg.swapDevices;
19- flatten [
20- (optional (cfg.numDevices > 1 && cfg.swapDevices == null) ''
21- Using several small zram devices as swap is no better than using one large.
22- Set either zramSwap.numDevices = 1 or explicitly set zramSwap.swapDevices.
23-24- Previously multiple zram devices were used to enable multithreaded
25- compression. Linux supports multithreaded compression for 1 device
26- since 3.15. See https://lkml.org/lkml/2014/2/28/404 for details.
27- '')
28- ];
2930in
3132{
33000034 ###### interface
3536 options = {
3738 zramSwap = {
3940- enable = mkOption {
41 default = false;
42- type = types.bool;
43 description = lib.mdDoc ''
44 Enable in-memory compressed devices and swap space provided by the zram
45 kernel module.
···49 '';
50 };
5152- numDevices = mkOption {
53- default = 1;
54- type = types.int;
55- description = lib.mdDoc ''
56- Number of zram devices to create. See also
57- `zramSwap.swapDevices`
58- '';
59- };
60-61- swapDevices = mkOption {
62- default = null;
63 example = 1;
64- type = with types; nullOr int;
65 description = lib.mdDoc ''
66- Number of zram devices to be used as swap. Must be
67- `<= zramSwap.numDevices`.
68- Default is same as `zramSwap.numDevices`, recommended is 1.
69 '';
70 };
7172- memoryPercent = mkOption {
73 default = 50;
74- type = types.int;
75 description = lib.mdDoc ''
76 Maximum total amount of memory that can be stored in the zram swap devices
77 (as a percentage of your total memory). Defaults to 1/2 of your total
···80 '';
81 };
8283- memoryMax = mkOption {
84 default = null;
85- type = with types; nullOr int;
86 description = lib.mdDoc ''
87 Maximum total amount of memory (in bytes) that can be stored in the zram
88 swap devices.
···90 '';
91 };
9293- priority = mkOption {
94 default = 5;
95- type = types.int;
96 description = lib.mdDoc ''
97 Priority of the zram swap devices. It should be a number higher than
98 the priority of your disk-based swap devices (so that the system will
···100 '';
101 };
102103- algorithm = mkOption {
104 default = "zstd";
105 example = "lz4";
106- type = with types; either (enum [ "lzo" "lz4" "zstd" ]) str;
107 description = lib.mdDoc ''
108 Compression algorithm. `lzo` has good compression,
109 but is slow. `lz4` has bad compression, but is fast.
···116117 };
118119- config = mkIf cfg.enable {
120-121- inherit warnings;
122123 system.requiredKernelConfig = with config.lib.kernelConfig; [
124 (isModule "ZRAM")
···128 # once in stage 2 boot, and again when the zram-reloader service starts.
129 # boot.kernelModules = [ "zram" ];
130131- boot.extraModprobeConfig = ''
132- options zram num_devices=${toString cfg.numDevices}
133- '';
134-135- boot.kernelParams = ["zram.num_devices=${toString cfg.numDevices}"];
136-137- services.udev.extraRules = ''
138- KERNEL=="zram[0-9]*", ENV{SYSTEMD_WANTS}="zram-init-%k.service", TAG+="systemd"
139- '';
140-141- systemd.services =
142- let
143- createZramInitService = dev:
144- nameValuePair "zram-init-${dev}" {
145- description = "Init swap on zram-based device ${dev}";
146- after = [ "dev-${dev}.device" "zram-reloader.service" ];
147- requires = [ "dev-${dev}.device" "zram-reloader.service" ];
148- before = [ "dev-${dev}.swap" ];
149- requiredBy = [ "dev-${dev}.swap" ];
150- unitConfig.DefaultDependencies = false; # needed to prevent a cycle
151- serviceConfig = {
152- Type = "oneshot";
153- RemainAfterExit = true;
154- ExecStop = "${pkgs.runtimeShell} -c 'echo 1 > /sys/class/block/${dev}/reset'";
155- };
156- script = ''
157- set -euo pipefail
158-159- # Calculate memory to use for zram
160- mem=$(${pkgs.gawk}/bin/awk '/MemTotal: / {
161- value=int($2*${toString cfg.memoryPercent}/100.0/${toString devicesCount}*1024);
162- ${lib.optionalString (cfg.memoryMax != null) ''
163- memory_max=int(${toString cfg.memoryMax}/${toString devicesCount});
164- if (value > memory_max) { value = memory_max }
165- ''}
166- print value
167- }' /proc/meminfo)
168-169- ${pkgs.util-linux}/sbin/zramctl --size $mem --algorithm ${cfg.algorithm} /dev/${dev}
170- ${pkgs.util-linux}/sbin/mkswap /dev/${dev}
171- '';
172- restartIfChanged = false;
173- };
174- in listToAttrs ((map createZramInitService devices) ++ [(nameValuePair "zram-reloader"
175- {
176- description = "Reload zram kernel module when number of devices changes";
177- wants = [ "systemd-udevd.service" ];
178- after = [ "systemd-udevd.service" ];
179- unitConfig.DefaultDependencies = false; # needed to prevent a cycle
180- serviceConfig = {
181- Type = "oneshot";
182- RemainAfterExit = true;
183- ExecStartPre = "-${modprobe} -r zram";
184- ExecStart = "-${modprobe} zram";
185- ExecStop = "-${modprobe} -r zram";
186- };
187- restartTriggers = [
188- cfg.numDevices
189- cfg.algorithm
190- cfg.memoryPercent
191- ];
192- restartIfChanged = true;
193- })]);
194195- swapDevices =
196- let
197- useZramSwap = dev:
198- {
199- device = "/dev/${dev}";
200- priority = cfg.priority;
201- };
202- in map useZramSwap devices;
00000000203204 };
205
···1{ config, lib, pkgs, ... }:
2003let
45 cfg = config.zramSwap;
6+ devices = map (nr: "zram${toString nr}") (lib.range 0 (cfg.swapDevices - 1));
0000000000000000000078in
910{
1112+ imports = [
13+ (lib.mkRemovedOptionModule [ "zramSwap" "numDevices" ] "Using ZRAM devices as general purpose ephemeral block devices is no longer supported")
14+ ];
15+16 ###### interface
1718 options = {
1920 zramSwap = {
2122+ enable = lib.mkOption {
23 default = false;
24+ type = lib.types.bool;
25 description = lib.mdDoc ''
26 Enable in-memory compressed devices and swap space provided by the zram
27 kernel module.
···31 '';
32 };
3334+ swapDevices = lib.mkOption {
35+ default = 0;
00000000036 example = 1;
37+ type = lib.types.int;
38 description = lib.mdDoc ''
39+ Number of zram devices to be used as swap, recommended is 1.
0040 '';
41 };
4243+ memoryPercent = lib.mkOption {
44 default = 50;
45+ type = lib.types.int;
46 description = lib.mdDoc ''
47 Maximum total amount of memory that can be stored in the zram swap devices
48 (as a percentage of your total memory). Defaults to 1/2 of your total
···51 '';
52 };
5354+ memoryMax = lib.mkOption {
55 default = null;
56+ type = with lib.types; nullOr int;
57 description = lib.mdDoc ''
58 Maximum total amount of memory (in bytes) that can be stored in the zram
59 swap devices.
···61 '';
62 };
6364+ priority = lib.mkOption {
65 default = 5;
66+ type = lib.types.int;
67 description = lib.mdDoc ''
68 Priority of the zram swap devices. It should be a number higher than
69 the priority of your disk-based swap devices (so that the system will
···71 '';
72 };
7374+ algorithm = lib.mkOption {
75 default = "zstd";
76 example = "lz4";
77+ type = with lib.types; either (enum [ "lzo" "lz4" "zstd" ]) str;
78 description = lib.mdDoc ''
79 Compression algorithm. `lzo` has good compression,
80 but is slow. `lz4` has bad compression, but is fast.
···8788 };
8990+ config = lib.mkIf cfg.enable {
009192 system.requiredKernelConfig = with config.lib.kernelConfig; [
93 (isModule "ZRAM")
···97 # once in stage 2 boot, and again when the zram-reloader service starts.
98 # boot.kernelModules = [ "zram" ];
99100+ systemd.packages = [ pkgs.zram-generator ];
101+ systemd.services."systemd-zram-setup@".path = [ pkgs.util-linux ]; # for mkswap
0000000000000000000000000000000000000000000000000000000000000102103+ environment.etc."systemd/zram-generator.conf".source =
104+ (pkgs.formats.ini { }).generate "zram-generator.conf" (lib.listToAttrs
105+ (builtins.map
106+ (dev: {
107+ name = dev;
108+ value =
109+ let
110+ size = "${toString cfg.memoryPercent} / 100 * ram";
111+ in
112+ {
113+ zram-size = if cfg.memoryMax != null then "min(${size}, ${toString cfg.memoryMax} / 1024 / 1024)" else size;
114+ compression-algorithm = cfg.algorithm;
115+ swap-priority = cfg.priority;
116+ };
117+ })
118+ devices));
119120 };
121