ZFS tab: Writes — the RAM write buffer, each pool's write rate, and a landing tier with its mover

Live from arcstats (dirty), dmu_tx (throttled writes), each pool's txgs (bytes synced to disk)
and objset kstats (bytes from programs). A landing tier — a mergerfs pool whose first branch is
fast storage and whose last is a ZFS dataset — is detected from mergerfs's branch xattr; a mover
status file in /run/landing-mover/ adds its queue, the file in flight and totals. Sensors
zfs.write.*, zfs.<pool>.write_bps|logical_bps and zfs.<pool>.landing.* carry the history.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-10-25 22:28:40 -07:00
co-authored by Claude Opus 5.5
parent 1a9b31ea0a
commit 86cfcd2bad
9 changed files with 754 additions and 9 deletions
+4 -1
View File
@@ -150,7 +150,8 @@ type Sample struct {
FS []FS `json:"fs"`
UPS *UPS `json:"ups"`
GPUs []GPU `json:"gpus"`
ARC *ARC `json:"arc"` // the ZFS read cache; nil without the module
ARC *ARC `json:"arc"` // the ZFS read cache; nil without the module
ZFSWrite *ZFSWrites `json:"zfs_writes"` // the ZFS write path; nil without the module
Uptime float64 `json:"uptime"`
fsT, upsT int64 // when the slow sections were really read; sensors report these, not T
@@ -182,6 +183,7 @@ type Collector struct {
gpu gpuState
power cpuPowerState
prevARC arcPrev
prevZW zfsWritePrev
subMu sync.Mutex
subs map[chan struct{}]struct{} // told after every sample; see Subscribe
@@ -368,6 +370,7 @@ func (c *Collector) sample() {
s.UPS, s.upsT = c.lastUPS, c.upsAt.UnixMilli()
s.GPUs = c.gpus(now, cpuTemp(s.Temps))
s.ARC = c.arc(now)
s.ZFSWrite = c.zfsWrites(now, s.ARC, s.Disks)
if first {
return // deltas are meaningless on the priming pass