Deadlock: flush_thread vs Cc write-behind on sustained heavy writes (v1.10, #345 family still present)
Environment
- Driver: WinBtrfs v1.10 (
btrfs.sys, Timestamp6A971661/ Tue Sep 1 21:16:01 2026, CheckSum00147D5D, ImageSize0013E000, basefffff80069f80000` in dump) - OS: Windows 10 Pro, build 26100 (21H2+ line;
Get-ComputerInforeportsWindowsVersion 2009 / OsBuildNumber 26340), 64 GB RAM, pagefile-backed commit limit ~73 GB - Disk: WDC WD10EZEX 1 TB HDD (single device, no RAID), one 1 TB Btrfs volume,
Healthy; ~358 GB used at the time, ~488 GB free (so not an ENOSPC case) - FS features (plain
mkbtrfs, no flags): crc32c, nodesize 16K, skinny-metadata, extiref, no-holes, free-space-tree ON, block-group-tree OFF, mixed groups OFF - Mount options for this volume (per-volume UUID subkey):
Compress=1, CompressType=3 (zstd), ZstdLevel=3, CompressForce=0, NoTrim=1; global defaults otherwise (FlushInterval=30,MaxInline=2048,NoDataCOW=0, …) - Workload: Steam downloading depot 668581 (AppID 668580) —
85 777 880 992 bytes download, 152 499 chunks, ~169 GB staging area,
target
D:\SteamLibraryon the Btrfs volume
Repro
- Steam downloads the ~86 GB depot to the Btrfs HDD volume (sustained
sequential cached writes + staging in
steamapps\downloading). - After a while (tens of minutes into the download, several GB staged), disk activity in Task Manager drops to 0 read / 0 write and never recovers.
- Explorer and all apps accessing the disk freeze; normal reboot hangs forever on the «Restarting» screen; only a hard reset (power button) helps.
- Reproduced 3 times in one evening under the same workload (hard resets at ~21:27, ~21:31, hang captured at ~21:55).
Timeline (local time, 2026-09-05, from System event log + Steam log)
17:45:34—Resource-Exhaustion-Detector2004: commit nearly exhausted; top consumerSearchFilterHost.exeat ~107 GB committed (limit ~73 GB). (Later analysis: treated as a symptom — unflushed dirty pages pinned in cache — since the indexer is normally at ~12–21 MB.)17:46–17:48— service crashes (Cloudflare One Client, connected-user telemetry), WER service timeout.17:47:20—btrfsEvent ID 141 ×2 (empty message — the known «description cannot be found» signature also seen in #438).21:27:08,21:31:22—Kernel-Power41 +EventLog6008 (hard resets).21:55:42–52— hang reproduced; manual crash invoked viaCrashOnCtrlScroll(Ctrl+ScrollLock×2) instead of the power button.21:55:57— WER 1001: bugcheck0xE2 MANUALLY_INITIATED_CRASH,C:\WINDOWS\MEMORY.DMP(3.1 GB automatic kernel dump) — the hung state, captured cleanly.- No new Event 141 entries on the captured hang — a pure deadlock with no driver error paths hit (consistent with «if it's deadlocking, logs won't help»).
Steam content_log.txt at the time:
update started : download 8072525584/85777880992 … stage 11056590580/168991463636,
Downloading 151775 chunks for depot 668581.
Dump analysis (WinDbg, MS symbols + v1.10 release PDBs, lmvm confirms PDB match)
!locks — one hot ERESOURCE:
Resource @ 0xffffc88f2b991358, Shared 1 owning threads
Contention Count = 297
NumberOfSharedWaiters = 8
NumberOfExclusiveWaiters = 1 (ffffc88f2b9e0040)(Compare #345: contention 264, 5 shared + 1 exclusive — same shape.)
Exclusive waiter (ffffc88f2b9e0040):
ExAcquireResourceExclusiveLite
← btrfs+0x38d41 = do_flush+0x21 (flushthread.c:8100)
← btrfs+0x3e5cd = flush_thread+0x8d (flushthread.c:8136)Shared holders, including Cc write-behind (ffffc88f63fc8080 et al.):
ExAcquireResourceSharedLite
← btrfs+0x16a82 = acquire_for_lazy_write+0x22 (cache.c:28)
← CcWriteBehindPreProcess ← CcWriteBehind ← CcWorkerThread~150 parked background write workers (all identical):
do_job+0x4b → do_write_job+0x3b (worker-thread.c:106/73)
→ write_file+0x173 (write.c:4964)
→ write_file2+0x179 (write.c:4465)
→ CcCanIWrite (gate closed, waits forever)Also blocked: 12× calc_thread+0x5a (calcthread.c:302),
long-blocked mountmgr_thread+0x10c (search.c:1105); victim user threads
(e.g. msedge.exe in FltpCreate). Threads Processed: 6874.
Interpretation
Classic flush-vs-Cc deadlock, same family as #345
(fast_io_write vs do_flush/flush_thread, confirmed there by the author):
flush_thread cannot take the resource exclusive to drain while Cc lazy-write
holds it shared; Cc cannot release/proceed because dirty pages never drain
(CcCanIWrite gate shut); all new write jobs pile up behind the gate.
Disk goes 0/0 permanently. No mount parameter creates this cycle — parameters
only set the pressure (sustained 86 GB Steam download + 169 GB staging with
zstd on a single HDD spindle).
Notably: zero compress.c/zstd frames in any of the hundreds of deadlocked
stacks — compression is not a participant in this instance (it was active,
zstd:3, per-volume). The 107 GB SearchFilterHost commit spike is assessed as
secondary (unflushable dirty pages), not causal.
Relation to existing issues
Same symptoms/trigger as #438 (incl. the Event 141 «Volume:…» signature quoted
there), #632, #660, #660 (Steam 40–85 GB updates), #750, #345 (root-caused
there as fast_io_write/FsRtlCopyWrite vs flush thread), #58. The v1.10
changelog lists deadlock fixes, but this Cc/flush ordering variant reproduces
on v1.10.
Artifacts
- Full 3.1 GB
MEMORY.DMPof the hung state (0xE2) — retained, can be shared privately on request (too large for a GitHub attachment). - DebugView kernel capture from the repro window (~1 KB, effectively empty — release driver only emits errors/FIXMEs via DbgPrint).
- Exact RVAs above are against v1.10 (
6A971661); PDBs from the v1.10 release page were used forlnresolution.
Workarounds tried
None applied — compression left ON (per-volume zstd:3) since the stacks clear it of participation; Steam downloads to this volume paused pending upstream feedback. Happy to test a candidate fix build against the same 86 GB Steam workload (100% repro rate here, 3 hangs in one evening).
Source: maharmstone/btrfs