mirror of
https://git.sr.ht/~magic_rb/dotfiles
synced 2024-11-29 11:36:16 +01:00
4b65a9335b
Signed-off-by: magic_rb <magic_rb@redalder.org>
160 lines
4.1 KiB
Nix
160 lines
4.1 KiB
Nix
{
|
|
config,
|
|
pkgs,
|
|
lib,
|
|
...
|
|
}: let
|
|
cfg = config.zfs.health;
|
|
pool = {
|
|
config,
|
|
name,
|
|
...
|
|
}: {
|
|
options = {
|
|
scrub = lib.mkOption {
|
|
type = with lib.types; nullOr str;
|
|
};
|
|
|
|
trim = {
|
|
secure = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
};
|
|
|
|
rate = lib.mkOption {
|
|
type = with lib.types; nullOr int;
|
|
default = null;
|
|
};
|
|
|
|
schedule = lib.mkOption {
|
|
type = with lib.types; nullOr str;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
zpool = lib.getExe' cfg.package "zpool";
|
|
|
|
trimPools = lib.filterAttrs (_: poolConfig: poolConfig.trim != null) cfg.pools;
|
|
in {
|
|
options.zfs.health = {
|
|
enable = lib.mkEnableOption "Enable ZFS health assurance module.";
|
|
|
|
package = lib.mkOption {
|
|
type = lib.types.package;
|
|
default = config.boot.zfs.package;
|
|
};
|
|
|
|
pools = lib.mkOption {
|
|
type = with lib.types; attrsOf (submodule pool);
|
|
default = [];
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
systemd.services = lib.foldl (acc: attr: acc // attr) {} [
|
|
(lib.flip lib.mapAttrs' trimPools
|
|
(
|
|
pool: poolConfig:
|
|
lib.nameValuePair "zfs-health-trim-${pool}-resume" {
|
|
after = ["systemd-suspend.service"];
|
|
wantedBy = ["suspend.target"];
|
|
|
|
restartIfChanged = false;
|
|
|
|
script = ''
|
|
set -eo pipefail
|
|
|
|
if -e /var/run/zfs-health-trim-${pool}-suspended ; then
|
|
systemctl start "zfs-healt-trim-${pool}.service"
|
|
rm /var/run/zfs-health-trim-${pool}-suspended
|
|
fi
|
|
'';
|
|
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
};
|
|
}
|
|
))
|
|
(lib.flip lib.mapAttrs' trimPools
|
|
(
|
|
pool: poolConfig:
|
|
lib.nameValuePair "zfs-health-trim-${pool}-suspend" {
|
|
before = ["systemd-suspend.service"];
|
|
wantedBy = ["suspend.target"];
|
|
|
|
restartIfChanged = false;
|
|
|
|
script = ''
|
|
set -eo pipefail
|
|
|
|
if systemctl status "zfs-healt-trim-${pool}.service" ; then
|
|
touch /var/run/zfs-health-trim-${pool}-suspended
|
|
fi
|
|
'';
|
|
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
};
|
|
}
|
|
))
|
|
(lib.flip lib.mapAttrs' trimPools
|
|
(pool: poolConfig:
|
|
lib.nameValuePair "zfs-health-trim-${pool}" {
|
|
after = ["multi-user.target"];
|
|
|
|
restartIfChanged = false;
|
|
|
|
preStop = ''
|
|
set -eo pipefail
|
|
|
|
if ${zpool} status ${pool} | grep -q trimming ; then
|
|
${zpool} trim --suspend ${pool}
|
|
|
|
if ! [ -z $MAINPID ] ; then
|
|
while kill -0 $MAINPID 2> /dev/null ; do
|
|
sleep 10
|
|
done
|
|
fi
|
|
fi
|
|
'';
|
|
|
|
script = ''
|
|
if ${zpool} status ${pool} | grep -q trimming ; then
|
|
echo "Trim already in progress, polling for completion"
|
|
while ${zpool} status ${pool} | grep trimming >/dev/null ; do
|
|
sleep 60
|
|
done
|
|
else
|
|
${zpool} trim ${pool} \
|
|
--wait \
|
|
${lib.optionalString (poolConfig.trim.rate != null) "--rate ${toString poolConfig.trim.rate}"} \
|
|
${lib.optionalString poolConfig.trim.secure "--secure"}
|
|
fi
|
|
|
|
echo "Trim done!"
|
|
${zpool} status ${pool}
|
|
'';
|
|
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
};
|
|
}))
|
|
];
|
|
|
|
systemd.timers = lib.pipe cfg.pools [
|
|
(lib.filterAttrs (_: poolConfig: poolConfig.trim != null))
|
|
(lib.mapAttrs'
|
|
(pool: poolConfig:
|
|
lib.nameValuePair "zfs-health-trim-${pool}" {
|
|
after = ["multi-user.target"];
|
|
|
|
timerConfig = {
|
|
OnCalendar = poolConfig.trim.schedule;
|
|
Persistent = true;
|
|
};
|
|
}))
|
|
];
|
|
};
|
|
}
|