ReactOS 0.4.15-dev-8093-g3285f69
flush.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 Flush.c
8
9Abstract:
10
11 This module implements the File Flush buffers routine for Fat called by the
12 dispatch driver.
13
14
15--*/
16
17#include "fatprocs.h"
18
19//
20// The Bug check file id for this module
21//
22
23#define BugCheckFileId (FAT_BUG_CHECK_FLUSH)
24
25//
26// The local debug trace level
27//
28
29#define Dbg (DEBUG_TRACE_FLUSH)
30
31#ifdef ALLOC_PRAGMA
32#pragma alloc_text(PAGE, FatCommonFlushBuffers)
33#pragma alloc_text(PAGE, FatFlushDirectory)
34#pragma alloc_text(PAGE, FatFlushFat)
35#pragma alloc_text(PAGE, FatFlushFile)
36#pragma alloc_text(PAGE, FatFlushVolume)
37#pragma alloc_text(PAGE, FatFsdFlushBuffers)
38#pragma alloc_text(PAGE, FatFlushDirentForFile)
39#pragma alloc_text(PAGE, FatFlushFatEntries)
40#pragma alloc_text(PAGE, FatHijackIrpAndFlushDevice)
41#endif
42
43//
44// Local procedure prototypes
45//
46
47IO_COMPLETION_ROUTINE FatFlushCompletionRoutine;
48
54 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
55 );
56
57IO_COMPLETION_ROUTINE FatHijackCompletionRoutine;
58
64 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
65 );
66
67
72FatFsdFlushBuffers (
73 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
75 )
76
77/*++
78
79Routine Description:
80
81 This routine implements the FSD part of Flush buffers.
82
83Arguments:
84
85 VolumeDeviceObject - Supplies the volume device object where the
86 file being flushed exists
87
88 Irp - Supplies the Irp being processed
89
90Return Value:
91
92 NTSTATUS - The FSD status for the IRP
93
94--*/
95
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}
146
147
148_Requires_lock_held_(_Global_critical_region_)
150FatCommonFlushBuffers (
151 IN PIRP_CONTEXT IrpContext,
152 IN PIRP Irp
153 )
154
155/*++
156
157Routine Description:
158
159 This is the common routine for flushing a buffer.
160
161Arguments:
162
163 Irp - Supplies the Irp to process
164
165Return Value:
166
167 NTSTATUS - The return status for the operation
168
169--*/
170
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
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
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
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
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}
525
526
527_Requires_lock_held_(_Global_critical_region_)
529FatFlushDirectory (
530 IN PIRP_CONTEXT IrpContext,
531 IN PDCB Dcb,
533 )
534
535/*++
536
537Routine Description:
538
539 This routine non-recursively flushes a dcb tree.
540
541Arguments:
542
543 Dcb - Supplies the Dcb being flushed
544
545 FlushType - Specifies the kind of flushing to perform
546
547Return Value:
548
549 VOID
550
551--*/
552
553{
554 PFCB Fcb;
555 PVCB Vcb;
556 PFCB NextFcb;
557
559 PBCB DirentBcb = NULL;
560
562 NTSTATUS ReturnStatus = STATUS_SUCCESS;
563
564 BOOLEAN ClearWriteThroughOnExit = FALSE;
565 BOOLEAN ClearWaitOnExit = FALSE;
566
567 ULONG CorrectedFileSize = 0;
568
569 PAGED_CODE();
570
571 NT_ASSERT( FatVcbAcquiredExclusive(IrpContext, Dcb->Vcb) );
572
573 DebugTrace(+1, Dbg, "FatFlushDirectory, Dcb = %p\n", Dcb);
574
575 //
576 // First flush all the files, then the directories, to make sure all the
577 // file sizes and times get sets correctly on disk.
578 //
579 // We also have to check here if the "Ea Data. Sf" fcb really
580 // corressponds to an existing file.
581 //
582
583 if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) {
584
585 ClearWriteThroughOnExit = TRUE;
586 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
587 }
588
589 if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {
590
591 ClearWaitOnExit = TRUE;
592 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
593 }
594
595 Vcb = Dcb->Vcb;
596 Fcb = Dcb;
597
598 while (Fcb != NULL) {
599
600 NextFcb = FatGetNextFcbTopDown(IrpContext, Fcb, Dcb);
601
602 if ( (NodeType( Fcb ) == FAT_NTC_FCB) &&
603 (Vcb->EaFcb != Fcb) &&
604 !IsFileDeleted(IrpContext, Fcb)) {
605
606 (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
607
609
610 //
611 // Exception handler to catch and commute errors encountered
612 // doing the flush dance. We may encounter corruption, and
613 // should continue flushing the volume as much as possible.
614 //
615
616 _SEH2_TRY {
617
618 //
619 // Standard handler to release resources, etc.
620 //
621
622 _SEH2_TRY {
623
624 //
625 // Make sure the Fcb is OK.
626 //
627
628 _SEH2_TRY {
629
630 FatVerifyFcb( IrpContext, Fcb );
631
634
635 FatResetExceptionState( IrpContext );
636 } _SEH2_END;
637
638 //
639 // If this Fcb is not good skip it. Note that a 'continue'
640 // here would be very expensive as we inside a try{} body.
641 //
642
643 if (Fcb->FcbCondition != FcbGood) {
644
646 }
647
648 //
649 // In case a handle was never closed and the FS and AS are more
650 // than a cluster different, do this truncate.
651 //
652
654
655
656 FatTruncateFileAllocation( IrpContext,
657 Fcb,
658 Fcb->Header.FileSize.LowPart );
659
660
661 }
662
663 //
664 // Also compare the file's dirent in the parent directory
665 // with the size information in the Fcb and update
666 // it if neccessary. Note that we don't mark the Bcb dirty
667 // because we will be flushing the file object presently, and
668 // Mm knows what's really dirty.
669 //
670
671 FatGetDirentFromFcbOrDcb( IrpContext,
672 Fcb,
673 FALSE,
674 &Dirent,
675 &DirentBcb );
676
677
678 CorrectedFileSize = Fcb->Header.FileSize.LowPart;
679
680
681 if (Dirent->FileSize != CorrectedFileSize) {
682
683 Dirent->FileSize = CorrectedFileSize;
684
685
686 }
687
688 //
689 // We must unpin the Bcb before the flush since we recursively tear up
690 // the tree if Mm decides that the data section is no longer referenced
691 // and the final close comes in for this file. If this parent has no
692 // more children as a result, we will try to initiate teardown on it
693 // and Cc will deadlock against the active count of this Bcb.
694 //
695
696 FatUnpinBcb( IrpContext, DirentBcb );
697
698 //
699 // Now flush the file. Note that this may make the Fcb
700 // go away if Mm dereferences its file object.
701 //
702
703 Status = FatFlushFile( IrpContext, Fcb, FlushType );
704
705 if (!NT_SUCCESS(Status)) {
706
707 ReturnStatus = Status;
708 }
709
710 } _SEH2_FINALLY {
711
712 FatUnpinBcb( IrpContext, DirentBcb );
713
714 //
715 // Since we have the Vcb exclusive we know that if any closes
716 // come in it is because the CcPurgeCacheSection caused the
717 // Fcb to go away.
718 //
719
720 if ( !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB) ) {
721
722 FatReleaseFcb( (IRPCONTEXT), Fcb );
723 }
724 } _SEH2_END;
725 } _SEH2_EXCEPT( (FsRtlIsNtstatusExpected( ReturnStatus = _SEH2_GetExceptionCode() ) != 0 ) ?
727 FatResetExceptionState( IrpContext );
728 } _SEH2_END;
729
730 }
731
732 Fcb = NextFcb;
733 }
734
735 //
736 // OK, now flush the directories.
737 //
738
739 Fcb = Dcb;
740
741 while (Fcb != NULL) {
742
743 NextFcb = FatGetNextFcbTopDown(IrpContext, Fcb, Dcb);
744
745 if ( (NodeType( Fcb ) != FAT_NTC_FCB) &&
746 !IsFileDeleted(IrpContext, Fcb) ) {
747
748 //
749 // Make sure the Fcb is OK.
750 //
751
752 _SEH2_TRY {
753
754 FatVerifyFcb( IrpContext, Fcb );
755
758
759 FatResetExceptionState( IrpContext );
760 } _SEH2_END;
761
762 if (Fcb->FcbCondition == FcbGood) {
763
764 Status = FatFlushFile( IrpContext, Fcb, FlushType );
765
766 if (!NT_SUCCESS(Status)) {
767
768 ReturnStatus = Status;
769 }
770 }
771 }
772
773 Fcb = NextFcb;
774 }
775
776 _SEH2_TRY {
777
778 FatUnpinRepinnedBcbs( IrpContext );
779
781
782 ReturnStatus = IrpContext->ExceptionStatus;
783 } _SEH2_END;
784
785 if (ClearWriteThroughOnExit) {
786
787 ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
788 }
789 if (ClearWaitOnExit) {
790
791 ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
792 }
793
794 DebugTrace(-1, Dbg, "FatFlushDirectory -> 0x%08lx\n", ReturnStatus);
795
796 return ReturnStatus;
797}
798
799
802 IN PIRP_CONTEXT IrpContext,
803 IN PVCB Vcb
804 )
805
806/*++
807
808Routine Description:
809
810 The function carefully flushes the entire FAT for a volume. It is
811 nessecary to dance around a bit because of complicated synchronization
812 reasons.
813
814Arguments:
815
816 Vcb - Supplies the Vcb whose FAT is being flushed
817
818Return Value:
819
820 VOID
821
822--*/
823
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}
960
961
962_Requires_lock_held_(_Global_critical_region_)
964FatFlushVolume (
965 IN PIRP_CONTEXT IrpContext,
966 IN PVCB Vcb,
968 )
969
970/*++
971
972Routine Description:
973
974 The following routine is used to flush a volume to disk, including the
975 volume file, and ea file.
976
977Arguments:
978
979 Vcb - Supplies the volume being flushed
980
981 FlushType - Specifies the kind of flushing to perform
982
983Return Value:
984
985 NTSTATUS - The Status from the flush.
986
987--*/
988
989{
991 NTSTATUS ReturnStatus = STATUS_SUCCESS;
992
993 PAGED_CODE();
994
995 //
996 // If this volume is write protected, no need to flush.
997 //
998
999 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
1000
1001 return STATUS_SUCCESS;
1002 }
1003
1004 //
1005 // Flush all the files and directories.
1006 //
1007
1008 Status = FatFlushDirectory( IrpContext, Vcb->RootDcb, FlushType );
1009
1010 if (!NT_SUCCESS(Status)) {
1011
1012 ReturnStatus = Status;
1013 }
1014
1015 //
1016 // Now Flush the FAT
1017 //
1018
1019 Status = FatFlushFat( IrpContext, Vcb );
1020
1021 if (!NT_SUCCESS(Status)) {
1022
1023 ReturnStatus = Status;
1024 }
1025
1026 //
1027 // Unlock the volume if it is removable.
1028 //
1029
1030 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
1032
1033 FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
1034 }
1035
1036 return ReturnStatus;
1037}
1038
1039
1040_Requires_lock_held_(_Global_critical_region_)
1042FatFlushFile (
1043 IN PIRP_CONTEXT IrpContext,
1044 IN PFCB Fcb,
1046 )
1047
1048/*++
1049
1050Routine Description:
1051
1052 This routine simply flushes the data section on a file.
1053
1054Arguments:
1055
1056 Fcb - Supplies the file being flushed
1057
1058 FlushType - Specifies the kind of flushing to perform
1059
1060Return Value:
1061
1062 NTSTATUS - The Status from the flush.
1063
1064--*/
1065
1066{
1068 PVCB Vcb = Fcb->Vcb;
1069
1070 PAGED_CODE();
1071
1073
1074
1075 if ( !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB )) {
1076
1077 //
1078 // Grab and release PagingIo to serialize ourselves with the lazy writer.
1079 // This will work to ensure that all IO has completed on the cached
1080 // data.
1081 //
1082 // If we are to invalidate the file, now is the right time to do it. Do
1083 // it non-recursively so we don't thump children before their time.
1084 //
1085
1086 ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
1087
1089
1090 FatMarkFcbCondition( IrpContext, Fcb, FcbBad, FALSE );
1091 }
1092
1093 ExReleaseResourceLite( Fcb->Header.PagingIoResource );
1094 }
1095
1096 return Iosb.Status;
1097}
1098
1099
1102 IN PIRP_CONTEXT IrpContext,
1103 IN PIRP Irp,
1105 )
1106
1107/*++
1108
1109Routine Description:
1110
1111 This routine is called when we need to send a flush to a device but
1112 we don't have a flush Irp. What this routine does is make a copy
1113 of its current Irp stack location, but changes the Irp Major code
1114 to a IRP_MJ_FLUSH_BUFFERS amd then send it down, but cut it off at
1115 the knees in the completion routine, fix it up and return to the
1116 user as if nothing had happened.
1117
1118Arguments:
1119
1120 Irp - The Irp to hijack
1121
1122 TargetDeviceObject - The device to send the request to.
1123
1124Return Value:
1125
1126 NTSTATUS - The Status from the flush in case anybody cares.
1127
1128--*/
1129
1130{
1131 KEVENT Event;
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 );
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}
1188
1189
1190VOID
1192 IN PIRP_CONTEXT IrpContext,
1193 IN PVCB Vcb,
1194 IN ULONG Cluster,
1195 IN ULONG Count
1196)
1197
1198/*++
1199
1200Routine Description:
1201
1202 This macro flushes the FAT page(s) containing the passed in run.
1203
1204Arguments:
1205
1206 Vcb - Supplies the volume being flushed
1207
1208 Cluster - The starting cluster
1209
1210 Count - The number of FAT entries in the run
1211
1212Return Value:
1213
1214 VOID
1215
1216--*/
1217
1218{
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}
1261
1262
1263VOID
1265 IN PIRP_CONTEXT IrpContext,
1266 IN PFCB Fcb
1267)
1268
1269/*++
1270
1271Routine Description:
1272
1273 This macro flushes the page containing a file's DIRENT in its parent.
1274
1275Arguments:
1276
1277 Fcb - Supplies the file whose DIRENT is being flushed
1278
1279Return Value:
1280
1281 VOID
1282
1283--*/
1284
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}
1308
1309
1310//
1311// Local support routine
1312//
1313
1315NTAPI
1318 IN PIRP Irp,
1319 IN PVOID Contxt
1320 )
1321
1322{
1323 NTSTATUS Status = (NTSTATUS) (ULONG_PTR) Contxt;
1324
1325 if ( Irp->PendingReturned ) {
1326
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}
1346
1347//
1348// Local support routine
1349//
1350
1352NTAPI
1355 _In_ PIRP Irp,
1356 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
1357 )
1358
1359{
1360 //
1361 // Set the event so that our call will wake up.
1362 //
1363
1364 KeSetEvent( (PKEVENT)Contxt, 0, FALSE );
1365
1368
1370}
1371
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
#define ULongToPtr(ul)
Definition: basetsd.h:92
PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread)
VOID NTAPI CcUnpinRepinnedBcb(IN PVOID Bcb, IN BOOLEAN WriteThrough, OUT PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:343
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
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
VOID NTAPI CcRepinBcb(IN PVOID Bcb)
Definition: cachesub.c:331
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:427
#define CanFsdWait(I)
Definition: cdprocs.h:2001
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
@ UserDirectoryOpen
Definition: cdprocs.h:576
@ UserFileOpen
Definition: cdprocs.h:577
@ UserVolumeOpen
Definition: cdprocs.h:575
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define try_leave(S)
Definition: cdprocs.h:2180
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
@ FcbGood
Definition: cdstruc.h:779
@ FcbBad
Definition: cdstruc.h:780
#define _Requires_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define NTSTATUS
Definition: precomp.h:21
BOOLEAN NTAPI KeRemoveQueueDpc(IN PKDPC Dpc)
Definition: dpc.c:878
#define NodeType(P)
Definition: nodetype.h:51
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
return Iosb
Definition: create.c:4402
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB * Dcb
Definition: create.c:4140
#define FatReservedBytes(B)
Definition: fat.h:414
#define FatBytesPerFat(B)
Definition: fat.h:410
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
#define FAT_NTC_FCB
Definition: nodetype.h:29
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define IRP_CONTEXT_FLAG_WRITE_THROUGH
Definition: ext2fs.h:1088
#define IsFileDeleted(Mcb)
Definition: ext2fs.h:968
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
NTSTATUS FatToggleMediaEjectDisable(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN PreventRemoval)
Definition: deviosup.c:3495
IO_COMPLETION_ROUTINE FatHijackCompletionRoutine
Definition: flush.c:57
VOID FatFlushFatEntries(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG Cluster, IN ULONG Count)
Definition: flush.c:1191
NTSTATUS FatFlushFat(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: flush.c:801
VOID FatFlushDirentForFile(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
Definition: flush.c:1264
IO_COMPLETION_ROUTINE FatFlushCompletionRoutine
Definition: flush.c:47
#define Dbg
Definition: flush.c:29
NTSTATUS FatHijackIrpAndFlushDevice(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: flush.c:1101
LOGICAL FatDiskAccountingEnabled
Definition: fatdata.c:129
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define DebugUnwind(X)
Definition: fatdata.h:315
@ VolumeClean
Definition: fatprocs.h:1954
#define FatVcbAcquiredExclusive(IRPCONTEXT, VCB)
Definition: fatprocs.h:1495
IN OUT PVCB IN PDEVICE_OBJECT TargetDeviceObject
Definition: fatprocs.h:1674
PFCB FatGetNextFcbTopDown(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PFCB TerminationFcb)
Definition: strucsup.c:2627
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:414
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:546
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2417
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2633
@ DirectoryFile
Definition: fatprocs.h:1046
@ VirtualVolumeFile
Definition: fatprocs.h:1045
@ EaFile
Definition: fatprocs.h:1047
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1644
#define FatResetExceptionState(IRPCONTEXT)
Definition: fatprocs.h:2983
#define FatAcquireExclusiveVcb(IC, V)
Definition: fatprocs.h:1460
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1082
enum _FAT_FLUSH_TYPE FAT_FLUSH_TYPE
#define FatNormalizeAndRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2995
VOID FatVerifyVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:270
@ Flush
Definition: fatprocs.h:1054
@ FlushAndInvalidate
Definition: fatprocs.h:1055
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1640
VOID FatMarkFcbCondition(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN FCB_CONDITION FcbCondition, IN BOOLEAN Recursive)
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2301
#define VCB_STATE_FLAG_VOLUME_DIRTY
Definition: fatstruc.h:561
#define FCB_STATE_FLUSH_FAT
Definition: fatstruc.h:1197
#define VCB_STATE_FLAG_DELETED_FCB
Definition: fatstruc.h:565
#define VCB_STATE_FLAG_REMOVABLE_MEDIA
Definition: fatstruc.h:560
#define VCB_STATE_FLAG_BOOT_OR_PAGING_FILE
Definition: fatstruc.h:567
#define VCB_STATE_FLAG_MOUNTED_DIRTY
Definition: fatstruc.h:562
#define VCB_STATE_FLAG_WRITE_PROTECTED
Definition: fatstruc.h:570
#define FCB_STATE_TRUNCATE_ON_CLOSE
Definition: fatstruc.h:1194
@ VcbGood
Definition: fatstruc.h:223
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define NOTHING
Definition: input_list.c:10
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define _Inout_
Definition: ms_sal.h:378
#define _In_reads_opt_(size)
Definition: ms_sal.h:320
#define _In_
Definition: ms_sal.h:308
#define KernelMode
Definition: asm.h:34
DRIVER_DISPATCH(nfs41_FsdDispatch)
int Count
Definition: noreturn.cpp:7
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ NotificationEvent
#define PIN_IF_BCB
#define PIN_WAIT
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1306
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
BOOLEAN NTAPI IoIsSystemThread(IN PETHREAD Thread)
Definition: util.c:115
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_FILE_INVALID
Definition: ntstatus.h:388
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
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 _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cdstruc.h:1067
Definition: cdstruc.h:902
struct _FCB * ParentDcb
Definition: fatstruc.h:836
PVCB Vcb
Definition: cdstruc.h:933
FCB_CONDITION FcbCondition
Definition: fatstruc.h:850
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
ULONG FcbState
Definition: cdstruc.h:971
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:811
VBO DirentOffsetWithinDirectory
Definition: fatstruc.h:906
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: fatstruc.h:729
Definition: cdstruc.h:498
PDEVICE_OBJECT TargetDeviceObject
Definition: cdstruc.h:517
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_FILE_SIZE_CHANGED
Definition: iotypes.h:1789
#define IRP_MJ_FLUSH_BUFFERS
@ Executive
Definition: ketypes.h:415
#define NT_ASSERT
Definition: rtlfuncs.h:3310