xref: /reactos/drivers/filesystems/fastfat/flush.c (revision 234f89c0)
1 /*
2  * COPYRIGHT:        See COPYING in the top level directory
3  * PROJECT:          ReactOS kernel
4  * FILE:             drivers/fs/vfat/flush.c
5  * PURPOSE:          VFAT Filesystem
6  * PROGRAMMER:
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include "vfat.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS ****************************************************************/
17 
18 static
19 NTSTATUS
20 VfatFlushFile(
21     PDEVICE_EXTENSION DeviceExt,
22     PVFATFCB Fcb)
23 {
24     IO_STATUS_BLOCK IoStatus;
25     NTSTATUS Status;
26 
27     DPRINT("VfatFlushFile(DeviceExt %p, Fcb %p) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);
28 
29     CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
30     if (IoStatus.Status == STATUS_INVALID_PARAMETER)
31     {
32         /* FIXME: Caching was possible not initialized */
33         IoStatus.Status = STATUS_SUCCESS;
34     }
35 
36     if (BooleanFlagOn(Fcb->Flags, FCB_IS_DIRTY))
37     {
38         Status = VfatUpdateEntry(DeviceExt, Fcb);
39         if (!NT_SUCCESS(Status))
40         {
41             IoStatus.Status = Status;
42         }
43     }
44     return IoStatus.Status;
45 }
46 
47 NTSTATUS
48 VfatFlushVolume(
49     PDEVICE_EXTENSION DeviceExt,
50     PVFATFCB VolumeFcb)
51 {
52     PLIST_ENTRY ListEntry;
53     PVFATFCB Fcb;
54     NTSTATUS Status, ReturnStatus = STATUS_SUCCESS;
55     PIRP Irp;
56     KEVENT Event;
57     IO_STATUS_BLOCK IoStatusBlock;
58 
59     DPRINT("VfatFlushVolume(DeviceExt %p, FatFcb %p)\n", DeviceExt, VolumeFcb);
60 
61     ListEntry = DeviceExt->FcbListHead.Flink;
62     while (ListEntry != &DeviceExt->FcbListHead)
63     {
64         Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
65         ListEntry = ListEntry->Flink;
66         if (!vfatFCBIsDirectory(Fcb))
67         {
68             ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
69             Status = VfatFlushFile(DeviceExt, Fcb);
70             ExReleaseResourceLite (&Fcb->MainResource);
71             if (!NT_SUCCESS(Status))
72             {
73                 DPRINT1("VfatFlushFile failed, status = %x\n", Status);
74                 ReturnStatus = Status;
75             }
76         }
77         /* FIXME: Stop flushing if this is a removable media and the media was removed */
78     }
79 
80     ListEntry = DeviceExt->FcbListHead.Flink;
81     while (ListEntry != &DeviceExt->FcbListHead)
82     {
83         Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
84         ListEntry = ListEntry->Flink;
85         if (vfatFCBIsDirectory(Fcb))
86         {
87             ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
88             Status = VfatFlushFile(DeviceExt, Fcb);
89             ExReleaseResourceLite (&Fcb->MainResource);
90             if (!NT_SUCCESS(Status))
91             {
92                 DPRINT1("VfatFlushFile failed, status = %x\n", Status);
93                 ReturnStatus = Status;
94             }
95         }
96         /* FIXME: Stop flushing if this is a removable media and the media was removed */
97     }
98 
99     Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext;
100 
101     ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
102     Status = VfatFlushFile(DeviceExt, Fcb);
103     ExReleaseResourceLite(&DeviceExt->FatResource);
104 
105     /* Prepare an IRP to flush device buffers */
106     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
107                                        DeviceExt->StorageDevice,
108                                        NULL, 0, NULL, &Event,
109                                        &IoStatusBlock);
110     if (Irp != NULL)
111     {
112         KeInitializeEvent(&Event, NotificationEvent, FALSE);
113 
114         Status = IoCallDriver(DeviceExt->StorageDevice, Irp);
115         if (Status == STATUS_PENDING)
116         {
117             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
118             Status = IoStatusBlock.Status;
119         }
120 
121         /* Ignore device not supporting flush operation */
122         if (Status == STATUS_INVALID_DEVICE_REQUEST)
123         {
124             DPRINT1("Flush not supported, ignored\n");
125             Status = STATUS_SUCCESS;
126 
127         }
128     }
129     else
130     {
131         Status = STATUS_INSUFFICIENT_RESOURCES;
132     }
133 
134     if (!NT_SUCCESS(Status))
135     {
136         DPRINT1("VfatFlushFile failed, status = %x\n", Status);
137         ReturnStatus = Status;
138     }
139 
140     return ReturnStatus;
141 }
142 
143 NTSTATUS
144 VfatFlush(
145     PVFAT_IRP_CONTEXT IrpContext)
146 {
147     NTSTATUS Status;
148     PVFATFCB Fcb;
149 
150     /* This request is not allowed on the main device object. */
151     if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
152     {
153         IrpContext->Irp->IoStatus.Information = 0;
154         return STATUS_INVALID_DEVICE_REQUEST;
155     }
156 
157     Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
158     ASSERT(Fcb);
159 
160     if (BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME))
161     {
162         ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
163         Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb);
164         ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
165     }
166     else
167     {
168         ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
169         Status = VfatFlushFile(IrpContext->DeviceExt, Fcb);
170         ExReleaseResourceLite (&Fcb->MainResource);
171     }
172 
173     IrpContext->Irp->IoStatus.Information = 0;
174     return Status;
175 }
176 
177 /* EOF */
178