Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400/* * COPYRIGHT: See COPYRIGHT.TXT * PROJECT: Ext2 File System Driver for WinNT/2K/XP * FILE: cleanup.c * PROGRAMMER: Matt Wu <mattwu@163.com> * HOMEPAGE: http://www.ext2fsd.com * UPDATE HISTORY: */
/* INCLUDES *****************************************************************/
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
NTSTATUSExt2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext){ PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; PEXT2_VCB Vcb = NULL; PFILE_OBJECT FileObject; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL; PIRP Irp = NULL; PEXT2_MCB Mcb = NULL;
BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN FcbPagingIoResourceAcquired = FALSE; BOOLEAN SymLinkDelete = FALSE;
_SEH2_TRY {
ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; }
Irp = IrpContext->Irp; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
if (!IsVcbInited(Vcb)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; }
FileObject = IrpContext->FileObject; Fcb = (PEXT2_FCB) FileObject->FsContext; if (!Fcb || (Fcb->Identifier.Type != EXT2VCB && Fcb->Identifier.Type != EXT2FCB)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } Mcb = Fcb->Mcb; Ccb = (PEXT2_CCB) FileObject->FsContext2;
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; }
if (Fcb->Identifier.Type == EXT2VCB) {
ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE;
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && Vcb->LockFile == FileObject ){
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED); Vcb->LockFile = NULL; Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED); }
if (Ccb) { Ext2DerefXcb(&Vcb->OpenHandleCount); Ext2DerefXcb(&Vcb->OpenVolumeCount); }
IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
Status = STATUS_SUCCESS; _SEH2_LEAVE; }
ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
FcbResourceAcquired = ExAcquireResourceExclusiveLite( &Fcb->MainResource, TRUE );
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) && !IsVcbReadOnly(Vcb) ) { Status = Ext2FlushFile(IrpContext, Fcb, Ccb); } _SEH2_LEAVE; }
if (Ccb == NULL) { Status = STATUS_SUCCESS; _SEH2_LEAVE; }
if (IsDirectory(Fcb)) { if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) { SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
FsRtlNotifyFullChangeDirectory( Vcb->NotifySync, &Vcb->NotifyList, Ccb, NULL, FALSE, FALSE, 0, NULL, NULL, NULL ); }
FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb); }
ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
Ext2DerefXcb(&Vcb->OpenHandleCount); Ext2DerefXcb(&Fcb->OpenHandleCount);
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) { Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE; }
if (IsDirectory(Fcb)) {
ext3_release_dir(Fcb->Inode, &Ccb->filp);
} else {
if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && !IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
LARGE_INTEGER SysTime; KeQuerySystemTime(&SysTime);
Fcb->Inode->i_atime = Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime); Fcb->Mcb->LastAccessTime = Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);
Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
Ext2NotifyReportChange( IrpContext, Vcb, Fcb->Mcb, FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS, FILE_ACTION_MODIFIED ); }
FsRtlCheckOplock( &Fcb->Oplock, Irp, IrpContext, NULL, NULL );
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) { Fcb->NonCachedOpenCount--; }
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) { if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) { SymLinkDelete = TRUE; } else { SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING); } }
// // Drop any byte range locks this process may have on the file. //
FsRtlFastUnlockAll( &Fcb->FileLockAnchor, FileObject, IoGetRequestorProcess(Irp), NULL );
// // If there are no byte range locks owned by other processes on the // file the fast I/O read/write functions doesn't have to check for // locks so we set IsFastIoPossible to FastIoIsPossible again. // if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) { if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {#if EXT2_DEBUG DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n", Ext2GetCurrentProcessName(), "FastIoIsPossible", &Fcb->Mcb->FullName ));#endif
Fcb->Header.IsFastIoPossible = FastIoIsPossible; } }
if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE | FCB_ALLOC_IN_SETINFO) ){
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) { if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) { if (!INODE_HAS_EXTENT(Fcb->Inode)) { #if EXT2_PRE_ALLOCATION_SUPPORT _SEH2_TRY { CcZeroData( FileObject, &Fcb->Header.ValidDataLength, &Fcb->Header.AllocationSize, TRUE); } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { DbgBreak(); } _SEH2_END; #endif } } }
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
LARGE_INTEGER Size;
ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE); FcbPagingIoResourceAcquired = TRUE;
Size.QuadPart = CEILING_ALIGNED(ULONGLONG, (ULONGLONG)Fcb->Mcb->Inode.i_size, (ULONGLONG)BLOCK_SIZE); if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size); Fcb->Header.AllocationSize = Size; Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size; if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; if (CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); } } ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO); ExReleaseResourceLite(&Fcb->PagingIoResource); FcbPagingIoResourceAcquired = FALSE; } } }
IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
if (!IsDirectory(Fcb)) {
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) && (Fcb->SectionObject.DataSectionObject != NULL)) {
if (!IsVcbReadOnly(Vcb)) { CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); }
/* purge cache if all remaining openings are non-cached */ if (Fcb->NonCachedOpenCount > 0 || IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { ExReleaseResourceLite(&(Fcb->PagingIoResource)); }
/* CcPurge could generate recursive IRP_MJ_CLOSE request */ CcPurgeCacheSection( &Fcb->SectionObject, NULL, 0, FALSE ); } }
CcUninitializeCacheMap(FileObject, NULL, NULL); }
if (SymLinkDelete || (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) && Fcb->OpenHandleCount == 0) ) {
// // Ext2DeleteFile will acquire these lock inside //
if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); FcbResourceAcquired = FALSE; }
// // this file is to be deleted ... // if (Ccb->SymLink) { Mcb = Ccb->SymLink; FileObject->DeletePending = FALSE; }
Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
if (NT_SUCCESS(Status)) { if (IsMcbDirectory(Mcb)) { Ext2NotifyReportChange( IrpContext, Vcb, Mcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_REMOVED ); } else { Ext2NotifyReportChange( IrpContext, Vcb, Mcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED ); } }
// // re-acquire the main resource lock //
FcbResourceAcquired = ExAcquireResourceExclusiveLite( &Fcb->MainResource, TRUE ); if (!SymLinkDelete) { SetFlag(FileObject->Flags, FO_FILE_MODIFIED); if (CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); } } }
DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n", Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
Status = STATUS_SUCCESS;
if (FileObject) { SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE); }
} _SEH2_FINALLY {
if (FcbPagingIoResourceAcquired) { ExReleaseResourceLite(&Fcb->PagingIoResource); }
if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); }
if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); }
if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { Ext2QueueRequest(IrpContext); } else { IrpContext->Irp->IoStatus.Status = Status; Ext2CompleteIrpContext(IrpContext, Status); } } } _SEH2_END;
return Status;}