ReactOS 0.4.15-dev-7931-gfd331f1
cleanup.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 Cleanup.c
8
9Abstract:
10
11 This module implements the File Cleanup 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_CLEANUP)
24
25//
26// The local debug trace level
27//
28
29#define Dbg (DEBUG_TRACE_CLEANUP)
30
31//
32// The following little routine exists solely because it need a spin lock.
33//
34
35VOID
37 IN PIRP_CONTEXT IrpContext,
38 IN PVCB Vcb
39 );
40
41#ifdef ALLOC_PRAGMA
42#pragma alloc_text(PAGE, FatCommonCleanup)
43#pragma alloc_text(PAGE, FatFsdCleanup)
44#endif
45
46
51FatFsdCleanup (
52 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
54 )
55
56/*++
57
58Routine Description:
59
60 This routine implements the FSD part of closing down a handle to a
61 file object.
62
63Arguments:
64
65 VolumeDeviceObject - Supplies the volume device object where the
66 file being Cleanup exists
67
68 Irp - Supplies the Irp being processed
69
70Return Value:
71
72 NTSTATUS - The FSD status for the IRP
73
74--*/
75
76{
78 PIRP_CONTEXT IrpContext = NULL;
79
81
82 PAGED_CODE();
83
84 //
85 // If we were called with our file system device object instead of a
86 // volume device object, just complete this request with STATUS_SUCCESS
87 //
88
89 if ( FatDeviceIsFatFsdo( VolumeDeviceObject)) {
90
91 Irp->IoStatus.Status = STATUS_SUCCESS;
92 Irp->IoStatus.Information = FILE_OPENED;
93
95
96 return STATUS_SUCCESS;
97 }
98
99 DebugTrace(+1, Dbg, "FatFsdCleanup\n", 0);
100
101 //
102 // Call the common Cleanup routine, with blocking allowed.
103 //
104
106
108
109 _SEH2_TRY {
110
111 IrpContext = FatCreateIrpContext( Irp, TRUE );
112
113 Status = FatCommonCleanup( IrpContext, Irp );
114
116
117 //
118 // We had some trouble trying to perform the requested
119 // operation, so we'll abort the I/O request with
120 // the error status that we get back from the
121 // execption code
122 //
123
124 Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
125 } _SEH2_END;
126
127 if (TopLevel) { IoSetTopLevelIrp( NULL ); }
128
130
131 //
132 // And return to our caller
133 //
134
135 DebugTrace(-1, Dbg, "FatFsdCleanup -> %08lx\n", Status);
136
137 UNREFERENCED_PARAMETER( VolumeDeviceObject );
138
139 return Status;
140}
141
142
143_Requires_lock_held_(_Global_critical_region_)
145FatCommonCleanup (
146 IN PIRP_CONTEXT IrpContext,
147 IN PIRP Irp
148 )
149
150/*++
151
152Routine Description:
153
154 This is the common routine for cleanup of a file/directory called by both
155 the fsd and fsp threads.
156
157 Cleanup is invoked whenever the last handle to a file object is closed.
158 This is different than the Close operation which is invoked when the last
159 reference to a file object is deleted.
160
161 The function of cleanup is to essentially "cleanup" the file/directory
162 after a user is done with it. The Fcb/Dcb remains around (because MM
163 still has the file object referenced) but is now available for another
164 user to open (i.e., as far as the user is concerned the is now closed).
165
166 See close for a more complete description of what close does.
167
168Arguments:
169
170 Irp - Supplies the Irp to process
171
172Return Value:
173
174 NTSTATUS - The return status for the operation
175
176--*/
177
178{
180
182
184
186 PVCB Vcb;
187 PFCB Fcb;
188 PCCB Ccb;
189
190 BOOLEAN SendUnlockNotification = FALSE;
191
193
194 PLARGE_INTEGER TruncateSize = NULL;
195 LARGE_INTEGER LocalTruncateSize;
196
197 BOOLEAN AcquiredVcb = FALSE;
198 BOOLEAN AcquiredFcb = FALSE;
199
200#if (NTDDI_VERSION >= NTDDI_WIN8)
201 BOOLEAN ProcessingDeleteOnClose = FALSE;
202#endif
203
204 PAGED_CODE();
205
207
208 DebugTrace(+1, Dbg, "FatCommonCleanup\n", 0);
209 DebugTrace( 0, Dbg, "Irp = %p\n", Irp);
210 DebugTrace( 0, Dbg, "->FileObject = %p\n", IrpSp->FileObject);
211
212 //
213 // Extract and decode the file object
214 //
215
218
219 //
220 // Special case the unopened file object. This will occur only when
221 // we are initializing Vcb and IoCreateStreamFileObject is being
222 // called.
223 //
224
226
227 DebugTrace(0, Dbg, "Unopened File Object\n", 0);
228
229 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
230
231 DebugTrace(-1, Dbg, "FatCommonCleanup -> STATUS_SUCCESS\n", 0);
232 return STATUS_SUCCESS;
233 }
234
235 //
236 // If this is not our first time through (for whatever reason)
237 // only see if we have to flush the file.
238 //
239
240 if (FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE )) {
241
242 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
246
247 //
248 // Flush the file.
249 //
250
251 Status = FatFlushFile( IrpContext, Fcb, Flush );
252
253 if (!NT_SUCCESS(Status)) {
254
255 FatNormalizeAndRaiseStatus( IrpContext, Status );
256 }
257 }
258
259 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
260
261 DebugTrace(-1, Dbg, "FatCommonCleanup -> STATUS_SUCCESS\n", 0);
262 return STATUS_SUCCESS;
263 }
264
265 //
266 // If we call change the allocation or call CcUninitialize,
267 // we have to take the Fcb exclusive
268 //
269
271
272 NT_ASSERT( Fcb != NULL );
273
274 (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
275
276 AcquiredFcb = TRUE;
277
278 //
279 // Do a check here if this was a DELETE_ON_CLOSE FileObject, and
280 // set the Fcb flag appropriately.
281 //
282
284
286
287 //
288 // Transfer the delete-on-close state to the FCB. We do this rather
289 // than leave the CCB_FLAG_DELETE_ON_CLOSE flag set so that if we
290 // end up breaking an oplock and come in again we won't try to break
291 // the oplock again (and again, and again...).
292 //
293
296
297#if (NTDDI_VERSION >= NTDDI_WIN8)
298 ProcessingDeleteOnClose = TRUE;
299#endif
300
301 //
302 // Report this to the dir notify package for a directory.
303 //
304
306
307#ifdef _MSC_VER
308#pragma prefast( suppress:6309, "FullDirectoryName may be NULL if NotifyIrp is also NULL. this indicates the object is being deleted." )
309#endif
311 &Vcb->DirNotifyList,
312 FileObject->FsContext,
313 NULL,
314 FALSE,
315 FALSE,
316 0,
317 NULL,
318 NULL,
319 NULL );
320 }
321 }
322
323 //
324 // Now if we may delete the file, drop the Fcb and acquire the Vcb
325 // first. Note that while we own the Fcb exclusive, a file cannot
326 // become DELETE_ON_CLOSE and cannot be opened via CommonCreate.
327 //
328
329 if ((Fcb->UncleanCount == 1) &&
331 (Fcb->FcbCondition != FcbBad) &&
333
334 FatReleaseFcb( IrpContext, Fcb );
335 AcquiredFcb = FALSE;
336
337 (VOID)FatAcquireExclusiveVcb( IrpContext, Vcb );
338 AcquiredVcb = TRUE;
339
340 (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
341 AcquiredFcb = TRUE;
342 }
343 }
344
345 //
346 // For user DASD cleanups, grab the Vcb exclusive.
347 //
348
349 if (TypeOfOpen == UserVolumeOpen) {
350
351 (VOID)FatAcquireExclusiveVcb( IrpContext, Vcb );
352 AcquiredVcb = TRUE;
353 }
354
355 //
356 // Complete any Notify Irps on this file handle.
357 //
358
360
361 FsRtlNotifyCleanup( Vcb->NotifySync,
362 &Vcb->DirNotifyList,
363 Ccb );
364 }
365
366 //
367 // Determine the Fcb state, Good or Bad, for better or for worse.
368 //
369 // We can only read the volume file if VcbCondition is good.
370 //
371
372 if ( Fcb != NULL) {
373
374 //
375 // Stop any raises from FatVerifyFcb, unless it is REAL bad.
376 //
377
378 _SEH2_TRY {
379
380 _SEH2_TRY {
381
382 FatVerifyFcb( IrpContext, Fcb );
383
386
387 FatResetExceptionState( IrpContext );
388 } _SEH2_END;
389
390 } _SEH2_FINALLY {
391
393
394 //
395 // We will be raising out of here.
396 //
397
398 if (AcquiredFcb) { FatReleaseFcb( IrpContext, Fcb ); }
399 if (AcquiredVcb) { FatReleaseVcb( IrpContext, Vcb ); }
400 }
401 } _SEH2_END;
402 }
403
404 _SEH2_TRY {
405
406#if (NTDDI_VERSION >= NTDDI_WIN8)
407
408 //
409 // See if this is a delete-on-close handle on a file or empty directory.
410 // If so we may need to break an oplock. We do this in the try block
411 // so that resources will be properly released.
412 //
413
414 if (ProcessingDeleteOnClose &&
416 ((NodeType( Fcb ) != FAT_NTC_DCB) ||
417 FatIsDirectoryEmpty( IrpContext, Fcb ))) {
418
419 Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
420 Irp,
421 OPLOCK_FLAG_CLOSING_DELETE_ON_CLOSE,
422 IrpContext,
425
426 if (Status != STATUS_SUCCESS) {
427
428 if (Status == STATUS_PENDING) {
429
432
433 } else {
434
435 FatNormalizeAndRaiseStatus( IrpContext, Status );
436 }
437 }
438 }
439#endif
440
441 //
442 // Case on the type of open that we are trying to cleanup.
443 // For all cases we need to set the share access to point to the
444 // share access variable (if there is one). After the switch
445 // we then remove the share access and complete the Irp.
446 // In the case of UserFileOpen we actually have a lot more work
447 // to do and we have the FsdLockControl complete the Irp for us.
448 //
449
450 switch (TypeOfOpen) {
451
452 case DirectoryFile:
454
455 DebugTrace(0, Dbg, "Cleanup VirtualVolumeFile/DirectoryFile\n", 0);
456
458
459 break;
460
461
462 case UserVolumeOpen:
463
464 DebugTrace(0, Dbg, "Cleanup UserVolumeOpen\n", 0);
465
467
468 FatCheckForDismount( IrpContext, Vcb, TRUE );
469
470 //
471 // If this handle had write access, and actually wrote something,
472 // flush the device buffers, and then set the verify bit now
473 // just to be safe (in case there is no dismount).
474 //
475
476 } else if (FileObject->WriteAccess &&
478
479 (VOID)FatHijackIrpAndFlushDevice( IrpContext,
480 Irp,
481 Vcb->TargetDeviceObject );
482
483 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
484 }
485
486 //
487 // If the volume is locked by this file object then release
488 // the volume and send notification.
489 //
490
491 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED) &&
492 (Vcb->FileObjectWithVcbLocked == FileObject)) {
493
494 FatAutoUnlock( IrpContext, Vcb );
495 SendUnlockNotification = TRUE;
496 }
497
498 ShareAccess = &Vcb->ShareAccess;
499
500 break;
501
502 case EaFile:
503
504 DebugTrace(0, Dbg, "Cleanup EaFileObject\n", 0);
505
507
508 break;
509
511
512 DebugTrace(0, Dbg, "Cleanup UserDirectoryOpen\n", 0);
513
515
516 //
517 // Determine here if we should try do delayed close.
518 //
519
520 if ((Fcb->UncleanCount == 1) &&
521 (Fcb->OpenCount == 1) &&
522 (Fcb->Specific.Dcb.DirectoryFileOpenCount == 0) &&
525
526 //
527 // Delay our close.
528 //
529
531 }
532
533 //
534 // Clear the deny defrag bit, if the handle we're cleaning up was the one that set it.
535 //
536
538
541 }
542
543 if ((VcbGood == Vcb->VcbCondition) &&
544 !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN)) {
545
546 FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
547
548 //
549 // If the directory has a unclean count of 1 then we know
550 // that this is the last handle for the file object. If
551 // we are supposed to delete it, do so.
552 //
553
554 if ((Fcb->UncleanCount == 1) &&
555 (NodeType(Fcb) == FAT_NTC_DCB) &&
557 (Fcb->FcbCondition == FcbGood) &&
559
560 if (!FatIsDirectoryEmpty(IrpContext, Fcb)) {
561
562 //
563 // If there are files in the directory at this point,
564 // forget that we were trying to delete it.
565 //
566
568
569 } else {
570
571#if (NTDDI_VERSION >= NTDDI_WIN8)
572 NTSTATUS BreakStatus;
573#endif
574
575 //
576 // Even if something goes wrong, we cannot turn back!
577 //
578
579 _SEH2_TRY {
580
582
583
584 //
585 // Before truncating file allocation remember this
586 // info for FatDeleteDirent.
587 //
588
589 DeleteContext.FileSize = Fcb->Header.FileSize.LowPart;
590 DeleteContext.FirstClusterOfFile = Fcb->FirstClusterOfFile;
591
592 //
593 // Synchronize here with paging IO
594 //
595
596 (VOID)ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource,
597 TRUE );
598
599 Fcb->Header.FileSize.LowPart = 0;
600
601 ExReleaseResourceLite( Fcb->Header.PagingIoResource );
602
603 //
604 // Truncate the file allocation down to zero
605 //
606
607 DebugTrace(0, Dbg, "Delete File allocation\n", 0);
608
609 FatTruncateFileAllocation( IrpContext, Fcb, 0 );
610
611 if (Fcb->Header.AllocationSize.LowPart == 0) {
612
613 //
614 // Tunnel and remove the dirent for the directory
615 //
616
617 DebugTrace(0, Dbg, "Delete the directory dirent\n", 0);
618
620
621 FatDeleteDirent( IrpContext, Fcb, &DeleteContext, TRUE );
622
623 //
624 // Report that we have removed an entry.
625 //
626
627 FatNotifyReportChange( IrpContext,
628 Vcb,
629 Fcb,
632 }
633
636
637 FatResetExceptionState( IrpContext );
638 } _SEH2_END;
639
640 //
641 // Remove the entry from the name table.
642 // This will ensure that
643 // we will not collide with the Dcb if the user wants
644 // to recreate the same file over again before we
645 // get a close irp.
646 //
647
648 FatRemoveNames( IrpContext, Fcb );
649
650#if (NTDDI_VERSION >= NTDDI_WIN8)
651 //
652 // We've removed the names so break any parent directory oplock.
653 // Directory oplock breaks are always advisory, so we will never
654 // block/get STATUS_PENDING here.
655 //
656
657 BreakStatus = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb->ParentDcb),
658 Irp,
659 (OPLOCK_FLAG_PARENT_OBJECT |
660 OPLOCK_FLAG_REMOVING_FILE_OR_LINK),
661 NULL,
662 NULL,
663 NULL );
664
665 ASSERT( BreakStatus != STATUS_PENDING );
666#endif
667 }
668 }
669 }
670
671 //
672 // Decrement the unclean count.
673 //
674
675 NT_ASSERT( Fcb->UncleanCount != 0 );
676 Fcb->UncleanCount -= 1;
677
678 break;
679
680 case UserFileOpen:
681
682 DebugTrace(0, Dbg, "Cleanup UserFileOpen\n", 0);
683
685
686 //
687 // Determine here if we should do a delayed close.
688 //
689
690 if ((FileObject->SectionObjectPointer->DataSectionObject == NULL) &&
691 (FileObject->SectionObjectPointer->ImageSectionObject == NULL) &&
692 (Fcb->UncleanCount == 1) &&
693 (Fcb->OpenCount == 1) &&
697
698 //
699 // Delay our close.
700 //
701
703 }
704
705 //
706 // Clear the deny defrag bit, if the handle we're cleaning up was the one that set it.
707 //
708
710
713 }
714
715 //
716 // Unlock all outstanding file locks.
717 //
718
719 (VOID) FsRtlFastUnlockAll( &Fcb->Specific.Fcb.FileLock,
722 NULL );
723
724
725
726 //
727 // We can proceed with on-disk updates only if the volume is mounted
728 // and we can still write to it if it hasn't been shutdown. Remember that
729 // we toss all sections in the failed-verify and dismount cases.
730 //
731
732 if ((Vcb->VcbCondition == VcbGood) &&
733 !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN)) {
734
735 if (Fcb->FcbCondition == FcbGood) {
736
737
738 FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
739
740 }
741
742 //
743 // If the file has a unclean count of 1 then we know
744 // that this is the last handle for the file object.
745 //
746
747 if ( (Fcb->UncleanCount == 1) && (Fcb->FcbCondition == FcbGood) ) {
748
750
751 //
752 // Check if we should be deleting the file. The
753 // delete operation really deletes the file but
754 // keeps the Fcb around for close to do away with.
755 //
756
759
760 //
761 // Before truncating file allocation remember this
762 // info for FatDeleteDirent.
763 //
764
765 DeleteContext.FileSize = Fcb->Header.FileSize.LowPart;
766 DeleteContext.FirstClusterOfFile = Fcb->FirstClusterOfFile;
767
768 DebugTrace(0, Dbg, "Delete File allocation\n", 0);
769
770 //
771 // Synchronize here with paging IO
772 //
773
774 (VOID)ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource,
775 TRUE );
776
777 Fcb->Header.FileSize.LowPart = 0;
778 Fcb->Header.ValidDataLength.LowPart = 0;
779 Fcb->ValidDataToDisk = 0;
780
781 ExReleaseResourceLite( Fcb->Header.PagingIoResource );
782
783 _SEH2_TRY {
784
785 FatSetFileSizeInDirent( IrpContext, Fcb, NULL );
786
789
790 FatResetExceptionState( IrpContext );
791 } _SEH2_END;
792
794
795 } else {
796
797 //
798 // We must zero between ValidDataLength and FileSize
799 //
800
802 (Fcb->Header.ValidDataLength.LowPart < Fcb->Header.FileSize.LowPart)) {
803
804 ULONG ValidDataLength;
805
806 ValidDataLength = Fcb->Header.ValidDataLength.LowPart;
807
808 if (ValidDataLength < Fcb->ValidDataToDisk) {
809 ValidDataLength = Fcb->ValidDataToDisk;
810 }
811
812 //
813 // Recheck, VDD can be >= FS
814 //
815
816 if (ValidDataLength < Fcb->Header.FileSize.LowPart) {
817
818 _SEH2_TRY {
819
820 (VOID)FatZeroData( IrpContext,
821 Vcb,
823 ValidDataLength,
824 Fcb->Header.FileSize.LowPart -
825 ValidDataLength );
826
827 //
828 // Since we just zeroed this, we can now bump
829 // up VDL in the Fcb.
830 //
831
833 Fcb->Header.ValidDataLength.LowPart =
834 Fcb->Header.FileSize.LowPart;
835
836 //
837 // We inform Cc of the motion so that the cache map is updated.
838 // This prevents optimized zero-page faults in case the cache
839 // structures are re-used for another handle before they are torn
840 // down by our soon-to-occur uninitialize. If they were, a noncached
841 // producer could write into the region we just zeroed and Cc would
842 // be none the wiser, then our async cached reader comes in and takes
843 // the optimized path, and we get bad (zero) data.
844 //
845 // If this was memory mapped, we don't have to (can't) tell Cc, it'll
846 // figure it out when a cached handle is opened.
847 //
848
849 if (CcIsFileCached( FileObject )) {
850 CcSetFileSizes( FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
851 }
852
855
856 FatResetExceptionState( IrpContext );
857 } _SEH2_END;
858 }
859 }
860 }
861
862 //
863 // See if we are supposed to truncate the file on the last
864 // close. If we cannot wait we'll ship this off to the fsp
865 //
866
867 _SEH2_TRY {
868
870
871 DebugTrace(0, Dbg, "truncate file allocation\n", 0);
872
873 if (Vcb->VcbCondition == VcbGood) {
874
875
876 FatTruncateFileAllocation( IrpContext,
877 Fcb,
878 Fcb->Header.FileSize.LowPart );
879
880
881 }
882
883 //
884 // We also have to get rid of the Cache Map because
885 // this is the only way we have of trashing the
886 // truncated pages.
887 //
888
889 LocalTruncateSize = Fcb->Header.FileSize;
890 TruncateSize = &LocalTruncateSize;
891
892 //
893 // Mark the Fcb as having now been truncated, just incase
894 // we have to reship this off to the fsp.
895 //
896
897 Fcb->FcbState &= ~FCB_STATE_TRUNCATE_ON_CLOSE;
898 }
899
900 //
901 // Now check again if we are to delete the file and if
902 // so then we remove the file from the disk.
903 //
904
906 Fcb->Header.AllocationSize.LowPart == 0) {
907
908 DebugTrace(0, Dbg, "Delete File\n", 0);
909
910 //
911 // Now tunnel and delete the dirent
912 //
913
915
916 FatDeleteDirent( IrpContext, Fcb, &DeleteContext, TRUE );
917
918 //
919 // Report that we have removed an entry.
920 //
921
922 FatNotifyReportChange( IrpContext,
923 Vcb,
924 Fcb,
927 }
928
931
932 FatResetExceptionState( IrpContext );
933 } _SEH2_END;
934
936
937#if (NTDDI_VERSION >= NTDDI_WIN8)
938 NTSTATUS BreakStatus;
939#endif
940 //
941 // Remove the entry from the splay table. This will
942 // ensure that we will not collide with the Fcb if the
943 // user wants to recreate the same file over again
944 // before we get a close irp.
945 //
946 // Note that we remove the name even if we couldn't
947 // truncate the allocation and remove the dirent above.
948 //
949
950 FatRemoveNames( IrpContext, Fcb );
951
952#if (NTDDI_VERSION >= NTDDI_WIN8)
953 //
954 // We've removed the names so break any parent directory oplock.
955 // Directory oplock breaks are always advisory, so we will never
956 // block/get STATUS_PENDING here.
957 //
958
959 BreakStatus = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb->ParentDcb),
960 Irp,
961 (OPLOCK_FLAG_PARENT_OBJECT |
962 OPLOCK_FLAG_REMOVING_FILE_OR_LINK),
963 NULL,
964 NULL,
965 NULL );
966
967 ASSERT( BreakStatus != STATUS_PENDING );
968#endif
969 }
970 }
971 }
972
973 //
974 // We've just finished everything associated with an unclean
975 // fcb so now decrement the unclean count before releasing
976 // the resource.
977 //
978
979 NT_ASSERT( Fcb->UncleanCount != 0 );
980 Fcb->UncleanCount -= 1;
981 if (!FlagOn( FileObject->Flags, FO_CACHE_SUPPORTED )) {
984 }
985
986 //
987 // If this was the last cached open, and there are open
988 // non-cached handles, attempt a flush and purge operation
989 // to avoid cache coherency overhead from these non-cached
990 // handles later. We ignore any I/O errors from the flush.
991 //
992
993 if (FlagOn( FileObject->Flags, FO_CACHE_SUPPORTED ) &&
994 (Fcb->NonCachedUncleanCount != 0) &&
997
999
1000 //
1001 // Grab and release PagingIo to serialize ourselves with the lazy writer.
1002 // This will work to ensure that all IO has completed on the cached
1003 // data and we will succesfully tear away the cache section.
1004 //
1005
1006 ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
1007 ExReleaseResourceLite( Fcb->Header.PagingIoResource );
1008
1010 NULL,
1011 0,
1012 FALSE );
1013 }
1014
1015 //
1016 // If the file is invalid, hint to the cache that we should throw everything out.
1017 //
1018
1019 if ( Fcb->FcbCondition == FcbBad ) {
1020
1021 TruncateSize = &FatLargeZero;
1022 }
1023
1024 //
1025 // Cleanup the cache map
1026 //
1027
1028 CcUninitializeCacheMap( FileObject, TruncateSize, NULL );
1029
1030 break;
1031
1032 default:
1033
1034#ifdef _MSC_VER
1035#pragma prefast( suppress: 28159, "if the type of open is unknown then things are very bad." )
1036#endif
1037 FatBugCheck( TypeOfOpen, 0, 0 );
1038 }
1039
1040 //
1041 // We must clean up the share access at this time, since we may not
1042 // get a Close call for awhile if the file was mapped through this
1043 // File Object.
1044 //
1045
1046 if (ShareAccess != NULL) {
1047
1048 DebugTrace(0, Dbg, "Cleanup the Share access\n", 0);
1050 }
1051
1052 if ((TypeOfOpen == UserFileOpen)
1054 ||
1056#endif
1057 ) {
1058
1059 //
1060 // Coordinate the cleanup operation with the oplock state.
1061 // Cleanup operations can always cleanup immediately.
1062 //
1063
1065 Irp,
1066 IrpContext,
1067 NULL,
1068 NULL );
1069
1070 Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
1071 }
1072
1073 //
1074 // First set the FO_CLEANUP_COMPLETE flag.
1075 //
1076
1078
1080
1081 //
1082 // Now unpin any repinned Bcbs.
1083 //
1084
1085 FatUnpinRepinnedBcbs( IrpContext );
1086
1087 //
1088 // If this was deferred flush media, flush the volume.
1089 // We used to do this in lieu of write through for all removable
1090 // media.
1091 //
1092
1093 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
1095
1096 //
1097 // Flush the file.
1098 //
1099
1100 if ((TypeOfOpen == UserFileOpen) &&
1102
1103 Status = FatFlushFile( IrpContext, Fcb, Flush );
1104 }
1105
1106 //
1107 // If that worked ok, then see if we should flush the FAT as well.
1108 //
1109
1110 if (NT_SUCCESS(Status) && Fcb && !FatIsFat12( Vcb) &&
1112
1113 Status = FatFlushFat( IrpContext, Vcb);
1114
1115 //
1116 // Also flush the parent directory.
1117 //
1118
1119 if (NT_SUCCESS(Status) && (Fcb->ParentDcb != NULL)) {
1120
1121 Status = FatFlushFile( IrpContext, Fcb->ParentDcb, Flush );
1122 }
1123 }
1124
1125 if (!NT_SUCCESS(Status)) {
1126
1127 FatNormalizeAndRaiseStatus( IrpContext, Status );
1128 }
1129 }
1130
1131#if (NTDDI_VERSION >= NTDDI_WIN8)
1132
1133 try_exit: NOTHING;
1134
1135#endif
1136
1137 } _SEH2_FINALLY {
1138
1139 DebugUnwind( FatCommonCleanup );
1140
1141 if (AcquiredFcb) { FatReleaseFcb( IrpContext, Fcb ); }
1142 if (AcquiredVcb) { FatReleaseVcb( IrpContext, Vcb ); }
1143
1144 if (SendUnlockNotification) {
1145
1147 }
1148
1149 //
1150 // If this is a normal termination then complete the request
1151 //
1152
1154 (Status != STATUS_PENDING)) {
1155
1156 FatCompleteRequest( IrpContext, Irp, Status );
1157 }
1158
1159 DebugTrace(-1, Dbg, "FatCommonCleanup -> %08lx\n", Status);
1160 } _SEH2_END;
1161
1162 return Status;
1163}
1164
1165VOID
1167 IN PIRP_CONTEXT IrpContext,
1168 IN PVCB Vcb
1169 )
1170{
1171 KIRQL SavedIrql;
1172
1173 //
1174 // Unlock the volume.
1175 //
1176
1177 UNREFERENCED_PARAMETER( IrpContext );
1178
1179 IoAcquireVpbSpinLock( &SavedIrql );
1180
1182
1183 Vcb->VcbState &= ~VCB_STATE_FLAG_LOCKED;
1184 Vcb->FileObjectWithVcbLocked = NULL;
1185
1186 IoReleaseVpbSpinLock( SavedIrql );
1187}
1188
1189
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
NodeType
Definition: Node.h:6
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
VOID DeleteContext(PWSTR pszName)
Definition: context.c:224
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
#define CcIsFileCached(FO)
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
@ UnopenedFileObject
Definition: cdprocs.h:573
@ 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
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define try_return(S)
Definition: cdprocs.h:2179
@ FcbGood
Definition: cdstruc.h:779
@ FcbBad
Definition: cdstruc.h:780
Definition: Header.h:9
#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 NodeType(P)
Definition: nodetype.h:51
VOID FatAutoUnlock(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: cleanup.c:1166
#define Dbg
Definition: cleanup.c:29
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT ShareAccess
Definition: create.c:4147
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
#define FAT_NTC_DCB
Definition: nodetype.h:30
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#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
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
FINISHED FatZeroData(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_OBJECT FileObject, IN ULONG StartingZero, IN ULONG ByteCount)
Definition: cachesup.c:1659
VOID FatTunnelFcbOrDcb(IN PFCB FcbOrDcb, IN PCCB Ccb OPTIONAL)
Definition: dirsup.c:652
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
LARGE_INTEGER FatLargeZero
Definition: fatdata.c:62
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define DebugUnwind(X)
Definition: fatdata.h:315
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
#define FatNotifyReportChange(I, V, F, FL, A)
Definition: fatprocs.h:2168
@ DirectoryFile
Definition: fatprocs.h:1046
@ VirtualVolumeFile
Definition: fatprocs.h:1045
@ EaFile
Definition: fatprocs.h:1047
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1644
NTSTATUS FatFlushFat(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: flush.c:801
VOID NTAPI FatPrePostIrp(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:91
#define FatIsFat12(VCB)
Definition: fatprocs.h:1448
#define FatDeviceIsFatFsdo(D)
Definition: fatprocs.h:3095
#define FatResetExceptionState(IRPCONTEXT)
Definition: fatprocs.h:2983
#define FatAcquireExclusiveVcb(IC, V)
Definition: fatprocs.h:1460
#define FatIsFastIoPossible(FCB)
Definition: fatprocs.h:2813
VOID NTAPI FatOplockComplete(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:35
#define FatNormalizeAndRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2995
@ Flush
Definition: fatprocs.h:1054
#define FatGetFcbOplock(F)
Definition: fatprocs.h:1656
VOID FatRemoveNames(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
Definition: splaysup.c:222
#define FatIsFileOplockable(F)
Definition: fatprocs.h:2851
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1640
NTSTATUS FatHijackIrpAndFlushDevice(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: flush.c:1101
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2301
#define FCB_STATE_FLUSH_FAT
Definition: fatstruc.h:1197
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:559
#define VCB_STATE_FLAG_SHUTDOWN
Definition: fatstruc.h:563
#define VCB_STATE_FLAG_DEFERRED_FLUSH
Definition: fatstruc.h:568
#define IRP_CONTEXT_FLAG_CLEANUP_BREAKING_OPLOCK
Definition: fatstruc.h:1575
#define FCB_STATE_DENY_DEFRAG
Definition: fatstruc.h:1217
#define VCB_STATE_FLAG_WRITE_PROTECTED
Definition: fatstruc.h:570
#define FCB_STATE_DELETE_ON_CLOSE
Definition: fatstruc.h:1193
#define FCB_STATE_TRUNCATE_ON_CLOSE
Definition: fatstruc.h:1194
#define FCB_STATE_PAGING_FILE
Definition: fatstruc.h:1195
@ VcbGood
Definition: fatstruc.h:223
#define CCB_FLAG_DENY_DEFRAG
Definition: fatstruc.h:1352
#define CCB_FLAG_DELETE_ON_CLOSE
Definition: fatstruc.h:1289
#define CCB_FLAG_COMPLETE_DISMOUNT
Definition: fatstruc.h:1331
#define FCB_STATE_DELAY_CLOSE
Definition: fatstruc.h:1203
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1025
#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
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
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
#define NTDDI_VERSION
Definition: k32.h:33
#define ASSERT(a)
Definition: mode.c:44
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define FILE_OPENED
Definition: nt_native.h:769
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
VOID NTAPI FsRtlNotifyCleanup(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:659
VOID NTAPI FsRtlNotifyFullChangeDirectory(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
Definition: notify.c:1487
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
VOID NTAPI IoRemoveShareAccess(IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess)
Definition: file.c:3478
#define IoCompleteRequest
Definition: irp.c:1240
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
#define STATUS_PENDING
Definition: ntstatus.h:82
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
#define Vcb
Definition: cdprocs.h:1415
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:160
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:158
#define NTDDI_WIN8
Definition: sdkddkver.h:113
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cdstruc.h:1067
Definition: cdstruc.h:902
struct _FCB * ParentDcb
Definition: fatstruc.h:836
ULONG Flags
Definition: ntfs.h:536
union _FCB::@720 Specific
SHARE_ACCESS ShareAccess
Definition: cdstruc.h:1009
struct _FCB::@720::@723 Fcb
FCB_CONDITION FcbCondition
Definition: fatstruc.h:850
CLONG OpenCount
Definition: fatstruc.h:881
CLONG UncleanCount
Definition: fatstruc.h:873
ULONG ValidDataToDisk
Definition: fatstruc.h:928
ULONG FirstClusterOfFile
Definition: fatstruc.h:818
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
ULONG FcbState
Definition: cdstruc.h:971
struct _FCB::@720::@722 Dcb
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:811
CLONG NonCachedUncleanCount
Definition: fatstruc.h:888
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: fatstruc.h:729
Definition: cdstruc.h:498
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define FILE_ACTION_REMOVED
#define FO_FILE_MODIFIED
Definition: iotypes.h:1788
#define FILE_NOTIFY_CHANGE_FILE_NAME
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
* PFILE_OBJECT
Definition: iotypes.h:1998
#define VPB_DIRECT_WRITES_ALLOWED
Definition: iotypes.h:1812
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define VPB_LOCKED
Definition: iotypes.h:1808
#define FO_CACHE_SUPPORTED
Definition: iotypes.h:1781
#define FILE_NOTIFY_CHANGE_DIR_NAME
#define IRP_MJ_CLEANUP
#define NT_ASSERT
Definition: rtlfuncs.h:3310