ReactOS 0.4.15-dev-7934-g1dc8d80
cleanup.c File Reference
#include "fatprocs.h"
Include dependency graph for cleanup.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (FAT_BUG_CHECK_CLEANUP)
 
#define Dbg   (DEBUG_TRACE_CLEANUP)
 

Functions

VOID FatAutoUnlock (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
 
 _Function_class_ (IRP_MJ_CLEANUP)
 
 _Requires_lock_held_ (_Global_critical_region_)
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (FAT_BUG_CHECK_CLEANUP)

Definition at line 23 of file cleanup.c.

◆ Dbg

#define Dbg   (DEBUG_TRACE_CLEANUP)

Definition at line 29 of file cleanup.c.

Function Documentation

◆ _Function_class_()

_Function_class_ ( IRP_MJ_CLEANUP  )

Definition at line 47 of file cleanup.c.

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}
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define Dbg
Definition: cleanup.c:29
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
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2417
#define FatDeviceIsFatFsdo(D)
Definition: fatprocs.h:3095
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2301
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
Status
Definition: gdiplustypes.h:25
#define FILE_OPENED
Definition: nt_native.h:769
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#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 STATUS_SUCCESS
Definition: shellext.h:65
#define IO_DISK_INCREMENT
Definition: iotypes.h:600

◆ _Requires_lock_held_()

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 143 of file cleanup.c.

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}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
NodeType
Definition: Node.h:6
#define VOID
Definition: acefi.h:82
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 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
_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
#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
LARGE_INTEGER FatLargeZero
Definition: fatdata.c:62
#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
#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 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
#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
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
#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 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
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
#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 NTDDI_WIN8
Definition: sdkddkver.h:113
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
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 FO_CACHE_SUPPORTED
Definition: iotypes.h:1781
#define FILE_NOTIFY_CHANGE_DIR_NAME
#define NT_ASSERT
Definition: rtlfuncs.h:3310

◆ FatAutoUnlock()

VOID FatAutoUnlock ( IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb 
)

Definition at line 1166 of file cleanup.c.

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}
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
#define VPB_DIRECT_WRITES_ALLOWED
Definition: iotypes.h:1812
#define VPB_LOCKED
Definition: iotypes.h:1808

Referenced by _Requires_lock_held_().