63 lines
2.6 KiB
Nix
63 lines
2.6 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
service_configs,
|
|
...
|
|
}:
|
|
let
|
|
hddTuneIosched = pkgs.writeShellScript "hdd-tune-iosched" ''
|
|
# Called by udev with the partition kernel name (e.g. sdb1).
|
|
# Derives the parent disk and applies mq-deadline iosched params.
|
|
parent=''${1%%[0-9]*}
|
|
dev="/sys/block/$parent"
|
|
[ -d "$dev/queue/iosched" ] || exit 0
|
|
echo 500 > "$dev/queue/iosched/read_expire"
|
|
echo 15000 > "$dev/queue/iosched/write_expire"
|
|
echo 128 > "$dev/queue/iosched/fifo_batch"
|
|
echo 16 > "$dev/queue/iosched/writes_starved"
|
|
echo 4096 > "$dev/queue/max_sectors_kb" 2>/dev/null || true
|
|
'';
|
|
in
|
|
{
|
|
boot.initrd.availableKernelModules = [
|
|
"xhci_pci"
|
|
"ahci"
|
|
"usb_storage"
|
|
"usbhid"
|
|
"sd_mod"
|
|
];
|
|
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
|
boot.kernelModules = [ "kvm-amd" ];
|
|
boot.extraModulePackages = [ ];
|
|
|
|
swapDevices = [ ];
|
|
|
|
hardware.cpu.amd.updateMicrocode = true;
|
|
hardware.enableRedistributableFirmware = true;
|
|
|
|
# HDD I/O tuning for torrent seeding workload (high-concurrency random reads)
|
|
# sharing the pool with latency-sensitive sequential reads (Jellyfin playback).
|
|
#
|
|
# mq-deadline sorts requests into elevator sweeps, reducing seek distance.
|
|
# read_expire=500ms keeps reads bounded so a Jellyfin segment can't queue for
|
|
# seconds behind a torrent burst; write_expire=15s lets the scheduler batch
|
|
# writes for coalescence (torrent writes are async and tolerate delay).
|
|
# The bulk of read coalescence already happens above the scheduler via ZFS
|
|
# aggregation (zfs_vdev_aggregation_limit=4M, read_gap_limit=128K,
|
|
# async_read_max=32), so the scheduler deadline only needs to be large enough
|
|
# to keep the elevator sweep coherent -- 500ms is plenty on rotational disks.
|
|
# fifo_batch=128 keeps sweeps long; writes_starved=16 heavily favors reads.
|
|
# 4 MiB readahead matches libtorrent piece extent affinity for sequential prefetch.
|
|
#
|
|
# The NixOS ZFS module hardcodes a udev rule that forces scheduler="none" on all
|
|
# ZFS member partitions' parent disks (on both add AND change events). We counter
|
|
# it with lib.mkAfter so our rule appears after theirs in 99-local.rules — our
|
|
# rule matches the same partition events and sets mq-deadline back, then a RUN
|
|
# script applies the iosched params. Only targets rotational, non-removable disks
|
|
# (i.e. HDDs, not SSDs or USB).
|
|
services.udev.extraRules = lib.mkAfter ''
|
|
ACTION=="add|change", KERNEL=="sd[a-z]*[0-9]*", ENV{ID_FS_TYPE}=="zfs_member", ATTR{../queue/rotational}=="1", ATTR{../removable}=="0", ATTR{../queue/scheduler}="mq-deadline", ATTR{../queue/read_ahead_kb}="4096", ATTR{../queue/nr_requests}="512", RUN+="${hddTuneIosched} %k"
|
|
'';
|
|
}
|