From c1bbc436cbdb343afc34fa08a8f27db7ae9416d8 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sat, 1 Nov 2014 20:19:52 +0000 Subject: [PATCH] [FASTFAT] Implement some kind of volume dismount in FastFAT (ie, implement VfatDismountVolume()) This is not fully perfect situation, but it does most of the job (+ leaking a few things). So far, this is not dramatic as its main use is for 1st stage. This will have to be improved later on. CORE-8732 #comment Can you retest please? svn path=/trunk/; revision=65173 --- reactos/drivers/filesystems/fastfat/fsctl.c | 63 ++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/reactos/drivers/filesystems/fastfat/fsctl.c b/reactos/drivers/filesystems/fastfat/fsctl.c index 19f97854ea8..dae7b3591b4 100644 --- a/reactos/drivers/filesystems/fastfat/fsctl.c +++ b/reactos/drivers/filesystems/fastfat/fsctl.c @@ -909,18 +909,77 @@ VfatDismountVolume( PVFAT_IRP_CONTEXT IrpContext) { PDEVICE_EXTENSION DeviceExt; + PLIST_ENTRY NextEntry; + PVFATFCB Fcb; DPRINT1("VfatDismountVolume(%p)\n", IrpContext); DeviceExt = IrpContext->DeviceExt; + /* We HAVE to be locked. Windows also allows dismount with no lock + * but we're here mainly for 1st stage, so KISS + */ if (!(DeviceExt->Flags & VCB_VOLUME_LOCKED)) { return STATUS_ACCESS_DENIED; } - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + /* Race condition? */ + if (DeviceExt->Flags & VCB_DISMOUNT_PENDING) + { + return STATUS_VOLUME_DISMOUNTED; + } + + /* Notify we'll dismount. Pass that point there's no reason we fail */ + FsRtlNotifyVolumeEvent(IrpContext->Stack->FileObject, FSRTL_VOLUME_DISMOUNT); + + ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE); + + /* Browse all the available FCBs first, and force data writing to disk */ + for (NextEntry = DeviceExt->FcbListHead.Flink; + NextEntry != &DeviceExt->FcbListHead; + NextEntry = NextEntry->Flink) + { + Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry); + + ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); + ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE); + + if (Fcb->FileObject) + { + if (Fcb->Flags & FCB_IS_DIRTY) + { + VfatUpdateEntry(Fcb); + } + + CcPurgeCacheSection(Fcb->FileObject->SectionObjectPointer, NULL, 0, FALSE); + CcUninitializeCacheMap(Fcb->FileObject, &Fcb->RFCB.FileSize, NULL); + } + + ExReleaseResourceLite(&Fcb->PagingIoResource); + ExReleaseResourceLite(&Fcb->MainResource); + } + + /* Rebrowse the FCB in order to free them now */ + while (!IsListEmpty(&DeviceExt->FcbListHead)) + { + NextEntry = RemoveHeadList(&DeviceExt->FcbListHead); + Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry); + vfatDestroyFCB(Fcb); + } + + /* Mark we're being dismounted */ + DeviceExt->Flags |= VCB_DISMOUNT_PENDING; + IrpContext->DeviceObject->Vpb->Flags &= ~VPB_MOUNTED; + + ExReleaseResourceLite(&DeviceExt->FatResource); + + /* Release a few resources and quit, we're done */ + ExDeleteResourceLite(&DeviceExt->DirResource); + ExDeleteResourceLite(&DeviceExt->FatResource); + ObDereferenceObject(DeviceExt->FATFileObject); + + return STATUS_SUCCESS; } /* -- 2.17.1