[FASTFAT] Only initialize directory cache on use.
[reactos.git] / drivers / filesystems / fastfat / flush.c
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 */