LEDs
Code: StatusLed, status_led_state(), storage_health(), DiskLeds,
qm2_slot_disks(), set_panel_brightness() in usr/sbin/qnapd. Tests:
TestDiskLeds, TestDiskHealth, TestStorageHealth,
TestQm2.test_slot_leds_*. Settings (Front panel tab): ledstatus,
leddisk, ledbrightness, volumefull, lednight, lednightstart,
lednightend, lednightbrightness.
Driver interfaces
| LED | Values | Blink |
|---|---|---|
qnap8528::status |
0 off, 1 green, 2 red | hardware via timer trigger (≈470–790 ms window) |
qnap8528::hddN |
0 off, 1 green, 2 red | hardware via timer, 80–140 ms window (we use 100 ms) |
qnap8528::usb |
0/1 (blue) | hardware, 280–470 ms |
qnap8528::panel_brightness |
0–100, dims all front LEDs | — |
qm2-<i2c>:green:slotN |
0 off, 1 on, 2 PIC slow blink | timer trigger (software, over the card’s I2C) |
qm2-<i2c>:red:slotN |
0 off, 1 on, 2 PIC slow blink | timer trigger (software) |
- Set the colour (brightness) before the
timertrigger. Writingtrigger=nonestops blinking. - The
timertrigger is a module (ledtrig-timer) on Debian and Proxmox kernels.qnapd.serviceloads it inExecStartPre; without it, writingtimerfails with EINVAL and the daemon falls back to a solid colour.
Status LED
Highest wins:
| State | LED | Cause |
|---|---|---|
| fault | solid red | fan stopped, no sensors, cannot set PWM; a pool FAULTED / UNAVAIL / SUSPENDED; a ZFS pool or local filesystem at least volumefull % used (default 95) |
| degraded / service failed | blinking red | a pool DEGRADED or an md array with a missing member ([U_]); failsafe after a crash |
| rebuilding | green/red alternating (status/blink_bicolor; red blink if the driver has blink_sw_only) |
ZFS resilver, md recovery / resync / reshape |
| starting | blinking green | daemon start |
| ok | solid green |
A ZFS scrub and an md check never change the LED: they are routine
maintenance, not warnings. Pools, arrays and usage are checked every
diskinterval from zpool list -H -o name,health,cap, zpool status
-LP, /proc/mdstat and statvfs of local ext*/xfs/btrfs/jfs/f2fs
mounts (one per device); none of these wake disks. The reasons show on
the Status page and dashboard widget as a Storage row.
Disk LEDs (drive bays and QM2 slots)
| State | Bay LED | QM2 slot LEDs |
|---|---|---|
| disk present, idle or asleep | green | green on, red off |
| I/O in the last second | green, 100 ms hardware blink | green, kernel timer blink |
| failed S.M.A.R.T. or faulted ZFS/md member | red | red on, green off |
| empty | off | both off |
- Bay N = the disk on SATA port N (
/sys/block/sdXreal path contains/ataN/), so it survivessdXrenaming and hot swap (rediscovered every control cycle). - QM2 slot N = the Nth downstream port of the card’s PCIe switch that holds
an NVMe SSD or nothing (ports with a NIC are skipped), in PCI order;
swapped when qm2mod logged
swap=1for that card (generic QM2-2P cards). - Activity:
/sys/block/<disk>/statread+write I/O counters or in-flight requests, polled every 250 ms, held for 1 s. Never wakes a disk. - Errors (checked every
diskinterval):smartctl -n standby -Hfor SATA,smartctl -Hfor NVMe (critical warning),zpool status -LP(not ONLINE, or non-zero READ/WRITE/CKSUM),/proc/mdstat(F)members. - A ZFS mirror spread over both QM2 slots makes both blink together on writes. That is real activity, not a mapping error.
- Activity blink on bays only for
HW_ACTIVITY_BLINK_MODELS(TS-253D, where the EC blinks in hardware). Elsewhere a blink request falls back to software blinking through the EC (a write every ~100 ms per LED, flooding the EC lock), so bays show present / error only. QM2 slots blink through qm2mod and are not affected. - One thread owns all disk LEDs; clean stop leaves present/error colours,
failsafestops any blinking.
Panel brightness and night schedule
panel_brightness (0–100) dims every front LED; QM2 card LEDs are not
affected. With Night brightness on, the control loop uses
lednightbrightness between lednightstart and lednightend (local
time, HH:MM; the window may span midnight, equal times mean never) and
ledbrightness otherwise. It writes only when the wanted value changes,
so the switch happens within one interval of the boundary.
Locate
System › QNAP › Disks lists each bay and QM2 slot (device, model, size,
LED state). Locate blinks the slot’s LED red for 10 minutes; Stop
locating ends it early. The RPC (Qnap.locate) only records the request
in /run/qnapd/locate.json ({slot id: expiry}); the disk LED thread
applies it within 0.25 s, so qnapd stays the only writer of LEDs. Bays:
brightness 2 + timer; QM2 slots: red 1 + timer, at the same rate as
activity (the PIC blink, red 2, is slower). Slot
ids are bayN and <card>-slotN. Needs Drive the disk LEDs.
Verifying a mapping on new hardware
Use tools/hw/led-test.sh (5 s per LED) and ask a person which bay or slot
lit; then read from one disk only (dd if=/dev/sdX of=/dev/null iflag=direct)
and confirm which LED blinks. Protocol:
../testing/hardware-testing.md.
Not done yet
Btrfs device errors in the status LED.
USB LED
qnap8528::usb (blue) blinks (hardware, 400 ms) while the USB Copy task
runs, stays on for 10 s after it succeeds, and goes off; off on failure
(with three short beeps when beeps are on). qnapd leaves it alone
otherwise.