[FASTFAT] Only initialize directory cache on use.
[reactos.git] / drivers / filesystems / fastfat / flush.c
index 76a3c5d..ebf1925 100644 (file)
 
 /* INCLUDES *****************************************************************/
 
-#define NDEBUG
 #include "vfat.h"
 
+#define NDEBUG
+#include <debug.h>
+
 /* FUNCTIONS ****************************************************************/
 
-static NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
+static
+NTSTATUS
+VfatFlushFile(
+    PDEVICE_EXTENSION DeviceExt,
+    PVFATFCB Fcb)
 {
-   IO_STATUS_BLOCK IoStatus;
-   NTSTATUS Status;
-
-   DPRINT("VfatFlushFile(DeviceExt %p, Fcb %p) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);
-
-   CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
-   if (IoStatus.Status == STATUS_INVALID_PARAMETER)
-   {
-      /* FIXME: Caching was possible not initialized */
-      IoStatus.Status = STATUS_SUCCESS;
-   }
-   if (Fcb->Flags & FCB_IS_DIRTY)
-     {
-       Status = VfatUpdateEntry(Fcb);
-       if (!NT_SUCCESS(Status))
-         {
-          IoStatus.Status = Status;
-        }
-     }
-   return IoStatus.Status;
+    IO_STATUS_BLOCK IoStatus;
+    NTSTATUS Status;
+
+    DPRINT("VfatFlushFile(DeviceExt %p, Fcb %p) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);
+
+    CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
+    if (IoStatus.Status == STATUS_INVALID_PARAMETER)
+    {
+        /* FIXME: Caching was possible not initialized */
+        IoStatus.Status = STATUS_SUCCESS;
+    }
+
+    if (BooleanFlagOn(Fcb->Flags, FCB_IS_DIRTY))
+    {
+        Status = VfatUpdateEntry(DeviceExt, Fcb);
+        if (!NT_SUCCESS(Status))
+        {
+            IoStatus.Status = Status;
+        }
+    }
+    return IoStatus.Status;
 }
 
-NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
+NTSTATUS
+VfatFlushVolume(
+    PDEVICE_EXTENSION DeviceExt,
+    PVFATFCB VolumeFcb)
 {
-   PLIST_ENTRY ListEntry;
-   PVFATFCB Fcb;
-   NTSTATUS Status, ReturnStatus = STATUS_SUCCESS;
-
-   DPRINT("VfatFlushVolume(DeviceExt %p, FatFcb %p)\n", DeviceExt, VolumeFcb);
-
-   ListEntry = DeviceExt->FcbListHead.Flink;
-   while (ListEntry != &DeviceExt->FcbListHead)
-     {
-       Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
-       ListEntry = ListEntry->Flink;
-       if (!vfatFCBIsDirectory(Fcb))
-         {
-           ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
-           Status = VfatFlushFile(DeviceExt, Fcb);
-           ExReleaseResourceLite (&Fcb->MainResource);
-           if (!NT_SUCCESS(Status))
-             {
-               DPRINT1("VfatFlushFile failed, status = %x\n", Status);
-              ReturnStatus = Status;
-             }
-        }
-       /* FIXME: Stop flushing if this is a removable media and the media was removed */
-     }
-   ListEntry = DeviceExt->FcbListHead.Flink;
-   while (ListEntry != &DeviceExt->FcbListHead)
-     {
-       Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
-       ListEntry = ListEntry->Flink;
-       if (vfatFCBIsDirectory(Fcb))
-         {
-           ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
-           Status = VfatFlushFile(DeviceExt, Fcb);
-           ExReleaseResourceLite (&Fcb->MainResource);
-           if (!NT_SUCCESS(Status))
-             {
-               DPRINT1("VfatFlushFile failed, status = %x\n", Status);
-              ReturnStatus = Status;
-             }
-        }
-       /* FIXME: Stop flushing if this is a removable media and the media was removed */
-     }
-
-   Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext;
-
-   ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
-   Status = VfatFlushFile(DeviceExt, Fcb);
-   ExReleaseResourceLite(&DeviceExt->FatResource);
-
-   /* FIXME: Flush the buffers from storage device */
-
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT1("VfatFlushFile failed, status = %x\n", Status);
-      ReturnStatus = Status;
-   }
-
-   return ReturnStatus;
+    PLIST_ENTRY ListEntry;
+    PVFATFCB Fcb;
+    NTSTATUS Status, ReturnStatus = STATUS_SUCCESS;
+    PIRP Irp;
+    KEVENT Event;
+    IO_STATUS_BLOCK IoStatusBlock;
+
+    DPRINT("VfatFlushVolume(DeviceExt %p, FatFcb %p)\n", DeviceExt, VolumeFcb);
+
+    ListEntry = DeviceExt->FcbListHead.Flink;
+    while (ListEntry != &DeviceExt->FcbListHead)
+    {
+        Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
+        ListEntry = ListEntry->Flink;
+        if (!vfatFCBIsDirectory(Fcb))
+        {
+            ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+            Status = VfatFlushFile(DeviceExt, Fcb);
+            ExReleaseResourceLite (&Fcb->MainResource);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("VfatFlushFile failed, status = %x\n", Status);
+                ReturnStatus = Status;
+            }
+        }
+        /* FIXME: Stop flushing if this is a removable media and the media was removed */
+    }
+
+    ListEntry = DeviceExt->FcbListHead.Flink;
+    while (ListEntry != &DeviceExt->FcbListHead)
+    {
+        Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
+        ListEntry = ListEntry->Flink;
+        if (vfatFCBIsDirectory(Fcb))
+        {
+            ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+            Status = VfatFlushFile(DeviceExt, Fcb);
+            ExReleaseResourceLite (&Fcb->MainResource);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("VfatFlushFile failed, status = %x\n", Status);
+                ReturnStatus = Status;
+            }
+        }
+        /* FIXME: Stop flushing if this is a removable media and the media was removed */
+    }
+
+    Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext;
+
+    ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
+    Status = VfatFlushFile(DeviceExt, Fcb);
+    ExReleaseResourceLite(&DeviceExt->FatResource);
+
+    /* Prepare an IRP to flush device buffers */
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
+                                       DeviceExt->StorageDevice,
+                                       NULL, 0, NULL, &Event,
+                                       &IoStatusBlock);
+    if (Irp != NULL)
+    {
+        KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+        Status = IoCallDriver(DeviceExt->StorageDevice, Irp);
+        if (Status == STATUS_PENDING)
+        {
+            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            Status = IoStatusBlock.Status;
+        }
+
+        /* Ignore device not supporting flush operation */
+        if (Status == STATUS_INVALID_DEVICE_REQUEST)
+        {
+            DPRINT1("Flush not supported, ignored\n");
+            Status = STATUS_SUCCESS;
+
+        }
+    }
+    else
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("VfatFlushFile failed, status = %x\n", Status);
+        ReturnStatus = Status;
+    }
+
+    return ReturnStatus;
 }
 
-NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext)
+NTSTATUS
+VfatFlush(
+    PVFAT_IRP_CONTEXT IrpContext)
 {
-  NTSTATUS Status;
-  PVFATFCB Fcb;
-  /*
-   * This request is not allowed on the main device object.
-   */
-  if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
-  {
-     Status = STATUS_INVALID_DEVICE_REQUEST;
-     goto ByeBye;
-  }
-
-  Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
-  ASSERT(Fcb);
-
-  if (Fcb->Flags & FCB_IS_VOLUME)
-  {
-     ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
-     Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb);
-     ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
-  }
-  else
-  {
-     ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
-     Status = VfatFlushFile(IrpContext->DeviceExt, Fcb);
-     ExReleaseResourceLite (&Fcb->MainResource);
-  }
-
-ByeBye:
-  IrpContext->Irp->IoStatus.Status = Status;
-  IrpContext->Irp->IoStatus.Information = 0;
-  IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
-  VfatFreeIrpContext(IrpContext);
-
-  return (Status);
+    NTSTATUS Status;
+    PVFATFCB Fcb;
+
+    /* This request is not allowed on the main device object. */
+    if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
+    {
+        IrpContext->Irp->IoStatus.Information = 0;
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+
+    Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
+    ASSERT(Fcb);
+
+    if (BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME))
+    {
+        ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
+        Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb);
+        ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
+    }
+    else
+    {
+        ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+        Status = VfatFlushFile(IrpContext->DeviceExt, Fcb);
+        ExReleaseResourceLite (&Fcb->MainResource);
+    }
+
+    IrpContext->Irp->IoStatus.Information = 0;
+    return Status;
 }
 
 /* EOF */