From f533440d69de4964b7ce89f617a41ff174d49f8a Mon Sep 17 00:00:00 2001 From: Peter Hoeg Date: Mon, 24 Aug 2020 14:44:05 +0800 Subject: nixos/sata: support SATA timeouts --- nixos/modules/hardware/sata.nix | 100 ++++++++++++++++++++++++++++++++++++++++ nixos/modules/module-list.nix | 1 + 2 files changed, 101 insertions(+) create mode 100644 nixos/modules/hardware/sata.nix (limited to 'nixos') diff --git a/nixos/modules/hardware/sata.nix b/nixos/modules/hardware/sata.nix new file mode 100644 index 00000000000..541897527a8 --- /dev/null +++ b/nixos/modules/hardware/sata.nix @@ -0,0 +1,100 @@ +{ config, lib, pkgs, ... }: +let + inherit (lib) mkEnableOption mkIf mkOption types; + + cfg = config.hardware.sata.timeout; + + buildRule = d: + lib.concatStringsSep ", " [ + ''ACTION=="add"'' + ''SUBSYSTEM=="block"'' + ''ENV{ID_${lib.toUpper d.idBy}}=="${d.name}"'' + ''TAG+="systemd"'' + ''ENV{SYSTEMD_WANTS}="${unitName d}"'' + ]; + + devicePath = device: + "/dev/disk/by-${device.idBy}/${device.name}"; + + unitName = device: + "sata-timeout-${lib.strings.sanitizeDerivationName device.name}"; + + startScript = + pkgs.writeShellScript "sata-timeout.sh" '' + set -eEuo pipefail + + device="$1" + + ${pkgs.smartmontools}/bin/smartctl \ + -l scterc,${toString cfg.deciSeconds},${toString cfg.deciSeconds} \ + --quietmode errorsonly \ + "$device" + ''; + +in +{ + meta.maintainers = with lib.maintainers; [ peterhoeg ]; + + options.hardware.sata.timeout = { + enable = mkEnableOption "SATA drive timeouts"; + + deciSeconds = mkOption { + example = "70"; + type = types.int; + description = '' + Set SCT Error Recovery Control timeout in deciseconds for use in RAID configurations. + + Values are as follows: + 0 = disable SCT ERT + 70 = default in consumer drives (7 seconds) + + Maximum is disk dependant but probably 60 seconds. + ''; + }; + + drives = mkOption { + description = "List of drives for which to configure the timeout."; + type = types.listOf + (types.submodule { + options = { + name = mkOption { + description = "Drive name without the full path."; + type = types.str; + }; + + idBy = mkOption { + description = "The method to identify the drive."; + type = types.enum [ "path" "wwn" ]; + default = "path"; + }; + }; + }); + }; + }; + + config = mkIf cfg.enable { + services.udev.extraRules = lib.concatMapStringsSep "\n" buildRule cfg.drives; + + systemd.services = lib.listToAttrs (map + (e: + lib.nameValuePair (unitName e) { + description = "SATA timeout for ${e.name}"; + wantedBy = [ "sata-timeout.target" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${startScript} '${devicePath e}'"; + PrivateTmp = true; + PrivateNetwork = true; + ProtectHome = "tmpfs"; + ProtectSystem = "strict"; + }; + } + ) + cfg.drives); + + systemd.targets.sata-timeout = { + description = "SATA timeout"; + wantedBy = [ "multi-user.target" ]; + }; + }; +} diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index ca7898687b8..e9b9664f8e7 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -70,6 +70,7 @@ ./hardware/usb-wwan.nix ./hardware/onlykey.nix ./hardware/opentabletdriver.nix + ./hardware/sata.nix ./hardware/wooting.nix ./hardware/uinput.nix ./hardware/video/amdgpu.nix -- cgit 1.4.1