Skip to content

Fix: disks never reach standby on 25.10.4/25.10.5 - temp() guard never fires - #7

Open
kienxux wants to merge 1 commit into
itiligent:mainfrom
kienxux:fix-temp-rotational-fallback
Open

Fix: disks never reach standby on 25.10.4/25.10.5 - temp() guard never fires#7
kienxux wants to merge 1 commit into
itiligent:mainfrom
kienxux:fix-temp-rotational-fallback

Conversation

@kienxux

@kienxux kienxux commented Aug 6, 2026

Copy link
Copy Markdown

Fixes #6, and likely #4.

Symptom

On TrueNAS 25.10.5 the v25 patch applies cleanly and the overlay mounts correctly, but the disks never spin down. Everything normally checked looks right:

$ sudo bash ./spindown-fix.sh status
  ... all four files present and bind-mounted

$ grep -n standby /usr/lib/python3/dist-packages/middlewared/utils/disks_/disk_class.py
322:        cmd = ["smartctl", "-n", "standby", "-x"]
362:            with open(f'{MIDDLEWARE_RUN_DIR}/standby_disks', 'r') as file:

$ stat -c '%d:%i' /usr/lib/.../disk_class.py /mnt/<overlay>/usr/lib/.../disk_class.py
64:200454
64:200454     # same inode, bind mount is live

The middleware is genuinely running the patched module. The disks still stay awake indefinitely.

Root cause

The tell is disk.temperatures:

$ midclt call disk.temperatures
{"sdb": 30.0, "sda": 39.0, "sde": 42.0, "sdf": 47.0, "sdc": 48.0, "sdd": 43.0, "nvme0n1": 37.85}

Real values, with the patch applied — so DiskEntry.temp() is still reaching the temp1_input sysfs read. TrueNAS's own comment on that method explains why it matters:

NOTE: The temp1_input file will issue a command to the disk each time it's accessed from user-space.

Each poll issues a command to the disk and restarts its idle timer, so a rotational disk never accumulates enough idle time to enter standby. The -n standby guard on smartctl is then irrelevant, because it only helps once a disk has already reached standby — which never happens.

The existing guard in temp() depends on {MIDDLEWARE_RUN_DIR}/standby_disks, written by plugins/disk.py during disk.power_management. When that file is not present at runtime the bare except: pass swallows the failure and execution falls through to the sysfs read. The patch then silently degrades to stock behaviour — which matches #6 exactly: patch applied, grep 360 confirms it, disks still awake.

Change

Adds a FileNotFoundError fallback inside temp(): if the standby_disks state file is missing, skip temperature reads for rotational disks (queue/rotational == 1). SSD and NVMe temperatures are unaffected, and the existing standby_disks behaviour is preserved when the file is present.

queue/rotational is read from sysfs and issues no command to the disk, so the check itself cannot wake anything.

Testing

TrueNAS 25.10.5, kernel 6.12.95, four SATA HDDs (Seagate ST4000NM000B, ST4000NE001, ST4000VN006), HDD Standby 10 min, APM 128, system dataset on an SSD pool.

Verified with temp() overridden for rotational disks — the configuration that was working on 25.10.0:

$ midclt call disk.temperatures
{"sdb": null, "sdd": null, "sde": null, "sdf": null, "sda": null, "sdc": null, "nvme0n1": null}

$ for d in sdb sdd sde sdf; do smartctl -i -n standby /dev/$d | grep -i "device is in"; done
Device is in STANDBY mode, exit(2)
Device is in STANDBY mode, exit(2)
Device is in STANDBY mode, exit(2)
Device is in STANDBY mode, exit(2)

Stable across a reboot (Pre Init mount + delayed middlewared restart) and over a 15-hour idle period.

Two notes for others hitting this

  1. Timing. Disks read ACTIVE/IDLE for the first N minutes after a middlewared restart. Wait past the standby timeout before concluding the patch failed — this cost me a day of chasing the wrong thing.
  2. Idle wattage is not only the disks. After the disks were parked, idle draw was still ~4W above the pre-upgrade figure. That turned out to be powertop tunables: SATA link power management reverts to Bad on every boot, and powertop settings do not survive a boot-environment change. Unrelated to this patch, but it looks identical from the wall meter.

…issing

On 25.10.4/25.10.5 the standby_disks state file is absent at runtime, so the existing guard in temp() never fires and temp1_input is read on every poll. Each read issues a command to the disk and restarts its idle timer, so rotational disks never reach standby - the patch silently degrades to stock behaviour. Adds a FileNotFoundError fallback that skips temperature reads for rotational disks. SSD/NVMe temperatures and the existing standby_disks path are unchanged. Tested on 25.10.5, kernel 6.12.95, four SATA HDDs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Not working in 25.10.4

1 participant