1{ config, lib, pkgs, utils, ... }:
2
3with utils;
4with lib;
5
6{
7
8 ###### interface
9
10 options = {
11
12 swapDevices = mkOption {
13 default = [];
14 example = [
15 { device = "/dev/hda7"; }
16 { device = "/var/swapfile"; }
17 { label = "bigswap"; }
18 ];
19 description = ''
20 The swap devices and swap files. These must have been
21 initialised using <command>mkswap</command>. Each element
22 should be an attribute set specifying either the path of the
23 swap device or file (<literal>device</literal>) or the label
24 of the swap device (<literal>label</literal>, see
25 <command>mkswap -L</command>). Using a label is
26 recommended.
27 '';
28
29 type = types.listOf types.optionSet;
30
31 options = {config, options, ...}: {
32
33 options = {
34
35 device = mkOption {
36 example = "/dev/sda3";
37 type = types.str;
38 description = "Path of the device.";
39 };
40
41 label = mkOption {
42 example = "swap";
43 type = types.str;
44 description = ''
45 Label of the device. Can be used instead of <varname>device</varname>.
46 '';
47 };
48
49 size = mkOption {
50 default = null;
51 example = 2048;
52 type = types.nullOr types.int;
53 description = ''
54 If this option is set, ‘device’ is interpreted as the
55 path of a swapfile that will be created automatically
56 with the indicated size (in megabytes) if it doesn't
57 exist.
58 '';
59 };
60
61 priority = mkOption {
62 default = null;
63 example = 2048;
64 type = types.nullOr types.int;
65 description = ''
66 Specify the priority of the swap device. Priority is a value between 0 and 32767.
67 Higher numbers indicate higher priority.
68 null lets the kernel choose a priority, which will show up as a negative value.
69 '';
70 };
71
72 };
73
74 config = {
75 device = mkIf options.label.isDefined
76 "/dev/disk/by-label/${config.label}";
77 };
78
79 };
80
81 };
82
83 };
84
85 config = mkIf ((length config.swapDevices) != 0) {
86
87 system.requiredKernelConfig = with config.lib.kernelConfig; [
88 (isYes "SWAP")
89 ];
90
91 # Create missing swapfiles.
92 # FIXME: support changing the size of existing swapfiles.
93 systemd.services =
94 let
95
96 createSwapDevice = sw:
97 assert sw.device != "";
98 let device' = escapeSystemdPath sw.device; in
99 nameValuePair "mkswap-${escapeSystemdPath sw.device}"
100 { description = "Initialisation of Swapfile ${sw.device}";
101 wantedBy = [ "${device'}.swap" ];
102 before = [ "${device'}.swap" ];
103 path = [ pkgs.utillinux ];
104 script =
105 ''
106 if [ ! -e "${sw.device}" ]; then
107 fallocate -l ${toString sw.size}M "${sw.device}" ||
108 dd if=/dev/zero of="${sw.device}" bs=1M count=${toString sw.size}
109 chmod 0600 ${sw.device}
110 mkswap ${sw.device}
111 fi
112 '';
113 unitConfig.RequiresMountsFor = [ "${dirOf sw.device}" ];
114 unitConfig.DefaultDependencies = false; # needed to prevent a cycle
115 serviceConfig.Type = "oneshot";
116 };
117
118 in listToAttrs (map createSwapDevice (filter (sw: sw.size != null) config.swapDevices));
119
120 };
121
122}