at 24.11-pre 2.6 kB view raw
1{ config, lib, pkgs, ... }: 2let 3 inherit (lib) mkEnableOption mkIf mkOption types; 4 5 cfg = config.hardware.sata.timeout; 6 7 buildRule = d: 8 lib.concatStringsSep ", " [ 9 ''ACTION=="add"'' 10 ''SUBSYSTEM=="block"'' 11 ''ENV{ID_${lib.toUpper d.idBy}}=="${d.name}"'' 12 ''TAG+="systemd"'' 13 ''ENV{SYSTEMD_WANTS}="${unitName d}"'' 14 ]; 15 16 devicePath = device: 17 "/dev/disk/by-${device.idBy}/${device.name}"; 18 19 unitName = device: 20 "sata-timeout-${lib.strings.sanitizeDerivationName device.name}"; 21 22 startScript = 23 pkgs.writeShellScript "sata-timeout.sh" '' 24 set -eEuo pipefail 25 26 device="$1" 27 28 ${pkgs.smartmontools}/bin/smartctl \ 29 -l scterc,${toString cfg.deciSeconds},${toString cfg.deciSeconds} \ 30 --quietmode errorsonly \ 31 "$device" 32 ''; 33 34in 35{ 36 meta.maintainers = with lib.maintainers; [ peterhoeg ]; 37 38 options.hardware.sata.timeout = { 39 enable = mkEnableOption "SATA drive timeouts"; 40 41 deciSeconds = mkOption { 42 example = 70; 43 type = types.int; 44 description = '' 45 Set SCT Error Recovery Control timeout in deciseconds for use in RAID configurations. 46 47 Values are as follows: 48 0 = disable SCT ERT 49 70 = default in consumer drives (7 seconds) 50 51 Maximum is disk dependant but probably 60 seconds. 52 ''; 53 }; 54 55 drives = mkOption { 56 description = "List of drives for which to configure the timeout."; 57 type = types.listOf 58 (types.submodule { 59 options = { 60 name = mkOption { 61 description = "Drive name without the full path."; 62 type = types.str; 63 }; 64 65 idBy = mkOption { 66 description = "The method to identify the drive."; 67 type = types.enum [ "path" "wwn" ]; 68 default = "path"; 69 }; 70 }; 71 }); 72 }; 73 }; 74 75 config = mkIf cfg.enable { 76 services.udev.extraRules = lib.concatMapStringsSep "\n" buildRule cfg.drives; 77 78 systemd.services = lib.listToAttrs (map 79 (e: 80 lib.nameValuePair (unitName e) { 81 description = "SATA timeout for ${e.name}"; 82 wantedBy = [ "sata-timeout.target" ]; 83 serviceConfig = { 84 Type = "oneshot"; 85 ExecStart = "${startScript} '${devicePath e}'"; 86 PrivateTmp = true; 87 PrivateNetwork = true; 88 ProtectHome = "tmpfs"; 89 ProtectSystem = "strict"; 90 }; 91 } 92 ) 93 cfg.drives); 94 95 systemd.targets.sata-timeout = { 96 description = "SATA timeout"; 97 wantedBy = [ "multi-user.target" ]; 98 }; 99 }; 100}