Author: pschweitzer
Date: Sat Nov 1 20:19:52 2014
New Revision: 65173
URL:
http://svn.reactos.org/svn/reactos?rev=65173&view=rev
Log:
[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?
Modified:
trunk/reactos/drivers/filesystems/fastfat/fsctl.c
Modified: trunk/reactos/drivers/filesystems/fastfat/fsctl.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfa…
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat/fsctl.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat/fsctl.c [iso-8859-1] Sat Nov 1 20:19:52
2014
@@ -909,18 +909,77 @@
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;
}
/*