#822·btrfs

Deadlock: flush_thread vs Cc write-behind on sustained heavy writes (v1.10, #345 family still present)

Author: ShredRumCreated Sep 5, 2026Updated Sep 10, 2026

Environment

  • Driver: WinBtrfs v1.10 (btrfs.sys, Timestamp 6A971661 / Tue Sep 1 21:16:01 2026, CheckSum 00147D5D, ImageSize 0013E000, base fffff80069f80000` in dump)
  • OS: Windows 10 Pro, build 26100 (21H2+ line; Get-ComputerInfo reports WindowsVersion 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:\SteamLibrary on the Btrfs volume

Repro

  1. Steam downloads the ~86 GB depot to the Btrfs HDD volume (sustained sequential cached writes + staging in steamapps\downloading).
  2. 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.
  3. Explorer and all apps accessing the disk freeze; normal reboot hangs forever on the «Restarting» screen; only a hard reset (power button) helps.
  4. 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:34Resource-Exhaustion-Detector 2004: commit nearly exhausted; top consumer SearchFilterHost.exe at ~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:20btrfs Event ID 141 ×2 (empty message — the known «description cannot be found» signature also seen in #438).
  • 21:27:08, 21:31:22Kernel-Power 41 + EventLog 6008 (hard resets).
  • 21:55:42–52 — hang reproduced; manual crash invoked via CrashOnCtrlScroll (Ctrl+ScrollLock×2) instead of the power button.
  • 21:55:57 — WER 1001: bugcheck 0xE2 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.DMP of 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 for ln resolution.

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).