ReactOS  0.4.15-dev-509-g96a357b
flush.c File Reference
#include "fatprocs.h"
Include dependency graph for flush.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (FAT_BUG_CHECK_FLUSH)
 
#define Dbg   (DEBUG_TRACE_FLUSH)
 

Functions

NTSTATUS NTAPI FatFlushCompletionRoutine (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt)
 
NTSTATUS NTAPI FatHijackCompletionRoutine (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt)
 
 _Function_class_ (IRP_MJ_FLUSH_BUFFERS)
 
 _Requires_lock_held_ (_Global_critical_region_)
 
NTSTATUS FatFlushFat (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
 
NTSTATUS FatHijackIrpAndFlushDevice (IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PDEVICE_OBJECT TargetDeviceObject)
 
VOID FatFlushFatEntries (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG Cluster, IN ULONG Count)
 
VOID FatFlushDirentForFile (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
 
NTSTATUS NTAPI FatFlushCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Contxt)
 

Variables

IO_COMPLETION_ROUTINE FatFlushCompletionRoutine
 
IO_COMPLETION_ROUTINE FatHijackCompletionRoutine
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (FAT_BUG_CHECK_FLUSH)

Definition at line 23 of file flush.c.

◆ Dbg

#define Dbg   (DEBUG_TRACE_FLUSH)

Definition at line 29 of file flush.c.

Function Documentation

◆ _Function_class_()

_Function_class_ ( IRP_MJ_FLUSH_BUFFERS  )

Definition at line 68 of file flush.c.

96 {
98  PIRP_CONTEXT IrpContext = NULL;
99 
101 
102  PAGED_CODE();
103 
104  DebugTrace(+1, Dbg, "FatFsdFlushBuffers\n", 0);
105 
106  //
107  // Call the common Cleanup routine, with blocking allowed if synchronous
108  //
109 
111 
113 
114  _SEH2_TRY {
115 
116  IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
117 
118  Status = FatCommonFlushBuffers( IrpContext, Irp );
119 
121 
122  //
123  // We had some trouble trying to perform the requested
124  // operation, so we'll abort the I/O request with
125  // the error status that we get back from the
126  // execption code
127  //
128 
129  Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
130  } _SEH2_END;
131 
132  if (TopLevel) { IoSetTopLevelIrp( NULL ); }
133 
135 
136  //
137  // And return to our caller
138  //
139 
140  DebugTrace(-1, Dbg, "FatFsdFlushBuffers -> %08lx\n", Status);
141 
142  UNREFERENCED_PARAMETER( VolumeDeviceObject );
143 
144  return Status;
145 }
#define FsRtlEnterFileSystem
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
#define FsRtlExitFileSystem
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
LONG NTSTATUS
Definition: precomp.h:26
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
_SEH2_TRY
Definition: create.c:4226
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2410
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2289
#define Dbg
Definition: flush.c:29
#define CanFsdWait(I)
Definition: cdprocs.h:2001
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
Status
Definition: gdiplustypes.h:24
_SEH2_END
Definition: create.c:4400
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define PAGED_CODE()

◆ _Requires_lock_held_()

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 148 of file flush.c.

171 {
173 
175 
177 
179  PVCB Vcb;
180  PFCB Fcb;
181  PFCB NextFcb;
182  PCCB Ccb;
183 
184  BOOLEAN VcbAcquired = FALSE;
185  BOOLEAN FcbAcquired = FALSE;
186  BOOLEAN FatFlushRequired = FALSE;
187 
188  PAGED_CODE();
189 
191 
192  DebugTrace(+1, Dbg, "FatCommonFlushBuffers\n", 0);
193  DebugTrace( 0, Dbg, "Irp = %p\n", Irp);
194  DebugTrace( 0, Dbg, "->FileObject = %p\n", IrpSp->FileObject);
195 
196  //
197  // Extract and decode the file object
198  //
199 
202 
203  //
204  // CcFlushCache is always synchronous, so if we can't wait enqueue
205  // the irp to the Fsp.
206  //
207 
208  if ( !FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ) {
209 
210  Status = FatFsdPostRequest( IrpContext, Irp );
211 
212  DebugTrace(-1, Dbg, "FatCommonFlushBuffers -> %08lx\n", Status );
213  return Status;
214  }
215 
217 
218  _SEH2_TRY {
219 
220 #if (NTDDI_VERSION >= NTDDI_WIN8)
221 
223 
224  PETHREAD OriginatingThread = NULL;
225 
226  //
227  // Charge the flush to the originating thread.
228  // Try the Thread in Irp's tail first, if that is NULL, then charge
229  // the flush to current thread.
230  //
231 
232  if ((Irp->Tail.Overlay.Thread != NULL) &&
233  !IoIsSystemThread( Irp->Tail.Overlay.Thread )) {
234 
235  OriginatingThread = Irp->Tail.Overlay.Thread;
236 
237  } else {
238 
239  OriginatingThread = PsGetCurrentThread();
240  }
241 
242  NT_ASSERT( OriginatingThread != NULL );
243 
244  PsUpdateDiskCounters( PsGetThreadProcess( OriginatingThread ),
245  0,
246  0,
247  0,
248  0,
249  1 );
250  }
251 
252 #endif
253 
254  //
255  // Case on the type of open that we are trying to flush
256  //
257 
258  switch (TypeOfOpen) {
259 
260  case VirtualVolumeFile:
261  case EaFile:
262  case DirectoryFile:
263  DebugTrace(0, Dbg, "Flush that does nothing\n", 0);
264  break;
265 
266  case UserFileOpen:
267 
268  DebugTrace(0, Dbg, "Flush User File Open\n", 0);
269 
270  (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
271 
272  FcbAcquired = TRUE;
273 
274  FatVerifyFcb( IrpContext, Fcb );
275 
276  //
277  // If the file is cached then flush its cache
278  //
279 
280  Status = FatFlushFile( IrpContext, Fcb, Flush );
281 
282  //
283  // Also flush the file's dirent in the parent directory if the file
284  // flush worked.
285  //
286 
287  if (NT_SUCCESS( Status )) {
288 
289  //
290  // Insure that we get the filesize to disk correctly. This is
291  // benign if it was already good.
292  //
293 
295 
296 
297  FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
298 
300 
301  FatFlushRequired = TRUE;
302  }
303 
304  //
305  // Flush the parent Dcb's to get any dirent updates to disk.
306  //
307 
308  NextFcb = Fcb->ParentDcb;
309 
310  while (NextFcb != NULL) {
311 
312  //
313  // Make sure the Fcb is OK.
314  //
315 
316  _SEH2_TRY {
317 
318  FatVerifyFcb( IrpContext, NextFcb );
319 
322 
323  FatResetExceptionState( IrpContext );
324  } _SEH2_END;
325 
326  if (NextFcb->FcbCondition == FcbGood) {
327 
328  NTSTATUS LocalStatus;
329 
330  LocalStatus = FatFlushFile( IrpContext, NextFcb, Flush );
331 
332  if (!NT_SUCCESS(LocalStatus)) {
333 
334  Status = LocalStatus;
335  }
336 
337  if (FlagOn(NextFcb->FcbState, FCB_STATE_FLUSH_FAT)) {
338 
339  FatFlushRequired = TRUE;
340  }
341  }
342 
343  NextFcb = NextFcb->ParentDcb;
344  }
345 
346  //
347  // Flush the volume file to get any allocation information
348  // updates to disk.
349  //
350 
351  if (FatFlushRequired) {
352 
353  Status = FatFlushFat( IrpContext, Vcb );
354 
356  }
357 
358  //
359  // Set the write through bit so that these modifications
360  // will be completed with the request.
361  //
362 
363  SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
364  }
365 
366  break;
367 
368  case UserDirectoryOpen:
369 
370  //
371  // If the user had opened the root directory then we'll
372  // oblige by flushing the volume.
373  //
374 
375  if (NodeType(Fcb) != FAT_NTC_ROOT_DCB) {
376 
377  DebugTrace(0, Dbg, "Flush a directory does nothing\n", 0);
378  break;
379  }
380 
381  case UserVolumeOpen:
382 
383  DebugTrace(0, Dbg, "Flush User Volume Open, or root dcb\n", 0);
384 
385  //
386  // Acquire exclusive access to the Vcb.
387  //
388 
389  {
390  BOOLEAN Finished;
391 #ifdef _MSC_VER
392 #pragma prefast( suppress:28931, "needed for debug build" )
393 #endif
394  Finished = FatAcquireExclusiveVcb( IrpContext, Vcb );
395  NT_ASSERT( Finished );
396  }
397 
398  VcbAcquired = TRUE;
399 
400  //
401  // Mark the volume clean and then flush the volume file,
402  // and then all directories
403  //
404 
405  Status = FatFlushVolume( IrpContext, Vcb, Flush );
406 
407  //
408  // If the volume was dirty, do the processing that the delayed
409  // callback would have done.
410  //
411 
412  if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY)) {
413 
414  //
415  // Cancel any pending clean volumes.
416  //
417 
418  (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
419  (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );
420 
421  //
422  // The volume is now clean, note it.
423  //
424 
425  if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
426 
427  FatMarkVolume( IrpContext, Vcb, VolumeClean );
429  }
430 
431  //
432  // Unlock the volume if it is removable.
433  //
434 
435  if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
437 
438  FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
439  }
440  }
441 
442  break;
443 
444  default:
445 
446 #ifdef _MSC_VER
447 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
448 #endif
449  FatBugCheck( TypeOfOpen, 0, 0 );
450  }
451 
452  FatUnpinRepinnedBcbs( IrpContext );
453 
454  } _SEH2_FINALLY {
455 
456  DebugUnwind( FatCommonFlushBuffers );
457 
458  if (VcbAcquired) { FatReleaseVcb( IrpContext, Vcb ); }
459 
460  if (FcbAcquired) { FatReleaseFcb( IrpContext, Fcb ); }
461 
462  //
463  // If this is a normal termination then pass the request on
464  // to the target device object.
465  //
466 
467  if (!_SEH2_AbnormalTermination()) {
468 
469 #if (NTDDI_VERSION >= NTDDI_WIN8)
470  if ((IrpSp->MinorFunction != IRP_MN_FLUSH_DATA_ONLY) &&
471  (IrpSp->MinorFunction != IRP_MN_FLUSH_NO_SYNC)) {
472 #endif
473 
474  NTSTATUS DriverStatus;
475 
476  //
477  // Get the next stack location, and copy over the stack location
478  //
479 
481 
482  //
483  // Set up the completion routine
484  //
485 
488  ULongToPtr( Status ),
489  TRUE,
490  TRUE,
491  TRUE );
492 
493  //
494  // Send the request.
495  //
496 
497  DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
498 
499  if ((DriverStatus == STATUS_PENDING) ||
500  (!NT_SUCCESS(DriverStatus) &&
501  (DriverStatus != STATUS_INVALID_DEVICE_REQUEST))) {
502 
503  Status = DriverStatus;
504  }
505 
506  Irp = NULL;
507 
508 #if (NTDDI_VERSION >= NTDDI_WIN8)
509  }
510 #endif
511 
512  //
513  // Complete the Irp if necessary and return to the caller.
514  //
515 
516  FatCompleteRequest( IrpContext, Irp, Status );
517 
518  }
519 
520  DebugTrace(-1, Dbg, "FatCommonFlushBuffers -> %08lx\n", Status);
521  } _SEH2_END;
522 
523  return Status;
524 }
BOOLEAN NTAPI IoIsSystemThread(IN PETHREAD Thread)
Definition: util.c:115
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define VCB_STATE_FLAG_VOLUME_DIRTY
Definition: fatstruc.h:560
#define TRUE
Definition: types.h:120
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
#define ULongToPtr(ul)
Definition: basetsd.h:92
#define VCB_STATE_FLAG_MOUNTED_DIRTY
Definition: fatstruc.h:561
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2630
_In_ PIRP Irp
Definition: csq.h:116
Definition: cdstruc.h:908
LOGICAL FatDiskAccountingEnabled
Definition: fatdata.c:129
#define IRP_CONTEXT_FLAG_WRITE_THROUGH
Definition: ext2fs.h:1079
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
Definition: cdstruc.h:1073
#define FCB_STATE_FLUSH_FAT
Definition: fatstruc.h:1196
LONG NTSTATUS
Definition: precomp.h:26
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
BOOLEAN NTAPI KeRemoveQueueDpc(IN PKDPC Dpc)
Definition: dpc.c:877
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
Definition: cdstruc.h:504
struct _FCB * ParentDcb
Definition: fatstruc.h:835
_SEH2_TRY
Definition: create.c:4226
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define FO_FILE_SIZE_CHANGED
Definition: iotypes.h:1748
PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread)
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2820
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:588
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
#define VCB_STATE_FLAG_REMOVABLE_MEDIA
Definition: fatstruc.h:559
NodeType
Definition: Node.h:5
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
IO_COMPLETION_ROUTINE FatFlushCompletionRoutine
Definition: flush.c:47
NTSTATUS FatToggleMediaEjectDisable(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN PreventRemoval)
Definition: deviosup.c:3495
#define DebugUnwind(X)
Definition: fatdata.h:315
#define Dbg
Definition: flush.c:29
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1644
#define FatResetExceptionState(IRPCONTEXT)
Definition: fatprocs.h:2980
#define VCB_STATE_FLAG_BOOT_OR_PAGING_FILE
Definition: fatstruc.h:566
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define Vcb
Definition: cdprocs.h:1415
* PFILE_OBJECT
Definition: iotypes.h:1957
#define VOID
Definition: acefi.h:82
enum _TYPE_OF_OPEN TYPE_OF_OPEN
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:588
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
Status
Definition: gdiplustypes.h:24
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2815
_SEH2_END
Definition: create.c:4400
#define FatAcquireExclusiveVcb(IC, V)
Definition: fatprocs.h:1460
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
_SEH2_FINALLY
Definition: create.c:4371
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1640
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
NTSTATUS FatFlushFat(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: flush.c:801
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
_In_ PFCB Fcb
Definition: cdprocs.h:159
return STATUS_SUCCESS
Definition: btrfs.c:3014
ULONG FcbState
Definition: cdstruc.h:977
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
FCB_CONDITION FcbCondition
Definition: fatstruc.h:849

◆ FatFlushCompletionRoutine() [1/2]

NTSTATUS NTAPI FatFlushCompletionRoutine ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID  Contxt 
)

◆ FatFlushCompletionRoutine() [2/2]

NTSTATUS NTAPI FatFlushCompletionRoutine ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Contxt 
)

Definition at line 1316 of file flush.c.

1322 {
1323  NTSTATUS Status = (NTSTATUS) (ULONG_PTR) Contxt;
1324 
1325  if ( Irp->PendingReturned ) {
1326 
1327  IoMarkIrpPending( Irp );
1328  }
1329 
1330  //
1331  // If the Irp got STATUS_INVALID_DEVICE_REQUEST, normalize it
1332  // to STATUS_SUCCESS.
1333  //
1334 
1335  if (NT_SUCCESS(Irp->IoStatus.Status) ||
1336  (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)) {
1337 
1338  Irp->IoStatus.Status = Status;
1339  }
1340 
1342  UNREFERENCED_PARAMETER( Contxt );
1343 
1344  return STATUS_SUCCESS;
1345 }
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
uint32_t ULONG_PTR
Definition: typedefs.h:64
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define NTSTATUS
Definition: precomp.h:20
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1569
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)

◆ FatFlushDirentForFile()

VOID FatFlushDirentForFile ( IN PIRP_CONTEXT  IrpContext,
IN PFCB  Fcb 
)

Definition at line 1264 of file flush.c.

1285 {
1288 
1289  PAGED_CODE();
1290 
1292 
1293  CcFlushCache( &Fcb->ParentDcb->NonPaged->SectionObjectPointers,
1294  &FileOffset,
1295  sizeof( DIRENT ),
1296  &Iosb );
1297 
1298  if (NT_SUCCESS(Iosb.Status)) {
1299  Iosb.Status = FatHijackIrpAndFlushDevice( IrpContext,
1300  IrpContext->OriginatingIrp,
1302  }
1303 
1304  if (!NT_SUCCESS(Iosb.Status)) {
1305  FatNormalizeAndRaiseStatus(IrpContext, Iosb.Status);
1306  }
1307 }
#define FatNormalizeAndRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2992
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
NTSTATUS FatHijackIrpAndFlushDevice(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: flush.c:1101
struct _FCB * ParentDcb
Definition: fatstruc.h:835
return Iosb
Definition: create.c:4402
PDEVICE_OBJECT TargetDeviceObject
Definition: cdstruc.h:523
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VBO DirentOffsetWithinDirectory
Definition: fatstruc.h:905
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
PVCB Vcb
Definition: cdstruc.h:939
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define PAGED_CODE()

◆ FatFlushFat()

NTSTATUS FatFlushFat ( IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb 
)

Definition at line 801 of file flush.c.

824 {
825  PBCB Bcb;
826  PVOID DontCare;
829 
830  NTSTATUS ReturnStatus = STATUS_SUCCESS;
831 
832  PAGED_CODE();
833 
834  //
835  // If this volume is write protected, no need to flush.
836  //
837 
838  if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
839 
840  return STATUS_SUCCESS;
841  }
842 
843  //
844  // Make sure the Vcb is OK.
845  //
846 
847  _SEH2_TRY {
848 
849  FatVerifyVcb( IrpContext, Vcb );
850 
853 
854  FatResetExceptionState( IrpContext );
855  } _SEH2_END;
856 
857  if (Vcb->VcbCondition != VcbGood) {
858 
859  return STATUS_FILE_INVALID;
860  }
861 
862  //
863  // The only way we have to correctly synchronize things is to
864  // repin stuff, and then unpin repin it.
865  //
866  // With NT 5.0, we can use some new cache manager support to make
867  // this a lot more efficient (important for FAT32). Since we're
868  // only worried about ranges that are dirty - and since we're a
869  // modified-no-write stream - we can assume that if there is no
870  // BCB, there is no work to do in the range. I.e., the lazy writer
871  // beat us to it.
872  //
873  // This is much better than reading the entire FAT in and trying
874  // to punch it out (see the test in the write path to blow
875  // off writes that don't correspond to dirty ranges of the FAT).
876  // For FAT32, this would be a *lot* of reading.
877  //
878 
879  if (Vcb->AllocationSupport.FatIndexBitSize != 12) {
880 
881  //
882  // Walk through the Fat, one page at a time.
883  //
884 
885  ULONG NumberOfPages;
886  ULONG Page;
887 
888  NumberOfPages = ( FatReservedBytes(&Vcb->Bpb) +
889  FatBytesPerFat(&Vcb->Bpb) +
890  (PAGE_SIZE - 1) ) / PAGE_SIZE;
891 
892 
893  for ( Page = 0, Offset.QuadPart = 0;
894  Page < NumberOfPages;
895  Page++, Offset.LowPart += PAGE_SIZE ) {
896 
897  _SEH2_TRY {
898 
899  if (CcPinRead( Vcb->VirtualVolumeFile,
900  &Offset,
901  PAGE_SIZE,
903  &Bcb,
904  &DontCare )) {
905 
907  CcRepinBcb( Bcb );
908  CcUnpinData( Bcb );
910 
911  if (!NT_SUCCESS(Iosb.Status)) {
912 
913  ReturnStatus = Iosb.Status;
914  }
915  }
916 
918 
919  ReturnStatus = IrpContext->ExceptionStatus;
920  continue;
921  } _SEH2_END;
922  }
923 
924  } else {
925 
926  //
927  // We read in the entire fat in the 12 bit case.
928  //
929 
930  Offset.QuadPart = FatReservedBytes( &Vcb->Bpb );
931 
932  _SEH2_TRY {
933 
934  if (CcPinRead( Vcb->VirtualVolumeFile,
935  &Offset,
936  FatBytesPerFat( &Vcb->Bpb ),
938  &Bcb,
939  &DontCare )) {
940 
942  CcRepinBcb( Bcb );
943  CcUnpinData( Bcb );
945 
946  if (!NT_SUCCESS(Iosb.Status)) {
947 
948  ReturnStatus = Iosb.Status;
949  }
950  }
951 
953 
954  ReturnStatus = IrpContext->ExceptionStatus;
955  } _SEH2_END;
956  }
957 
958  return ReturnStatus;
959 }
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define TRUE
Definition: types.h:120
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:411
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define VCB_STATE_FLAG_WRITE_PROTECTED
Definition: fatstruc.h:569
#define PIN_WAIT
VOID FatVerifyVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:270
#define STATUS_FILE_INVALID
Definition: ntstatus.h:374
_SEH2_TRY
Definition: create.c:4226
#define FatReservedBytes(B)
Definition: fat.h:414
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define FatBytesPerFat(B)
Definition: fat.h:410
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
#define FatResetExceptionState(IRPCONTEXT)
Definition: fatprocs.h:2980
VOID NTAPI CcUnpinRepinnedBcb(IN PVOID Bcb, IN BOOLEAN WriteThrough, OUT PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:343
return Iosb
Definition: create.c:4402
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
BOOLEAN NTAPI CcPinRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer)
Definition: pinsup.c:802
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
_SEH2_END
Definition: create.c:4400
#define PIN_IF_BCB
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI CcRepinBcb(IN PVOID Bcb)
Definition: cachesub.c:331
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define PAGED_CODE()

Referenced by _Requires_lock_held_().

◆ FatFlushFatEntries()

VOID FatFlushFatEntries ( IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb,
IN ULONG  Cluster,
IN ULONG  Count 
)

Definition at line 1191 of file flush.c.

1218 {
1219  ULONG ByteCount;
1221 
1223 
1224  PAGED_CODE();
1225 
1226  FileOffset.HighPart = 0;
1227  FileOffset.LowPart = FatReservedBytes( &Vcb->Bpb );
1228 
1229  if (Vcb->AllocationSupport.FatIndexBitSize == 12) {
1230 
1231  FileOffset.LowPart += Cluster * 3 / 2;
1232  ByteCount = (Count * 3 / 2) + 1;
1233 
1234  } else if (Vcb->AllocationSupport.FatIndexBitSize == 32) {
1235 
1236  FileOffset.LowPart += Cluster * sizeof(ULONG);
1237  ByteCount = Count * sizeof(ULONG);
1238 
1239  } else {
1240 
1241  FileOffset.LowPart += Cluster * sizeof( USHORT );
1242  ByteCount = Count * sizeof( USHORT );
1243 
1244  }
1245 
1246  CcFlushCache( &Vcb->SectionObjectPointers,
1247  &FileOffset,
1248  ByteCount,
1249  &Iosb );
1250 
1251  if (NT_SUCCESS(Iosb.Status)) {
1252  Iosb.Status = FatHijackIrpAndFlushDevice( IrpContext,
1253  IrpContext->OriginatingIrp,
1254  Vcb->TargetDeviceObject );
1255  }
1256 
1257  if (!NT_SUCCESS(Iosb.Status)) {
1258  FatNormalizeAndRaiseStatus(IrpContext, Iosb.Status);
1259  }
1260 }
#define FatNormalizeAndRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2992
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
NTSTATUS FatHijackIrpAndFlushDevice(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: flush.c:1101
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1173
#define FatReservedBytes(B)
Definition: fat.h:414
return Iosb
Definition: create.c:4402
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1063
unsigned short USHORT
Definition: pedump.c:61
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
unsigned int ULONG
Definition: retypes.h:1
#define PAGED_CODE()

◆ FatHijackCompletionRoutine()

NTSTATUS NTAPI FatHijackCompletionRoutine ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID  Contxt 
)

Definition at line 1353 of file flush.c.

1359 {
1360  //
1361  // Set the event so that our call will wake up.
1362  //
1363 
1364  KeSetEvent( (PKEVENT)Contxt, 0, FALSE );
1365 
1368 
1370 }
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1569

◆ FatHijackIrpAndFlushDevice()

NTSTATUS FatHijackIrpAndFlushDevice ( IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp,
IN PDEVICE_OBJECT  TargetDeviceObject 
)

Definition at line 1101 of file flush.c.

1130 {
1131  KEVENT Event;
1132  NTSTATUS Status;
1133  PIO_STACK_LOCATION NextIrpSp;
1134 
1135  PAGED_CODE();
1136 
1137  UNREFERENCED_PARAMETER( IrpContext );
1138 
1139  //
1140  // Get the next stack location, and copy over the stack location
1141  //
1142 
1144 
1145  NextIrpSp = IoGetNextIrpStackLocation( Irp );
1146  NextIrpSp->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
1147  NextIrpSp->MinorFunction = 0;
1148 
1149  //
1150  // Set up the completion routine
1151  //
1152 
1154 
1157  &Event,
1158  TRUE,
1159  TRUE,
1160  TRUE );
1161 
1162  //
1163  // Send the request.
1164  //
1165 
1167 
1168  if (Status == STATUS_PENDING) {
1169 
1171 
1172  Status = Irp->IoStatus.Status;
1173  }
1174 
1175  //
1176  // If the driver doesn't support flushes, return SUCCESS.
1177  //
1178 
1181  }
1182 
1183  Irp->IoStatus.Status = 0;
1184  Irp->IoStatus.Information = 0;
1185 
1186  return Status;
1187 }
IO_COMPLETION_ROUTINE FatHijackCompletionRoutine
Definition: flush.c:57
#define TRUE
Definition: types.h:120
#define IRP_MJ_FLUSH_BUFFERS
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2820
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:437
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_PENDING
Definition: ntstatus.h:82
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
Status
Definition: gdiplustypes.h:24
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
IN OUT PVCB IN PDEVICE_OBJECT TargetDeviceObject
Definition: fatprocs.h:1673
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define PAGED_CODE()

Referenced by _Requires_lock_held_(), FatFlushDirentForFile(), and FatFlushFatEntries().

Variable Documentation

◆ FatFlushCompletionRoutine

IO_COMPLETION_ROUTINE FatFlushCompletionRoutine

Definition at line 47 of file flush.c.

Referenced by _Requires_lock_held_().

◆ FatHijackCompletionRoutine

NTSTATUS NTAPI FatHijackCompletionRoutine

Definition at line 57 of file flush.c.

Referenced by FatHijackIrpAndFlushDevice().