mirror of
https://github.com/bobranten/Ext4Fsd.git
synced 2026-03-22 07:58:30 -05:00
Ext4Fsd master
This commit is contained in:
399
Ext4Fsd/cleanup.c
Normal file
399
Ext4Fsd/cleanup.c
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* 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 *************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
Ext2Cleanup (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;
|
||||
|
||||
__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;
|
||||
__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;
|
||||
__leave;
|
||||
}
|
||||
|
||||
FileObject = IrpContext->FileObject;
|
||||
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
||||
if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
|
||||
Fcb->Identifier.Type != EXT2FCB)) {
|
||||
Status = STATUS_SUCCESS;
|
||||
__leave;
|
||||
}
|
||||
Mcb = Fcb->Mcb;
|
||||
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
||||
|
||||
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
|
||||
Status = STATUS_SUCCESS;
|
||||
__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;
|
||||
__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);
|
||||
}
|
||||
__leave;
|
||||
}
|
||||
|
||||
if (Ccb == NULL) {
|
||||
Status = STATUS_SUCCESS;
|
||||
__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
|
||||
__try {
|
||||
CcZeroData( FileObject,
|
||||
&Fcb->Header.ValidDataLength,
|
||||
&Fcb->Header.AllocationSize,
|
||||
TRUE);
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
DbgBreak();
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
} __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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
Reference in New Issue
Block a user