DisksService.getDisks wakes spun-down array disks via systeminformation.diskLayout()
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 65/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 静か
- 技術スタック
- linux, typescript
調査の方向性
Start in api/src/unraid-api/graph/resolvers/disks/disks.service.ts at getDisks(), then compare its diskLayout() path with getTemperature() and the WebUI's SmartInfo.php behavior. Exercise /graphql with { disks { id } } against standby disks; done means identity is returned without waking them and smartStatus remains unknown for disks that are still asleep.
索引モデルが issue の本文から書いたものです。
説明
Environment
Unraid OS Version: 7.3.1
Are you using a reverse proxy? No (tested directly against the LAN IP and via the LAN hostname; reproduction does not involve any proxy).
Pre-submission Checklist
- I have verified that my Unraid OS is up to date
- I have tested this issue by accessing my server directly (not through a reverse proxy)
- This is not an Unraid Connect related issue (if it is, please submit via the support form instead)
Issue Description
Querying { disks { ... } } over the unraid-api GraphQL endpoint spins up array drives that were in standby. The resolver populates each Disk via systeminformation.diskLayout(), which on Linux runs smartctl -H and smartctl -a -j per device (systeminformation 5.31.7, lib/filesystem.js), without the -n standby flag. Modern large HDDs (Seagate Exos ≥16 TB, WD Gold ≥16 TB, etc.) treat the resulting ATA commands as a wake-up signal and leave standby.
Note that the same file's getTemperature(device) already does the right thing on line 104:
const { stdout } = await execa('smartctl', ['-n', 'standby', '-A', '-j', device]);
That is exactly the call shape we need everywhere else in this service.
The relevant code in api/src/unraid-api/graph/resolvers/disks/disks.service.ts:378 (unchanged on main as of this edit):
async getDisks(): Promise<Disk[]> {
const partitions = await blockDevices().then((devices) =>
devices.filter((device) => device.type === 'part')
);
const arrayDisks = this.configService.get<ArrayDisk[]>('store.emhttp.disks', []);
const { data } = await batchProcess(await diskLayout(), async (disk) =>
this.parseDisk(disk, partitions, arrayDisks)
);
return data;
}
The official WebUI (/usr/local/emhttp/plugins/dynamix/include/SmartInfo.php) already avoids this: identity comes from cached disks.ini populated by emhttpd at boot, and any smartctl invocation passes -n standby. That is why opening Main on the WebUI never wakes drives but a GraphQL { disks { ... } } does.
Steps to Reproduce
- Spin down the array disks via the WebUI or
hdparm -y /dev/sdX. - Confirm they are sleeping:
smartctl -n standby -i /dev/sdX→Device is in STANDBY mode. - Issue a minimal GraphQL query through
/graphql:{ disks { id } } - Re-check the larger drives:
smartctl -n standby -i /dev/sdX. - The ≥16 TB drives that reported
STANDBY modein step 2 now reportPower mode. Field selection in the query is irrelevant: even{ disks { id } }is enough because the resolver fully populates each disk viadiskLayout()before returning.
Expected Behavior
GraphQL queries against disks, and everything else that goes through DisksService.getDisks() (disk(id), assignableDisks, the onboarding Internal Boot step via getAssignableDisks() / getInternalBootDevices(), and the disk temperature sensors), should not transition any drive out of standby. Identity fields (vendor, model, serialNum, firmwareRevision, interfaceType, size, type) should come from kernel metadata, and smartStatus should be probed only for drives that are already spinning, matching the WebUI's behavior.
Actual Behavior
Test data from one server (mixed array, single query of { disks { id } } from a fully spun-down baseline):
| Disk | Model | Size | After { disks { id } } |
|---|---|---|---|
| /dev/sda | WDC WD160EDGZ | 16 TB | Spun up |
| /dev/sdb | WDC WD180EDGZ (parity) | 18 TB | Spun up |
| /dev/sdd | WDC WD30NPRZ | 3 TB | Still standby |
| /dev/sde | WDC WD40EZRX | 4 TB | Still standby |
| /dev/sdf | WDC WD180EDGZ | 18 TB | Spun up |
| /dev/sdg | ST16000NM000J | 16 TB | Spun up |
| /dev/sdh | ST16000NM000J | 16 TB | Spun up |
Pattern: large modern drives wake on any ATA command; older smaller drives ignore it. Consistent with current Seagate / WD firmware behavior.
Additional Context
Suggested fix. Replace diskLayout() with a custom enumeration that mirrors the WebUI strategy:
- Use
lsblk -d -b -J -Ofor identity. It is sysfs-backed with no SMART access.-bmatters: without itsizecomes back as a string like"931.5G"instead of bytes (systeminformation itself callslsblk -ablJO). - Map each lsblk device to the shape
diskLayout()returned (device,name,vendor,serialNum,firmwareRevision,interfaceType,size,typeasHD/SSD/NVMefromrotaandtran), soparseDiskcan stay as it is. lsblk reportsvendor: "ATA"for SATA drives, so the vendor is better derived from the model string in that case. - Use
smartctl -n standby -H -j /dev/sdXper disk forsmartStatus. Treat exit code 2 as "standby, status unknown". - Keep
blockDevices()for partitions.
#2091 adds a DisksService.getPhysicalDisks() built on lsblk -b for the temperature sensors; the fix above could build on it once it lands.
Reference implementation. I have implemented this pattern as a runtime monkey-patch in u-manager-companion (function patch_disks_service_bundle) and verified on the same server that:
{ disks { ... } }returns the full record (vendor / serial / firmware / interfaceType / size) andsmartStatus: "UNKNOWN"for spun-down disks.- No drive in standby transitions to active.
- Latency drops from several seconds to <500 ms because we no longer wait on
smartctlfor every device.
Happy to open a PR with the upstream version of the same change.
- 主要言語
- TypeScript
- スター
- 113
- フォーク
- 23
- 平均マージ
- 2日 8時間
- マージ済み PR(30日)
- 9
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
unraid/api のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 64/100
メンテナーはふだん 1 日以内に返信
-
Work Intent: File Manager integration for #1599対応中かも @elibosley が 9 日前に担当しました。 オープン
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 58/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
Bayern feature:Application ready web
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
digitalfabrik/entitlementcard#3176 ·
メンテナーはふだん 7 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
NanmiCoder/cc-haha#1533 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
🐛 Bug: Calendar work items cannot be opened on mobile対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 92/100