···
1
+
{ config, lib, pkgs, ... }:
3
+
inherit (lib) mkEnableOption mkIf mkOption types;
5
+
cfg = config.hardware.sata.timeout;
8
+
lib.concatStringsSep ", " [
10
+
''SUBSYSTEM=="block"''
11
+
''ENV{ID_${lib.toUpper d.idBy}}=="${d.name}"''
13
+
''ENV{SYSTEMD_WANTS}="${unitName d}"''
16
+
devicePath = device:
17
+
"/dev/disk/by-${device.idBy}/${device.name}";
20
+
"sata-timeout-${lib.strings.sanitizeDerivationName device.name}";
23
+
pkgs.writeShellScript "sata-timeout.sh" ''
28
+
${pkgs.smartmontools}/bin/smartctl \
29
+
-l scterc,${toString cfg.deciSeconds},${toString cfg.deciSeconds} \
30
+
--quietmode errorsonly \
36
+
meta.maintainers = with lib.maintainers; [ peterhoeg ];
38
+
options.hardware.sata.timeout = {
39
+
enable = mkEnableOption "SATA drive timeouts";
41
+
deciSeconds = mkOption {
45
+
Set SCT Error Recovery Control timeout in deciseconds for use in RAID configurations.
47
+
Values are as follows:
49
+
70 = default in consumer drives (7 seconds)
51
+
Maximum is disk dependant but probably 60 seconds.
56
+
description = "List of drives for which to configure the timeout.";
61
+
description = "Drive name without the full path.";
66
+
description = "The method to identify the drive.";
67
+
type = types.enum [ "path" "wwn" ];
75
+
config = mkIf cfg.enable {
76
+
services.udev.extraRules = lib.concatMapStringsSep "\n" buildRule cfg.drives;
78
+
systemd.services = lib.listToAttrs (map
80
+
lib.nameValuePair (unitName e) {
81
+
description = "SATA timeout for ${e.name}";
82
+
wantedBy = [ "sata-timeout.target" ];
85
+
ExecStart = "${startScript} '${devicePath e}'";
87
+
PrivateNetwork = true;
88
+
ProtectHome = "tmpfs";
89
+
ProtectSystem = "strict";
95
+
systemd.targets.sata-timeout = {
96
+
description = "SATA timeout";
97
+
wantedBy = [ "multi-user.target" ];