Hang within NtAllocateVirtualMemory when saving large file in 3dsmax

I have a file system driver (not filter driver) and I am investigating a hang that happens when 3dsmax saves large files. Using the !locks command I am able to determine that at the time of the hang there are 2 locks held; with one of them being in contention with my file system.

The first thread is an MiMappedPageWriter thread, which exclusively owns the lock. The thread is waiting using KeWaitForMultipleObjects and the wait reason is listed as WrFreePage. The second thread is a thread executing NtAllocateVirtualMemory that accesses my file system using FsRtlGetFileSize; my file system attempts to acquire shared the lock and blocks because the lock is already acquired by the MiMappedPageWriter thread.

There is no obvious deadlock to me here; the problem is that the MiMappedPageWriter is waiting on objects that presumably never get signaled. But I have a very superficial understanding of the Mm, so I may be missing something obvious to the experts in this forum.

The !locks dump follows. More information can be found in this GitHub issue comment. I am happy to provide additional information if requested.

lkd> !locks -v 0xffffac8c5e966870    

Resource @ 0xffffac8c5e966870    Exclusively owned
    Contention Count = 40
    NumberOfSharedWaiters = 1
    Threads: ffffac8c5bc73040-05<*> 

    THREAD ffffac8c5bc73040  Cid 0004.00e8  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (WrFreePage) KernelMode Non-Alertable
        fffff803549a5ec8  SynchronizationEvent
        fffff803549a5ee0  SynchronizationEvent
        fffff803549a5ef8  SynchronizationEvent
        fffff803549a5f10  SynchronizationEvent
        fffff803549a5f28  SynchronizationEvent
        fffff803549a5f40  SynchronizationEvent
        fffff803549a5f58  SynchronizationEvent
        fffff803549a5f70  SynchronizationEvent
        fffff803549a5f88  SynchronizationEvent
        fffff803549a5fa0  SynchronizationEvent
        fffff803549a5fb8  SynchronizationEvent
        fffff803549a5fd0  SynchronizationEvent
        fffff803549a5fe8  SynchronizationEvent
        fffff803549a6000  SynchronizationEvent
        fffff803549a6018  SynchronizationEvent
        fffff803549a6030  SynchronizationEvent
        fffff803549a50d0  NotificationEvent
        fffff803549a5310  SynchronizationEvent
    Not impersonating
    DeviceMap                 ffff8781e1616b50
    Owning Process            ffffac8c5aa21040       Image:         System
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      26619          Ticks: 112399 (0:00:29:16.234)
    Context Switch Count      3945           IdealProcessor: 0             
    UserTime                  00:00:00.000
    KernelTime                00:00:00.187
    Win32 Start Address nt!MiMappedPageWriter (0xfffff803547b4ca8)
    Stack Init ffff99814b2f6c90 Current ffff99814b2f6400
    Base ffff99814b2f7000 Limit ffff99814b2f1000 Call 0
    Priority 18 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
GetContextState failed, 0x80004001
Unable to get current machine context, HRESULT 0x80004001
    Child-SP          RetAddr           Call Site
    ffff9981`4b2f6440 fffff803`546c046c nt!KiSwapContext+0x76
    ffff9981`4b2f6580 fffff803`546bff0f nt!KiSwapThread+0x17c
    ffff9981`4b2f6630 fffff803`546bf5ce nt!KiCommitThreadWait+0x14f
    ffff9981`4b2f66d0 fffff803`547b4e9c nt!KeWaitForMultipleObjects+0x1fe
    ffff9981`4b2f67b0 fffff803`5473d2d5 nt!MiMappedPageWriter+0x1f4
    ffff9981`4b2f6c10 fffff803`547dac86 nt!PspSystemThreadStartup+0x41
    ffff9981`4b2f6c60 00000000`00000000 nt!KiStartSystemThread+0x16

ffffac8c5e401080-01    

    THREAD ffffac8c5e401080  Cid 13cc.0828  Teb: 000000e0d760f000 Win32Thread: ffffac8c5bdda8c0 WAIT: (WrResource) KernelMode Non-Alertable
        ffff99814c7727a0  SynchronizationEvent
    IRP List:
        ffffac8c5d9b9330: (0006,0118) Flags: 00060000  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffff8781ecd40dd0
    Owning Process            ffffac8c5df53080       Image:         3dsmax.exe
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      138956         Ticks: 116 (0:00:00:01.812)
    Context Switch Count      122463         IdealProcessor: 1             
    UserTime                  00:00:39.984
    KernelTime                00:00:09.593
    Win32 Start Address 0x00007ff6191736d0
    Stack Init ffff99814c772fd0 Current ffff99814c7723c0
    Base ffff99814c773000 Limit ffff99814c76d000 Call 0
    Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
GetContextState failed, 0x80004001
Unable to get current machine context, HRESULT 0x80004001
    Child-SP          RetAddr           Call Site
    ffff9981`4c772400 fffff803`546c046c nt!KiSwapContext+0x76
    ffff9981`4c772540 fffff803`546bff0f nt!KiSwapThread+0x17c
    ffff9981`4c7725f0 fffff803`546c21b8 nt!KiCommitThreadWait+0x14f
    ffff9981`4c772690 fffff803`546f6a95 nt!ExpWaitForResource+0x2a8
    ffff9981`4c772760 fffff801`7064f55c nt!ExAcquireResourceSharedLite+0x365
    ffff9981`4c7727f0 fffff801`7065229c winfsp_x64!FspFileNodeAcquireSharedF+0x6c
    ffff9981`4c772820 fffff801`70653e71 winfsp_x64!FspFsvolQueryInformation+0x230
    ffff9981`4c772920 fffff801`6c005206 winfsp_x64!FspQueryInformation+0xb1
    ffff9981`4c772980 fffff801`6c003146 FLTMGR!FltpLegacyProcessingAfterPreCallbacksCompleted+0x1a6
    ffff9981`4c772a10 fffff803`54a986a6 FLTMGR!FltpDispatch+0xb6
    ffff9981`4c772a70 fffff803`54ac3085 nt!FsRtlGetFileSize+0x14e
    ffff9981`4c772b20 fffff803`54aa54cc nt!MmExtendSection+0x275
    ffff9981`4c772b80 fffff803`54aa4630 nt!MiAllocateVirtualMemory+0xe8c
    ffff9981`4c772d70 fffff803`547e0493 nt!NtAllocateVirtualMemory+0x40
    ffff9981`4c772dd0 00007ff8`96dc63d4 nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffff9981`4c772e40)
    000000e0`d78f9af8 00000000`00000000 ntdll!NtAllocateVirtualMemory+0x14

1 total locks, 1 locks currently held

The mapped page writer acquired your lock exclusively five times, which I would guess means you’ve seen (at least) five paging writes to this file. I would look to see if you have any paging writes hanging out waiting to be completed OR if there’s a path in your paging write handler that grabs this lock and fails to release it.