[NTFS]
[reactos.git] / drivers / filesystems / ffs / src / flush.c
1 /*
2 * FFS File System Driver for Windows
3 *
4 * flush.c
5 *
6 * 2004.5.6 ~
7 *
8 * Lee Jae-Hong, http://www.pyrasis.com
9 *
10 * See License.txt
11 *
12 */
13
14 #include "ntifs.h"
15 #include "ffsdrv.h"
16
17 /* Globals */
18
19 extern PFFS_GLOBAL FFSGlobal;
20
21
22 /* Definitions */
23
24 #ifdef ALLOC_PRAGMA
25 #pragma alloc_text(PAGE, FFSFlushFile)
26 #pragma alloc_text(PAGE, FFSFlushFiles)
27 #pragma alloc_text(PAGE, FFSFlushVolume)
28 #pragma alloc_text(PAGE, FFSFlush)
29 #endif
30
31 #ifdef _PREFAST_
32 IO_COMPLETION_ROUTINE FFSFlushCompletionRoutine;
33 #endif // _PREFAST_
34
35 NTSTATUS NTAPI
36 FFSFlushCompletionRoutine(
37 IN PDEVICE_OBJECT DeviceObject,
38 IN PIRP Irp,
39 IN PVOID Contxt)
40
41 {
42 if (Irp->PendingReturned)
43 IoMarkIrpPending(Irp);
44
45
46 if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
47 Irp->IoStatus.Status = STATUS_SUCCESS;
48
49 return STATUS_SUCCESS;
50 }
51
52 __drv_mustHoldCriticalRegion
53 NTSTATUS
54 FFSFlushFiles(
55 IN PFFS_VCB Vcb,
56 BOOLEAN bShutDown)
57 {
58 IO_STATUS_BLOCK IoStatus;
59
60 PFFS_FCB Fcb;
61 PLIST_ENTRY ListEntry;
62
63 PAGED_CODE();
64
65 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
66 IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
67 {
68 return STATUS_SUCCESS;
69 }
70
71 FFSPrint((DBG_INFO, "Flushing Files ...\n"));
72
73 // Flush all Fcbs in Vcb list queue.
74 {
75 for (ListEntry = Vcb->FcbList.Flink;
76 ListEntry != &Vcb->FcbList;
77 ListEntry = ListEntry->Flink)
78 {
79 Fcb = CONTAINING_RECORD(ListEntry, FFS_FCB, Next);
80
81 if (ExAcquireResourceExclusiveLite(
82 &Fcb->MainResource,
83 TRUE))
84 {
85 IoStatus.Status = FFSFlushFile(Fcb);
86 #if 0
87 /*
88 if (bShutDown)
89 IoStatus.Status = FFSPurgeFile(Fcb, TRUE);
90 else
91 IoStatus.Status = FFSFlushFile(Fcb);
92 */
93 #endif
94 ExReleaseResourceForThreadLite(
95 &Fcb->MainResource,
96 ExGetCurrentResourceThread());
97 }
98 }
99 }
100
101 return IoStatus.Status;
102 }
103
104
105 __drv_mustHoldCriticalRegion
106 NTSTATUS
107 FFSFlushVolume(
108 IN PFFS_VCB Vcb,
109 BOOLEAN bShutDown)
110 {
111 IO_STATUS_BLOCK IoStatus;
112
113 PAGED_CODE();
114
115 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
116 IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
117 {
118 return STATUS_SUCCESS;
119 }
120
121 FFSPrint((DBG_INFO, "FFSFlushVolume: Flushing Vcb ...\n"));
122
123 ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
124 ExReleaseResourceLite(&Vcb->PagingIoResource);
125
126 CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
127
128 return IoStatus.Status;
129 }
130
131
132 NTSTATUS
133 FFSFlushFile(
134 IN PFFS_FCB Fcb)
135 {
136 IO_STATUS_BLOCK IoStatus;
137
138 PAGED_CODE();
139
140 ASSERT(Fcb != NULL);
141
142 ASSERT((Fcb->Identifier.Type == FFSFCB) &&
143 (Fcb->Identifier.Size == sizeof(FFS_FCB)));
144
145 if (IsDirectory(Fcb))
146 return STATUS_SUCCESS;
147
148 FFSPrint((DBG_INFO, "FFSFlushFile: Flushing File Inode=%xh %S ...\n",
149 Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
150 /*
151 {
152 ULONG ResShCnt, ResExCnt;
153 ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
154 ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);
155
156 FFSPrint((DBG_INFO, "FFSFlushFile: PagingIoRes: %xh:%xh\n", ResShCnt, ResExCnt));
157 }
158 */
159 CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
160
161 ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
162
163 return IoStatus.Status;
164 }
165
166
167 __drv_mustHoldCriticalRegion
168 NTSTATUS
169 FFSFlush(
170 IN PFFS_IRP_CONTEXT IrpContext)
171 {
172 NTSTATUS Status;
173
174 PIRP Irp;
175 PIO_STACK_LOCATION IrpSp;
176
177 PFFS_VCB Vcb = 0;
178 PFFS_FCBVCB FcbOrVcb = 0;
179 PFILE_OBJECT FileObject;
180
181 PDEVICE_OBJECT DeviceObject;
182
183 BOOLEAN MainResourceAcquired = FALSE;
184
185 PAGED_CODE();
186
187 _SEH2_TRY
188 {
189 ASSERT(IrpContext);
190
191 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
192 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
193
194 DeviceObject = IrpContext->DeviceObject;
195
196 //
197 // This request is not allowed on the main device object
198 //
199 if (DeviceObject == FFSGlobal->DeviceObject)
200 {
201 Status = STATUS_INVALID_DEVICE_REQUEST;
202 _SEH2_LEAVE;
203 }
204
205 Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
206
207 ASSERT(Vcb != NULL);
208
209 ASSERT((Vcb->Identifier.Type == FFSVCB) &&
210 (Vcb->Identifier.Size == sizeof(FFS_VCB)));
211
212 ASSERT(IsMounted(Vcb));
213
214 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
215 IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
216 {
217 Status = STATUS_SUCCESS;
218 _SEH2_LEAVE;
219 }
220
221 Irp = IrpContext->Irp;
222
223 IrpSp = IoGetCurrentIrpStackLocation(Irp);
224
225 FileObject = IrpContext->FileObject;
226
227 FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;
228
229 ASSERT(FcbOrVcb != NULL);
230 #ifdef _MSC_VER
231 #pragma prefast( suppress: 28137, "by design" )
232 #endif
233 if (!ExAcquireResourceExclusiveLite(
234 &FcbOrVcb->MainResource,
235 IrpContext->IsSynchronous))
236 {
237 Status = STATUS_PENDING;
238 _SEH2_LEAVE;
239 }
240
241 MainResourceAcquired = TRUE;
242
243 if (FcbOrVcb->Identifier.Type == FFSVCB)
244 {
245 Status = FFSFlushFiles((PFFS_VCB)(FcbOrVcb), FALSE);
246
247 if (NT_SUCCESS(Status))
248 {
249 _SEH2_LEAVE;
250 }
251
252 Status = FFSFlushVolume((PFFS_VCB)(FcbOrVcb), FALSE);
253
254 if (NT_SUCCESS(Status) && IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED))
255 {
256 ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
257 }
258 }
259 else if (FcbOrVcb->Identifier.Type == FFSFCB)
260 {
261 Status = FFSFlushFile((PFFS_FCB)(FcbOrVcb));
262
263 if (NT_SUCCESS(Status) && IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED))
264 {
265 ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
266 }
267 }
268 }
269
270 _SEH2_FINALLY
271 {
272 if (MainResourceAcquired)
273 {
274 ExReleaseResourceForThreadLite(
275 &FcbOrVcb->MainResource,
276 ExGetCurrentResourceThread());
277 }
278
279 if (!IrpContext->ExceptionInProgress)
280 {
281 if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
282 {
283 // Call the disk driver to flush the physial media.
284 NTSTATUS DriverStatus;
285 PIO_STACK_LOCATION NextIrpSp;
286
287 IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
288 NextIrpSp = IoGetNextIrpStackLocation(IrpContext->Irp);
289
290 *NextIrpSp = *IrpSp;
291
292 IoSetCompletionRoutine(IrpContext->Irp,
293 FFSFlushCompletionRoutine,
294 NULL,
295 TRUE,
296 TRUE,
297 TRUE);
298
299 DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
300
301 Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
302 Status : DriverStatus;
303
304 IrpContext->Irp = NULL;
305 }
306
307 FFSCompleteIrpContext(IrpContext, Status);
308 }
309 } _SEH2_END;
310
311 return Status;
312 }