[CRT] Massively improve performance of rand_s
[reactos.git] / drivers / filesystems / reiserfs / src / flush.c
1 /*
2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
4 * FILE: flush.c
5 * PURPOSE:
6 * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
7 * HOMEPAGE:
8 * UPDATE HISTORY:
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include "rfsd.h"
14
15 /* GLOBALS ***************************************************************/
16
17 extern PRFSD_GLOBAL RfsdGlobal;
18
19 /* DEFINITIONS *************************************************************/
20
21 #ifdef ALLOC_PRAGMA
22 #pragma alloc_text(PAGE, RfsdFlushFile)
23 #pragma alloc_text(PAGE, RfsdFlushFiles)
24 #pragma alloc_text(PAGE, RfsdFlushVolume)
25 #pragma alloc_text(PAGE, RfsdFlush)
26 #endif
27
28 #ifdef _PREFAST_
29 IO_COMPLETION_ROUTINE RfsdFlushCompletionRoutine;
30 #endif // _PREFAST_
31
32 NTSTATUS NTAPI
33 RfsdFlushCompletionRoutine (
34 IN PDEVICE_OBJECT DeviceObject,
35 IN PIRP Irp,
36 IN PVOID Contxt )
37
38 {
39 if (Irp->PendingReturned)
40 IoMarkIrpPending( Irp );
41
42
43 if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
44 Irp->IoStatus.Status = STATUS_SUCCESS;
45
46 return STATUS_SUCCESS;
47 }
48
49 __drv_mustHoldCriticalRegion
50 NTSTATUS
51 RfsdFlushFiles (IN PRFSD_VCB Vcb, BOOLEAN bShutDown)
52 {
53 IO_STATUS_BLOCK IoStatus;
54 PRFSD_FCB Fcb;
55 PLIST_ENTRY ListEntry;
56
57 PAGED_CODE();
58
59 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
60 IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
61 return STATUS_SUCCESS;
62 }
63
64 RfsdPrint((DBG_INFO, "Flushing Files ...\n"));
65
66 // Flush all Fcbs in Vcb list queue.
67 {
68 for (ListEntry = Vcb->FcbList.Flink;
69 ListEntry != &Vcb->FcbList;
70 ListEntry = ListEntry->Flink ) {
71
72 Fcb = CONTAINING_RECORD(ListEntry, RFSD_FCB, Next);
73
74 if (ExAcquireResourceExclusiveLite(
75 &Fcb->MainResource,
76 TRUE )) {
77
78 IoStatus.Status = RfsdFlushFile(Fcb);
79 /*
80 if (bShutDown)
81 IoStatus.Status = RfsdPurgeFile(Fcb, TRUE);
82 else
83 IoStatus.Status = RfsdFlushFile(Fcb);
84 */
85 ExReleaseResourceForThreadLite(
86 &Fcb->MainResource,
87 ExGetCurrentResourceThread());
88 }
89 }
90 }
91
92 return IoStatus.Status;
93 }
94
95 __drv_mustHoldCriticalRegion
96 NTSTATUS
97 RfsdFlushVolume (IN PRFSD_VCB Vcb, BOOLEAN bShutDown)
98 {
99 IO_STATUS_BLOCK IoStatus;
100
101 PAGED_CODE();
102
103 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
104 IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
105 return STATUS_SUCCESS;
106 }
107
108 RfsdPrint((DBG_INFO, "RfsdFlushVolume: Flushing Vcb ...\n"));
109
110 ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
111 ExReleaseResourceLite(&Vcb->PagingIoResource);
112
113 CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
114
115 return IoStatus.Status;
116 }
117
118 NTSTATUS
119 RfsdFlushFile (IN PRFSD_FCB Fcb)
120 {
121 IO_STATUS_BLOCK IoStatus;
122
123 PAGED_CODE();
124
125 ASSERT(Fcb != NULL);
126
127 ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
128 (Fcb->Identifier.Size == sizeof(RFSD_FCB)));
129
130 if (IsDirectory(Fcb))
131 return STATUS_SUCCESS;
132
133 RfsdPrint((DBG_INFO, "RfsdFlushFile: Flushing File Key=%x,%xh %S ...\n",
134 Fcb->RfsdMcb->Key.k_dir_id, Fcb->RfsdMcb->Key.k_objectid, Fcb->RfsdMcb->ShortName.Buffer));
135 /*
136 {
137 ULONG ResShCnt, ResExCnt;
138 ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
139 ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);
140
141 RfsdPrint((DBG_INFO, "RfsdFlushFile: PagingIoRes: %xh:%xh\n", ResShCnt, ResExCnt));
142 }
143 */
144 CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
145
146 ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
147
148 return IoStatus.Status;
149 }
150
151 __drv_mustHoldCriticalRegion
152 NTSTATUS
153 RfsdFlush (IN PRFSD_IRP_CONTEXT IrpContext)
154 {
155 NTSTATUS Status;
156
157 PIRP Irp;
158 PIO_STACK_LOCATION IrpSp;
159
160 PRFSD_VCB Vcb = 0;
161 PRFSD_FCBVCB FcbOrVcb = 0;
162 PFILE_OBJECT FileObject;
163
164 PDEVICE_OBJECT DeviceObject;
165
166 BOOLEAN MainResourceAcquired = FALSE;
167
168 PAGED_CODE();
169
170 _SEH2_TRY {
171
172 ASSERT(IrpContext);
173
174 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
175 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
176
177 DeviceObject = IrpContext->DeviceObject;
178
179 //
180 // This request is not allowed on the main device object
181 //
182 if (DeviceObject == RfsdGlobal->DeviceObject) {
183 Status = STATUS_INVALID_DEVICE_REQUEST;
184 _SEH2_LEAVE;
185 }
186
187 Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
188
189 ASSERT(Vcb != NULL);
190
191 ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
192 (Vcb->Identifier.Size == sizeof(RFSD_VCB)));
193
194 ASSERT(IsMounted(Vcb));
195
196 if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
197 IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
198 Status = STATUS_SUCCESS;
199 _SEH2_LEAVE;
200 }
201
202 Irp = IrpContext->Irp;
203
204 IrpSp = IoGetCurrentIrpStackLocation(Irp);
205
206 FileObject = IrpContext->FileObject;
207
208 FcbOrVcb = (PRFSD_FCBVCB) FileObject->FsContext;
209
210 ASSERT(FcbOrVcb != NULL);
211
212 #ifdef _MSC_VER
213 #pragma prefast( suppress: 28137, "by design" )
214 #endif
215 if (!ExAcquireResourceExclusiveLite(
216 &FcbOrVcb->MainResource,
217 IrpContext->IsSynchronous )) {
218 Status = STATUS_PENDING;
219 _SEH2_LEAVE;
220 }
221
222 MainResourceAcquired = TRUE;
223
224 if (FcbOrVcb->Identifier.Type == RFSDVCB) {
225
226 Status = RfsdFlushFiles((PRFSD_VCB)(FcbOrVcb), FALSE);
227
228 if (NT_SUCCESS(Status)) {
229 _SEH2_LEAVE;
230 }
231
232 Status = RfsdFlushVolume((PRFSD_VCB)(FcbOrVcb), FALSE);
233
234 if (NT_SUCCESS(Status) && IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED)) {
235 ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
236 }
237
238 } else if (FcbOrVcb->Identifier.Type == RFSDFCB) {
239
240 Status = RfsdFlushFile((PRFSD_FCB)(FcbOrVcb));
241
242 if (NT_SUCCESS(Status) && IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
243 ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
244 }
245 }
246
247 } _SEH2_FINALLY {
248
249 if (MainResourceAcquired) {
250 ExReleaseResourceForThreadLite(
251 &FcbOrVcb->MainResource,
252 ExGetCurrentResourceThread() );
253 }
254
255 if (!IrpContext->ExceptionInProgress) {
256
257 if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
258
259 // Call the disk driver to flush the physial media.
260 NTSTATUS DriverStatus;
261 PIO_STACK_LOCATION IrpSp;
262 PIO_STACK_LOCATION NextIrpSp;
263
264 IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
265 NextIrpSp = IoGetNextIrpStackLocation(IrpContext->Irp);
266
267 *NextIrpSp = *IrpSp;
268
269 IoSetCompletionRoutine( IrpContext->Irp,
270 RfsdFlushCompletionRoutine,
271 NULL,
272 TRUE,
273 TRUE,
274 TRUE );
275
276 DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
277
278 Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
279 Status : DriverStatus;
280
281 IrpContext->Irp = Irp = NULL;
282 }
283
284 RfsdCompleteIrpContext(IrpContext, Status);
285 }
286 } _SEH2_END;
287
288 return Status;
289 }