crash handling FSCTL_INVALIDATE_VOLUMES after surprise USB disk removal

Hi everyone,

Can anybody suggest where I might go with this?

I am implementing FSCTRL_INVALIDATE_VOLUMES for my on-disk filesystem
and have managed to handle every case I can think of except the trivial
one. I mean, I can handle forced dismounts from surprise disk removals
(from e.g. unplugging USB disks) when there ARE open handles, but I've
got a problem when there are NO open files on it. (I'd have thought
would be simpler, but I've definitely messed something up.)

If during INVALIDATE_VOLUMES handling I swap the RealDevice VPB and free
the old one (a la FASTFAT AFAICT), I get a crash like this:

*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

DRIVER_VERIFIER_IOMANAGER_VIOLATION (c9)
The IO manager has caught a misbehaving driver.
Arguments:
Arg1: 0000000000000004, Invalid Device object passed to IoCallDriver
Arg2: fffffa8000d42d68, the Device object
Arg3: 0000000000000000
Arg4: 0000000000000000

Debugging Details:

BUGCHECK_STR: 0xc9_4

DRIVER_VERIFIER_IO_VIOLATION_TYPE: 4

DEVICE_OBJECT: fffffa8000d42d68

DRIVER_OBJECT: fffff8000179e928

IMAGE_NAME: hy

DEBUG_FLR_IMAGE_TIMESTAMP: 0

MODULE_NAME: hy

FAULTING_MODULE: 0000000000000000

DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT

PROCESS_NAME: System

CURRENT_IRQL: 2

LAST_CONTROL_TRANSFER: from fffff80001711502 to fffff800016616f0

STACK_TEXT:
fffffa6001784d68 fffff80001711502 : fffffa8000d44040 0000000000000065 0000000000000004 fffff800016a4210 : nt!RtlpBreakWithStatusInstruction
fffffa6001784d70 fffff800017122bb : 0000000000000003 0000000000000000 fffff800016a1aa0 00000000000000c9 : nt!KiBugCheckDebugBreak+0x12
fffffa6001784dd0 fffff80001667554 : 0000000000000001 0000000000000000 fffff80001a78440 fffff800016929fe : nt!KeBugCheck2+0x6eb
fffffa6001785440 fffff800016d0580 : 00000000000000c9 0000000000000004 fffffa8000d42d68 0000000000000000 : nt!KeBugCheckEx+0x104
fffffa6001785480 fffff80001a72476 : fffff98008966f30 fffff8000168c1c1 0000000000000000 fffffa80026dce20 : nt!VfBugCheckNoStackUsage+0x30
fffffa60017854c0 fffff800018d4084 : fffffa80026dce20 fffff98008966f30 fffff9800897eca0 fffffa80021a29f0 : nt!IovCallDriver+0x236
fffffa6001785500 fffff800018c96a0 : 0000000000000000 fffffa80026dce20 fffff88005a4cfd0 fffffa8000d4b000 : nt!IopCloseFile+0x184
fffffa6001785590 fffff800018d1287 : fffff88005a4cfd0 fffffa8000000001 fffffa8000cef110 0000000000000000 : nt!ObpDecrementHandleCount+0xc0
fffffa6001785620 fffff800018d1554 : fffff880000000d0 fffff88000000000 0000000000000000 00000000000007f4 : nt!ObpCloseHandleTableEntry+0xb7
fffffa60017856c0 fffff80001666ef3 : fffffa8000d44040 fffffa6001785790 0000000000000000 0000000000000000 : nt!ObpCloseHandle+0x94
fffffa6001785710 fffff80001667400 : fffff80001a3b8c8 0000000000000000 0000000000000000 fffffa6001785988 : nt!KiSystemServiceCopyEnd+0x13
fffffa60017858a8 fffff80001a3b8c8 : 0000000000000000 0000000000000000 fffffa6001785988 fffffa80021a29f0 : nt!KiServiceLinkage
fffffa60017858b0 fffff80001a40e5b : fffffa80026e7bd0 ffffffff800007f4 fffffa80026e7bd0 0000000000000017 : nt!IopInvalidateVolumesForDevice+0x278
fffffa6001785980 fffff80001a3d743 : fffffa80026e7950 fffffa80026e7950 000000000000030a 0000000000000308 : nt!IopRemoveDevice+0x15b
fffffa6001785a40 fffff80001a40937 : fffffa80026e7950 0000000000000000 0000000000000003 0000000072637050 : nt!PnpSurpriseRemoveLockedDeviceNode+0xe3
fffffa6001785a80 fffff80001a40a60 : 0000000000000000 fffffa80026e7900 fffff880060d6cd0 fffffa6001785bc8 : nt!PnpDeleteLockedDeviceNode+0x37
fffffa6001785ab0 fffff80001a44c08 : 0000000000000002 0000000000000000 0000000000000003 0000000000000000 : nt!PnpDeleteLockedDeviceNodes+0xa0
fffffa6001785b20 fffff80001a4574c : fffffa6001785cf8 0000000000000000 fffff8800656a200 fffffa8000000000 : nt!PnpProcessQueryRemoveAndEject+0x6d8
fffffa6001785c70 fffff800019447aa : 0000000000000001 fffffa80022930e0 fffff88006157950 000000004b706e50 : nt!PnpProcessTargetDeviceEvent+0x4c
fffffa6001785ca0 fffff8000166e8c3 : fffff800018647d8 fffff88006157950 fffff8000179e8f8 fffffa8000d44040 : nt! ?? ::NNGAKEGL::string'+0x4ffc7 fffffa6001785cf0 fffff80001871ec7 : fffffa80022930e0 0000000000000000 fffffa8000d44040 0000000000000080 : nt!ExpWorkerThread+0xfb fffffa6001785d50 fffff800016a4616 : fffff80001780680 fffffa8000d44040 fffffa8000d43720 fffffa8000d43818 : nt!PspSystemThreadStartup+0x57 fffffa6001785d80 0000000000000000 : 0000000000000000 0000000000000000 0000000000000000 00000000`00000000 : nt!KiStartSystemThread+0x16

STACK_COMMAND: kb

FOLLOWUP_NAME: MachineOwner

FAILURE_BUCKET_ID: X64_0xc9_4_VRF_IMAGE_hy

BUCKET_ID: X64_0xc9_4_VRF_IMAGE_hy

Followup: MachineOwner

If I leak the VPB then everything works fine.

AFAICT I should be able to free the original VPB, as at the time:

  • the Vpb->RealDevice no longer refers back to this VPB
  • the Vpb->ReferenceCount is 0
  • the filesystem has no open handles
  • the current INVALIDATE_VOLUMES is the only IRP being processed by
    the driver

I'd be very grateful for any ideas! In particular can anyone suggest
how to get more information about the handle argument to ObpCloseHandle()
and figure out how it leads to my VPB?

Thanks,

Jeff