diff options
author | Matt Wu <matt@ext2fsd.com> | 2016-04-27 19:42:05 +0300 |
---|---|---|
committer | Matt Wu <matt@ext2fsd.com> | 2016-04-27 19:42:05 +0300 |
commit | 8573bc8c1192be6e1f34745dbbb814f9b7fcdd79 (patch) | |
tree | 0bf4e9cf88e5c778f917818514a0efcb5ca2924d | |
parent | 5886485e82d1880a20d320a98915e341a1aabbcc (diff) |
Feature: reapear mechanism implemented for Fcb
1) big vcb-lock killed for create/cleanup/close/setinfo
2) flexible FcbLock and McbLock to balance Fcb's reaper
3) thread id added for reaper thread (mainly for debugging)
-rwxr-xr-x | Ext3Fsd/cleanup.c | 86 | ||||
-rw-r--r-- | Ext3Fsd/close.c | 125 | ||||
-rwxr-xr-x | Ext3Fsd/create.c | 84 | ||||
-rwxr-xr-x | Ext3Fsd/fileinfo.c | 171 | ||||
-rw-r--r-- | Ext3Fsd/fsctl.c | 176 | ||||
-rwxr-xr-x | Ext3Fsd/include/ext2fs.h | 26 | ||||
-rwxr-xr-x | Ext3Fsd/init.c | 10 | ||||
-rwxr-xr-x | Ext3Fsd/memory.c | 311 |
8 files changed, 554 insertions, 435 deletions
diff --git a/Ext3Fsd/cleanup.c b/Ext3Fsd/cleanup.c index 5945b6b..1d49d58 100755 --- a/Ext3Fsd/cleanup.c +++ b/Ext3Fsd/cleanup.c @@ -73,14 +73,12 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) __leave; } - VcbResourceAcquired = - ExAcquireResourceExclusiveLite( - &Vcb->MainResource, - TRUE - ); - if (Fcb->Identifier.Type == EXT2VCB) { + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + VcbResourceAcquired = TRUE; + if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && Vcb->LockFile == FileObject ){ @@ -103,6 +101,12 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) 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) && @@ -135,18 +139,8 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) } FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb); - } - ExReleaseResourceLite(&Vcb->MainResource); - VcbResourceAcquired = FALSE; - - FcbResourceAcquired = - ExAcquireResourceExclusiveLite( - &Fcb->MainResource, - TRUE - ); - ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB))); @@ -284,6 +278,37 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) } } + 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) ) { @@ -337,35 +362,6 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) } } - 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) { - if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { - ExReleaseResourceLite(&(Fcb->PagingIoResource)); - } - - CcPurgeCacheSection( &Fcb->SectionObject, - NULL, - 0, - FALSE ); - } - } - - CcUninitializeCacheMap(FileObject, NULL, NULL); - } - - IoRemoveShareAccess(FileObject, &Fcb->ShareAccess); - DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n", Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName)); diff --git a/Ext3Fsd/close.c b/Ext3Fsd/close.c index 6c9a55f..7a3b410 100644 --- a/Ext3Fsd/close.c +++ b/Ext3Fsd/close.c @@ -31,11 +31,10 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) PFILE_OBJECT FileObject; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL; + BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE; - BOOLEAN bDeleteVcb = FALSE; - BOOLEAN bBeingClosed = FALSE; - BOOLEAN bSkipLeave = FALSE; + BOOLEAN FcbDerefDeferred = FALSE; __try { @@ -55,25 +54,6 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); - if (!ExAcquireResourceExclusiveLite( - &Vcb->MainResource, - TRUE )) { - DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n", - Vcb->OpenHandleCount, Vcb->ReferenceCount)); - - Status = STATUS_PENDING; - __leave; - } - VcbResourceAcquired = TRUE; - - bSkipLeave = TRUE; - if (IsFlagOn(Vcb->Flags, VCB_BEING_CLOSED)) { - bBeingClosed = TRUE; - } else { - SetLongFlag(Vcb->Flags, VCB_BEING_CLOSED); - bBeingClosed = FALSE; - } - if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) { FileObject = NULL; @@ -92,11 +72,30 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) Ccb = (PEXT2_CCB) FileObject->FsContext2; } - DEBUG(DL_INF, ( "Ext2Close: (VCB) bBeingClosed = %d Vcb = %p ReferCount = %d\n", - bBeingClosed, Vcb, Vcb->ReferenceCount)); + DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n", + Vcb, Vcb->ReferenceCount)); + + /* + * WARNING: don't release Vcb resource lock here. + * + * CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE + * which would cause revrese order of lock acquirision: + * 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock + * 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock + */ if (Fcb->Identifier.Type == EXT2VCB) { + if (!ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE )) { + DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n", + Vcb->OpenHandleCount, Vcb->ReferenceCount)); + Status = STATUS_PENDING; + __leave; + } + VcbResourceAcquired = TRUE; + if (Ccb) { Ext2DerefXcb(&Vcb->ReferenceCount); @@ -112,7 +111,7 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) } if ( Fcb->Identifier.Type != EXT2FCB || - Fcb->Identifier.Size != sizeof(EXT2_FCB)) { + Fcb->Identifier.Size != sizeof(EXT2_FCB)) { __leave; } @@ -126,68 +125,40 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; - if (!Ccb) { + if (Ccb == NULL || + Ccb->Identifier.Type != EXT2CCB || + Ccb->Identifier.Size != sizeof(EXT2_CCB)) { Status = STATUS_SUCCESS; __leave; } - ASSERT((Ccb->Identifier.Type == EXT2CCB) && - (Ccb->Identifier.Size == sizeof(EXT2_CCB))); - - if (IsFlagOn(Fcb->Flags, FCB_STATE_BUSY)) { - SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY); - DEBUG(DL_WRN, ( "Ext2Close: busy bit set: %wZ\n", &Fcb->Mcb->FullName )); - Status = STATUS_PENDING; - __leave; - } - DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n", Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName )); - if (Ccb) { - - Ext2FreeCcb(Vcb, Ccb); - - if (FileObject) { - FileObject->FsContext2 = Ccb = NULL; - } + Ext2FreeCcb(Vcb, Ccb); + if (FileObject) { + FileObject->FsContext2 = Ccb = NULL; } - if (0 == Ext2DerefXcb(&Fcb->ReferenceCount)) { - - // - // Remove Fcb from Vcb->FcbList ... - // - - if (FcbResourceAcquired) { - ExReleaseResourceLite(&Fcb->MainResource); - FcbResourceAcquired = FALSE; - } - - Ext2FreeFcb(Fcb); + /* only deref fcb, Ext2ReleaseFcb might lead deadlock */ + FcbDerefDeferred = TRUE; + if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) || + NULL == Fcb->Mcb || + IsFileDeleted(Fcb->Mcb)) { + Fcb->TsDrop.QuadPart = 0; + } else { + KeQuerySystemTime(&Fcb->TsDrop); + } + Ext2DerefXcb(&Vcb->ReferenceCount); - if (FileObject) { - FileObject->FsContext = Fcb = NULL; - } + if (FileObject) { + FileObject->FsContext = NULL; } - Ext2DerefXcb(&Vcb->ReferenceCount); Status = STATUS_SUCCESS; } __finally { - if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) { - /* for Ext2Fsd driver open/close, Vcb is NULL */ - if ((!bBeingClosed) && (Vcb->ReferenceCount == 0) && - (!IsMounted(Vcb) || IsDispending(Vcb))) { - bDeleteVcb = TRUE; - } - } - - if (bSkipLeave && !bBeingClosed) { - ClearFlag(Vcb->Flags, VCB_BEING_CLOSED); - } - if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } @@ -205,17 +176,11 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) } else { Ext2CompleteIrpContext(IrpContext, Status); - - if (bDeleteVcb) { - - PVPB Vpb = Vcb->Vpb; - DEBUG(DL_DBG, ( "Ext2Close: Try to free Vcb %p and Vpb %p\n", - Vcb, Vpb)); - - Ext2CheckDismount(IrpContext, Vcb, FALSE); - } } } + + if (FcbDerefDeferred) + Ext2DerefXcb(&Fcb->ReferenceCount); } return Status; diff --git a/Ext3Fsd/create.c b/Ext3Fsd/create.c index f653c7d..69a1ac0 100755 --- a/Ext3Fsd/create.c +++ b/Ext3Fsd/create.c @@ -694,11 +694,12 @@ Ext2CreateFile( ULONG CreateDisposition; BOOLEAN bParentFcbCreated = FALSE; - BOOLEAN bDir = FALSE; BOOLEAN bFcbAllocated = FALSE; BOOLEAN bCreated = FALSE; + BOOLEAN bMainResourceAcquired = FALSE; + BOOLEAN bFcbLockAcquired = FALSE; BOOLEAN OpenDirectory; BOOLEAN OpenTargetDirectory; @@ -770,14 +771,14 @@ Ext2CreateFile( if (ParentFcb) { ParentMcb = ParentFcb->Mcb; - SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY); Ext2ReferMcb(ParentMcb); + ParentFcb = NULL; } if (FileName.Length == 0) { - if (ParentFcb) { - Mcb = ParentFcb->Mcb; + if (ParentMcb) { + Mcb = ParentMcb; Ext2ReferMcb(Mcb); Status = STATUS_SUCCESS; goto McbExisting; @@ -805,7 +806,7 @@ Ext2CreateFile( RtlZeroMemory(FileName.Buffer, FileName.MaximumLength); RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length); - if (ParentFcb && FileName.Buffer[0] == L'\\') { + if (IrpSp->FileObject->RelatedFileObject && FileName.Buffer[0] == L'\\') { Status = STATUS_INVALID_PARAMETER; __leave; } @@ -944,9 +945,9 @@ Dissecting: __leave; } - /* clear BUSY bit from original ParentFcb */ - if (ParentFcb) { - ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY); + if (!bFcbLockAcquired) { + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + bFcbLockAcquired = TRUE; } /* get the ParentFcb, allocate it if needed ... */ @@ -958,9 +959,13 @@ Dissecting: __leave; } bParentFcbCreated = TRUE; - Ext2ReferXcb(&ParentFcb->ReferenceCount); } - SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY); + Ext2ReferXcb(&ParentFcb->ReferenceCount); + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } // We need to create a new one ? if ((CreateDisposition == FILE_CREATE ) || @@ -1149,6 +1154,12 @@ Dissecting: } Openit: + + if (!bFcbLockAcquired) { + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + bFcbLockAcquired = TRUE; + } + /* Mcb should already be referred and symlink is too */ if (Mcb) { @@ -1213,10 +1224,15 @@ Openit: } if (Fcb) { - /* grab Fcb's reference first to avoid the race between Ext2Close (it could free the Fcb we are accessing) */ Ext2ReferXcb(&Fcb->ReferenceCount); + } + + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + + if (Fcb) { ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); bMainResourceAcquired = TRUE; @@ -1557,6 +1573,9 @@ Openit: } __finally { + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + } if (ParentMcb) { Ext2DerefMcb(ParentMcb); @@ -1598,29 +1617,24 @@ Openit: Ext2FreeCcb(Vcb, Ccb); } - } - - if (Fcb && Ext2DerefXcb(&Fcb->ReferenceCount) == 0) { - if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) { + if (Fcb != NULL) { - LARGE_INTEGER Size; - ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE); - __try { - Size.QuadPart = 0; - Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size); - } __finally { - ExReleaseResourceLite(&Fcb->PagingIoResource); + if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) { + LARGE_INTEGER Size; + ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE); + __try { + Size.QuadPart = 0; + Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size); + } __finally { + ExReleaseResourceLite(&Fcb->PagingIoResource); + } } - } - if (bCreated) { - Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb); + if (bCreated) { + Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb); + } } - - Ext2FreeFcb(Fcb); - Fcb = NULL; - bMainResourceAcquired = FALSE; } if (bMainResourceAcquired) { @@ -1633,14 +1647,12 @@ Openit: Ext2FreePool(FileName.Buffer, EXT2_FNAME_MAGIC); } - /* dereference parent Fcb, free it if it goes to zero */ + /* dereference Fcb and parent */ + if (Fcb) { + Ext2ReleaseFcb(Fcb); + } if (ParentFcb) { - ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY); - if (bParentFcbCreated) { - if (Ext2DerefXcb(&ParentFcb->ReferenceCount) == 0) { - Ext2FreeFcb(ParentFcb); - } - } + Ext2ReleaseFcb(ParentFcb); } /* drop SymLink's refer: If succeeds, Ext2AllocateCcb should refer diff --git a/Ext3Fsd/fileinfo.c b/Ext3Fsd/fileinfo.c index 122d987..3039605 100755 --- a/Ext3Fsd/fileinfo.c +++ b/Ext3Fsd/fileinfo.c @@ -504,7 +504,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) ULONG Length; PVOID Buffer; - BOOLEAN VcbMainResourceAcquired = FALSE; BOOLEAN FcbMainResourceAcquired = FALSE; BOOLEAN FcbPagingIoResourceAcquired = FALSE; @@ -542,18 +541,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) __leave; } - /* we need grab Vcb in case it's rename or sethardlink */ - if (FileInformationClass == FileRenameInformation || - FileInformationClass == FileLinkInformation) { - if (!ExAcquireResourceExclusiveLite( - &Vcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { - Status = STATUS_PENDING; - __leave; - } - VcbMainResourceAcquired = TRUE; - } - if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { Status = STATUS_ACCESS_DENIED; __leave; @@ -1047,10 +1034,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) ExReleaseResourceLite(&Fcb->MainResource); } - if (VcbMainResourceAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - } - if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT ) { @@ -1347,8 +1330,7 @@ Ext2SetRenameInfo( BOOLEAN bMove = FALSE; BOOLEAN bTargetRemoved = FALSE; - BOOLEAN bNewTargetDcb = FALSE; - BOOLEAN bNewParentDcb = FALSE; + BOOLEAN bFcbLockAcquired = FALSE; PFILE_RENAME_INFORMATION FRI; @@ -1435,16 +1417,17 @@ Ext2SetRenameInfo( bMove = TRUE; } + if (!bFcbLockAcquired) { + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + bFcbLockAcquired = TRUE; + } + TargetDcb = TargetMcb->Fcb; if (TargetDcb == NULL) { TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); - if (TargetDcb) { - Ext2ReferXcb(&TargetDcb->ReferenceCount); - bNewTargetDcb = TRUE; - } } if (TargetDcb) { - SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY); + Ext2ReferXcb(&TargetDcb->ReferenceCount); } ParentMcb = Mcb->Parent; @@ -1454,15 +1437,16 @@ Ext2SetRenameInfo( if (ParentDcb == NULL) { ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); - if (ParentDcb) { - Ext2ReferXcb(&ParentDcb->ReferenceCount); - bNewParentDcb = TRUE; - } - } - if (ParentDcb) { - SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY); } } + if (ParentDcb) { + Ext2ReferXcb(&ParentDcb->ReferenceCount); + } + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } if (!TargetDcb || !ParentDcb) { Status = STATUS_INSUFFICIENT_RESOURCES; @@ -1625,40 +1609,25 @@ Ext2SetRenameInfo( FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME ), FILE_ACTION_RENAMED_NEW_NAME ); - } } errorout: + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } + if (NewEntry) Ext2FreeEntry(NewEntry); if (TargetDcb) { - if (ParentDcb && ParentDcb->Inode->i_ino != TargetDcb->Inode->i_ino) { - ClearLongFlag(ParentDcb->Flags, FCB_STATE_BUSY); - } - ClearLongFlag(TargetDcb->Flags, FCB_STATE_BUSY); + Ext2ReleaseFcb(TargetDcb); } - if (bNewTargetDcb) { - ASSERT(TargetDcb != NULL); - if (Ext2DerefXcb(&TargetDcb->ReferenceCount) == 0) { - Ext2FreeFcb(TargetDcb); - TargetDcb = NULL; - } else { - DEBUG(DL_RES, ( "Ext2SetRenameInfo: TargetDcb is resued by other threads.\n")); - } - } - - if (bNewParentDcb) { - ASSERT(ParentDcb != NULL); - if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) { - Ext2FreeFcb(ParentDcb); - ParentDcb = NULL; - } else { - DEBUG(DL_RES, ( "Ext2SetRenameInfo: ParentDcb is resued by other threads.\n")); - } + if (ParentDcb) { + Ext2ReleaseFcb(ParentDcb); } if (ExistingMcb) @@ -1698,8 +1667,8 @@ Ext2SetLinkInfo( BOOLEAN ReplaceIfExists; BOOLEAN bTargetRemoved = FALSE; - BOOLEAN bNewTargetDcb = FALSE; - BOOLEAN bNewParentDcb = FALSE; + + BOOLEAN bFcbLockAcquired = FALSE; PFILE_LINK_INFORMATION FLI; @@ -1781,17 +1750,15 @@ Ext2SetLinkInfo( } } + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + bFcbLockAcquired = TRUE; + TargetDcb = TargetMcb->Fcb; if (TargetDcb == NULL) { TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); - if (TargetDcb) { - Ext2ReferXcb(&TargetDcb->ReferenceCount); - bNewTargetDcb = TRUE; - } } - if (TargetDcb) { - SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY); + Ext2ReferXcb(&TargetDcb->ReferenceCount); } ParentMcb = Mcb->Parent; @@ -1801,15 +1768,16 @@ Ext2SetLinkInfo( if (ParentDcb == NULL) { ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); - if (ParentDcb) { - Ext2ReferXcb(&ParentDcb->ReferenceCount); - bNewParentDcb = TRUE; - } - } - if (ParentDcb) { - SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY); } } + if (ParentDcb) { + Ext2ReferXcb(&ParentDcb->ReferenceCount); + } + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; + } if (!TargetDcb || !ParentDcb) { Status = STATUS_INSUFFICIENT_RESOURCES; @@ -1887,31 +1855,17 @@ Ext2SetLinkInfo( errorout: - if (TargetDcb) { - if (ParentDcb && ParentDcb->Inode->i_ino != TargetDcb->Inode->i_ino) { - ClearLongFlag(ParentDcb->Flags, FCB_STATE_BUSY); - } - ClearLongFlag(TargetDcb->Flags, FCB_STATE_BUSY); + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; } - if (bNewTargetDcb) { - ASSERT(TargetDcb != NULL); - if (Ext2DerefXcb(&TargetDcb->ReferenceCount) == 0) { - Ext2FreeFcb(TargetDcb); - TargetDcb = NULL; - } else { - DEBUG(DL_RES, ( "Ext2SetLinkInfo: TargetDcb is resued by other threads.\n")); - } + if (TargetDcb) { + Ext2ReleaseFcb(TargetDcb); } - if (bNewParentDcb) { - ASSERT(ParentDcb != NULL); - if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) { - Ext2FreeFcb(ParentDcb); - ParentDcb = NULL; - } else { - DEBUG(DL_RES, ( "Ext2SeLinkInfo: ParentDcb is resued by other threads.\n")); - } + if (ParentDcb) { + Ext2ReleaseFcb(ParentDcb); } if (ExistingMcb) @@ -1957,7 +1911,7 @@ Ext2DeleteFile( LARGE_INTEGER Size; LARGE_INTEGER SysTime; - BOOLEAN bNewDcb = FALSE; + BOOLEAN bFcbLockAcquired = FALSE; DEBUG(DL_INF, ( "Ext2DeleteFile: File %wZ (%xh) will be deleted!\n", &Mcb->FullName, Mcb->Inode.i_ino)); @@ -1979,16 +1933,22 @@ Ext2DeleteFile( ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + bFcbLockAcquired = TRUE; + if (!(Dcb = Mcb->Parent->Fcb)) { Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent); - if (Dcb) { - Ext2ReferXcb(&Dcb->ReferenceCount); - bNewDcb = TRUE; - } + } + if (Dcb) { + Ext2ReferXcb(&Dcb->ReferenceCount); + } + + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + bFcbLockAcquired = FALSE; } if (Dcb) { - SetLongFlag(Dcb->Flags, FCB_STATE_BUSY); DcbResourceAcquired = ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); @@ -2090,21 +2050,18 @@ Ext2DeleteFile( ExReleaseResourceLite(&Dcb->MainResource); } - if (Dcb) { - ClearLongFlag(Dcb->Flags, FCB_STATE_BUSY); - if (bNewDcb) { - if (Ext2DerefXcb(&Dcb->ReferenceCount) == 0) { - Ext2FreeFcb(Dcb); - } else { - DEBUG(DL_ERR, ( "Ext2DeleteFile: Dcb %wZ used by other threads.\n", - &Mcb->FullName )); - } - } + if (bFcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); } + if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } + if (Dcb) { + Ext2ReleaseFcb(Dcb); + } + Ext2DerefMcb(Mcb); } @@ -2112,4 +2069,4 @@ Ext2DeleteFile( &Mcb->FullName, ext3_free_blocks_count(SUPER_BLOCK))); return Status; -} +}
\ No newline at end of file diff --git a/Ext3Fsd/fsctl.c b/Ext3Fsd/fsctl.c index 0c3cbc8..d841e3b 100644 --- a/Ext3Fsd/fsctl.c +++ b/Ext3Fsd/fsctl.c @@ -1580,8 +1580,6 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) PEXT2_MCB Mcb = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; - BOOLEAN bNewParentDcb = FALSE; - BOOLEAN MainResourceAcquired = FALSE; PVOID InputBuffer; ULONG InputBufferLength; @@ -1598,6 +1596,8 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) PCHAR OemNameBuffer = NULL; int OemNameLength = 0, i; + BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN FcbLockAcquired = FALSE; __try { @@ -1612,19 +1612,26 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + FcbLockAcquired = TRUE; + ParentMcb = Mcb->Parent; ParentDcb = ParentMcb->Fcb; if (ParentDcb == NULL) { ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); - if (ParentDcb) { - Ext2ReferXcb(&ParentDcb->ReferenceCount); - bNewParentDcb = TRUE; - } + } + if (ParentDcb) { + Ext2ReferXcb(&ParentDcb->ReferenceCount); } if (!Mcb) __leave; + if (FcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + FcbLockAcquired = FALSE; + } + if (!ExAcquireResourceSharedLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { @@ -1700,6 +1707,11 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) } __finally { + if (FcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + FcbLockAcquired = FALSE; + } + if (MainResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } @@ -1717,16 +1729,6 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) FILE_ACTION_MODIFIED ); } - if (bNewParentDcb) { - ASSERT(ParentDcb != NULL); - if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) { - Ext2FreeFcb(ParentDcb); - ParentDcb = NULL; - } else { - DEBUG(DL_RES, ( "Ext2SetRenameInfo: ParentDcb is resued by other threads.\n")); - } - } - if (!AbnormalTermination()) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2QueueRequest(IrpContext); @@ -1734,6 +1736,10 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) Ext2CompleteIrpContext(IrpContext, Status); } } + + if (ParentDcb) { + Ext2ReleaseFcb(ParentDcb); + } } return Status; @@ -1784,13 +1790,14 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) PEXT2_CCB Ccb = NULL; PEXT2_MCB Mcb = NULL; + PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ + PEXT2_MCB ParentMcb = NULL; + NTSTATUS Status = STATUS_UNSUCCESSFUL; - BOOLEAN bNewParentDcb = FALSE; - BOOLEAN bFcbAllocated = FALSE; + + BOOLEAN FcbLockAcquired = FALSE; BOOLEAN MainResourceAcquired = FALSE; - PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ - PEXT2_MCB ParentMcb = NULL; __try { @@ -1803,14 +1810,16 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) Mcb = IrpContext->Fcb->Mcb; Irp = IrpContext->Irp; + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + FcbLockAcquired = TRUE; + ParentMcb = Mcb->Parent; ParentDcb = ParentMcb->Fcb; if (ParentDcb == NULL) { ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); - if (ParentDcb) { - Ext2ReferXcb(&ParentDcb->ReferenceCount); - bNewParentDcb = TRUE; - } + } + if (ParentDcb) { + Ext2ReferXcb(&ParentDcb->ReferenceCount); } if (!Mcb || !IsInodeSymLink(&Mcb->Inode) || @@ -1818,15 +1827,19 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) Status = STATUS_NOT_A_REPARSE_POINT; __leave; } - + Fcb = Ext2AllocateFcb (Vcb, Mcb); if (Fcb) { - bFcbAllocated = TRUE; + Ext2ReferXcb(&Fcb->ReferenceCount); } else { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; } - Ext2ReferXcb(&Fcb->ReferenceCount); + + if (FcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + FcbLockAcquired = FALSE; + } if (!ExAcquireResourceSharedLite( &Fcb->MainResource, @@ -1846,6 +1859,10 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) } __finally { + if (FcbLockAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + } + if (MainResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } @@ -1860,16 +1877,6 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) } - if (bNewParentDcb) { - ASSERT(ParentDcb != NULL); - if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) { - Ext2FreeFcb(ParentDcb); - ParentDcb = NULL; - } else { - DEBUG(DL_RES, ( "Ext2DeleteReparsePoint: ParentDcb is resued.\n")); - } - } - if (!AbnormalTermination()) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2QueueRequest(IrpContext); @@ -1877,11 +1884,13 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) Ext2CompleteIrpContext(IrpContext, Status); } } - - if (bFcbAllocated) { - if (Ext2DerefXcb(&Fcb->ReferenceCount) == 0) { - Ext2FreeFcb(Fcb); - } + + if (ParentDcb) { + Ext2ReleaseFcb(ParentDcb); + } + + if (Fcb) { + Ext2ReleaseFcb(Fcb); } } @@ -2448,13 +2457,7 @@ Ext2VerifyVolume (IN PEXT2_IRP_CONTEXT IrpContext) } else { Status = STATUS_WRONG_VOLUME; - if (VcbResourceAcquired) { - ExReleaseResourceLite(&Vcb->MainResource); - VcbResourceAcquired = FALSE; - } Ext2PurgeVolume(Vcb, FALSE); - VcbResourceAcquired = - ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); SetLongFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); @@ -2605,8 +2608,9 @@ Ext2CheckDismount ( ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); - if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && - (IrpContext->RealDevice == Vcb->RealDevice)) { + if (IrpContext && + IrpContext->MajorFunction == IRP_MJ_CREATE && + IrpContext->RealDevice == Vcb->RealDevice) { UnCleanCount = 2; } else { UnCleanCount = 1; @@ -2694,11 +2698,10 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb, IN BOOLEAN FlushBeforePurge ) { PEXT2_FCB Fcb; - LIST_ENTRY FcbList; - PLIST_ENTRY ListEntry; - PFCB_LIST_ENTRY FcbListEntry; + LIST_ENTRY List, *Next; BOOLEAN VcbResourceAcquired = FALSE; + BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN gdResourceAcquired = FALSE; __try { @@ -2707,46 +2710,32 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb, ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); - VcbResourceAcquired = - ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + VcbResourceAcquired = TRUE; if (IsVcbReadOnly(Vcb)) { FlushBeforePurge = FALSE; } - FcbListEntry= NULL; - InitializeListHead(&FcbList); + InitializeListHead(&List); - for (ListEntry = Vcb->FcbList.Flink; - ListEntry != &Vcb->FcbList; - ListEntry = ListEntry->Flink ) { - - Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next); + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + FcbResourceAcquired = TRUE; - DEBUG(DL_INF, ( "Ext2PurgeVolume: %wZ refercount=%xh\n", &Fcb->Mcb->FullName, Fcb->ReferenceCount)); + while (!IsListEmpty(&Vcb->FcbList)) { - FcbListEntry = Ext2AllocatePool( - PagedPool, - sizeof(FCB_LIST_ENTRY), - EXT2_FLIST_MAGIC - ); + Next = RemoveHeadList(&Vcb->FcbList); + Fcb = CONTAINING_RECORD(Next, EXT2_FCB, Next); - if (FcbListEntry) { - Ext2ReferXcb(&Fcb->ReferenceCount); - FcbListEntry->Fcb = Fcb; - InsertTailList(&FcbList, &FcbListEntry->Next); - } else { - DEBUG(DL_ERR, ( "Ext2PurgeVolume: failed to allocate FcbListEntry ...\n")); - } + DEBUG(DL_INF, ( "Ext2PurgeVolume: %wZ refercount=%xh\n", + &Fcb->Mcb->FullName, Fcb->ReferenceCount)); + InsertTailList(&List, &Fcb->Next); } - while (!IsListEmpty(&FcbList)) { + while (!IsListEmpty(&List)) { - ListEntry = RemoveHeadList(&FcbList); - - FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next); - - Fcb = FcbListEntry->Fcb; + Next = RemoveHeadList(&List); + Fcb = CONTAINING_RECORD(Next, EXT2_FCB, Next); if (ExAcquireResourceExclusiveLite( &Fcb->MainResource, @@ -2754,16 +2743,20 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb, Ext2PurgeFile(Fcb, FlushBeforePurge); - if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1) { - Ext2FreeFcb(Fcb); + if (Fcb->ReferenceCount <= 1) { + Fcb->TsDrop.QuadPart = 0; + InsertHeadList(&Vcb->FcbList, &Fcb->Next); } else { - ExReleaseResourceLite(&Fcb->MainResource); + InsertTailList(&Vcb->FcbList, &Fcb->Next); } + ExReleaseResourceLite(&Fcb->MainResource); } - - Ext2FreePool(FcbListEntry, EXT2_FLIST_MAGIC); } + if (FcbResourceAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + FcbResourceAcquired = FALSE; + } /* acquire bd lock to avoid bh creation */ ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE); @@ -2795,6 +2788,10 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb, ExReleaseResourceLite(&Vcb->sbi.s_gd_lock); } + if (FcbResourceAcquired) { + ExReleaseResourceLite(&Vcb->FcbLock); + } + if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } @@ -2816,30 +2813,23 @@ Ext2PurgeFile ( IN PEXT2_FCB Fcb, if (!IsVcbReadOnly(Fcb->Vcb) && FlushBeforePurge) { - DEBUG(DL_INF, ( "Ext2PurgeFile: CcFlushCache on %wZ.\n", &Fcb->Mcb->FullName)); - ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); ExReleaseResourceLite(&Fcb->PagingIoResource); - CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus); ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); } if (Fcb->SectionObject.ImageSectionObject) { - DEBUG(DL_INF, ( "Ext2PurgeFile: MmFlushImageSection on %wZ.\n", &Fcb->Mcb->FullName)); - MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite); } if (Fcb->SectionObject.DataSectionObject) { - DEBUG(DL_INF, ( "Ext2PurgeFile: CcPurgeCacheSection on %wZ.\n", &Fcb->Mcb->FullName)); - CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE); } diff --git a/Ext3Fsd/include/ext2fs.h b/Ext3Fsd/include/ext2fs.h index bb0fffc..288b38d 100755 --- a/Ext3Fsd/include/ext2fs.h +++ b/Ext3Fsd/include/ext2fs.h @@ -479,6 +479,7 @@ typedef PVOID PBCB; typedef VOID (*EXT2_REAPER_RELEASE)(PVOID); typedef struct _EXT2_REAPER { + PETHREAD Thread; KEVENT Engine; KEVENT Wait; EXT2_REAPER_RELEASE Free; @@ -522,6 +523,7 @@ typedef struct _EXT2_GLOBAL { LIST_ENTRY VcbList; /* Cleaning thread related: resource cleaner */ + EXT2_REAPER FcbReaper; EXT2_REAPER McbReaper; EXT2_REAPER bhReaper; @@ -654,7 +656,7 @@ typedef struct _EXT2_VCB { // List of FCBs for open files on this volume ULONG FcbCount; LIST_ENTRY FcbList; - KSPIN_LOCK FcbLock; + ERESOURCE FcbLock; // Share Access for the file object SHARE_ACCESS ShareAccess; @@ -805,6 +807,7 @@ typedef struct _EXT2_FCB { // List of FCBs for this volume LIST_ENTRY Next; + LARGE_INTEGER TsDrop; /* drop time */ SECTION_OBJECT_POINTERS SectionObject; @@ -851,7 +854,7 @@ typedef struct _EXT2_FCB { #define FCB_FROM_POOL 0x00000001 #define FCB_PAGE_FILE 0x00000002 #define FCB_FILE_MODIFIED 0x00000020 -#define FCB_STATE_BUSY 0x00000040 + #define FCB_ALLOC_IN_CREATE 0x00000080 #define FCB_ALLOC_IN_WRITE 0x00000100 #define FCB_ALLOC_IN_SETINFO 0x00000200 @@ -946,12 +949,10 @@ struct _EXT2_MCB { #define Ext2DerefXcb(_C) DEC_OBJ_CNT(_C) __inline ULONG DEC_OBJ_CNT(PULONG _C) { - if (*_C > 0) { - return InterlockedDecrement(_C); - } else { + if (*_C <= 0) { DbgBreak(); } - return 0; + return InterlockedDecrement(_C); } #if EXT2_DEBUG @@ -2484,6 +2485,11 @@ Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext); // VOID +Ext2FcbReaperThread( + PVOID Context +); + +VOID Ext2McbReaperThread( PVOID Context ); @@ -2509,13 +2515,15 @@ Ext2AllocateFcb ( ); VOID -Ext2FreeFcb (IN PEXT2_FCB Fcb); +Ext2UnlinkFcb(IN PEXT2_FCB Fcb); VOID -Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb); +Ext2FreeFcb (IN PEXT2_FCB Fcb); +VOID +Ext2ReleaseFcb (IN PEXT2_FCB Fcb); VOID -Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb); +Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb); PEXT2_CCB Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink); diff --git a/Ext3Fsd/init.c b/Ext3Fsd/init.c index e2f39e1..53efdcc 100755 --- a/Ext3Fsd/init.c +++ b/Ext3Fsd/init.c @@ -429,6 +429,7 @@ Ext2EresourceAlignmentChecking() CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaInode) & 7) == 0); CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaBlock) & 7) == 0); CL_ASSERT((FIELD_OFFSET(EXT2_VCB, McbLock) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, FcbLock) & 7) == 0); CL_ASSERT((FIELD_OFFSET(EXT2_VCB, bd.bd_bh_lock) & 7) == 0); CL_ASSERT((FIELD_OFFSET(EXT2_VCB, sbi.s_gd_lock) & 7) == 0); CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0); @@ -553,11 +554,19 @@ DriverEntry ( goto errorout; } + Status= Ext2StartReaper( + &Ext2Global->FcbReaper, + Ext2FcbReaperThread); + if (!NT_SUCCESS(Status)) { + goto errorout; + } + /* start resource reaper thread */ Status= Ext2StartReaper( &Ext2Global->McbReaper, Ext2McbReaperThread); if (!NT_SUCCESS(Status)) { + Ext2StopReaper(&Ext2Global->FcbReaper); goto errorout; } @@ -565,6 +574,7 @@ DriverEntry ( &Ext2Global->bhReaper, Ext2bhReaperThread); if (!NT_SUCCESS(Status)) { + Ext2StopReaper(&Ext2Global->FcbReaper); Ext2StopReaper(&Ext2Global->McbReaper); goto errorout; } diff --git a/Ext3Fsd/memory.c b/Ext3Fsd/memory.c index 37ff709..975edf9 100755 --- a/Ext3Fsd/memory.c +++ b/Ext3Fsd/memory.c @@ -18,15 +18,11 @@ extern PEXT2_GLOBAL Ext2Global; /* DEFINITIONS *************************************************************/ #ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, Ext2AllocateFcb) -#pragma alloc_text(PAGE, Ext2FreeFcb) #pragma alloc_text(PAGE, Ext2AllocateInode) #pragma alloc_text(PAGE, Ext2DestroyInode) #pragma alloc_text(PAGE, Ext2CheckBitmapConsistency) #pragma alloc_text(PAGE, Ext2CheckSetBlock) #pragma alloc_text(PAGE, Ext2InitializeVcb) -#pragma alloc_text(PAGE, Ext2FreeCcb) -#pragma alloc_text(PAGE, Ext2AllocateCcb) #pragma alloc_text(PAGE, Ext2TearDownStream) #pragma alloc_text(PAGE, Ext2DestroyVcb) #pragma alloc_text(PAGE, Ext2SyncUninitializeCacheMap) @@ -139,6 +135,8 @@ Ext2AllocateFcb ( { PEXT2_FCB Fcb; + ASSERT(ExIsResourceAcquiredExclusiveLite(&Vcb->FcbLock)); + Fcb = (PEXT2_FCB) ExAllocateFromNPagedLookasideList( &(Ext2Global->Ext2FcbLookasideList)); @@ -201,84 +199,121 @@ Ext2AllocateFcb ( } VOID -Ext2FreeFcb (IN PEXT2_FCB Fcb) +Ext2UnlinkFcb(IN PEXT2_FCB Fcb) { - PEXT2_VCB Vcb = Fcb->Vcb; + PEXT2_VCB Vcb = Fcb->Vcb; + PEXT2_MCB Mcb; - ASSERT((Fcb != NULL) && (Fcb->Identifier.Type == EXT2FCB) && - (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - ASSERT((Fcb->Mcb->Identifier.Type == EXT2MCB) && - (Fcb->Mcb->Identifier.Size == sizeof(EXT2_MCB))); + ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE); + Mcb = Fcb->Mcb; -#ifndef _WIN2K_TARGET_ - FsRtlTeardownPerStreamContexts(&Fcb->Header); -#endif + DEBUG(DL_ERR, ("Ext2FreeFcb: Fcb (%p) to be unlinked: %wZ.\n", + Fcb, Mcb ? &Mcb->FullName : NULL)); - if ((Fcb->Mcb->Identifier.Type == EXT2MCB) && - (Fcb->Mcb->Identifier.Size == sizeof(EXT2_MCB))) { + if ((Mcb != NULL) && + (Mcb->Identifier.Type == EXT2MCB) && + (Mcb->Identifier.Size == sizeof(EXT2_MCB))) { - ASSERT (Fcb->Mcb->Fcb == Fcb); - if (IsMcbSpecialFile(Fcb->Mcb) || IsFileDeleted(Fcb->Mcb)) { + ASSERT (Mcb->Fcb == Fcb); + if (IsMcbSpecialFile(Mcb) || + IsFileDeleted(Mcb)) { ASSERT(!IsRoot(Fcb)); - Ext2RemoveMcb(Fcb->Vcb, Fcb->Mcb); - Fcb->Mcb->Fcb = NULL; + Ext2RemoveMcb(Vcb, Mcb); + Mcb->Fcb = NULL; - Ext2UnlinkMcb(Vcb, Fcb->Mcb); - Ext2DerefMcb(Fcb->Mcb); - Ext2LinkHeadMcb(Vcb, Fcb->Mcb); + Ext2UnlinkMcb(Vcb, Mcb); + Ext2DerefMcb(Mcb); + Ext2LinkHeadMcb(Vcb, Mcb); } else { - - Fcb->Mcb->Fcb = NULL; - Ext2DerefMcb(Fcb->Mcb); + Mcb->Fcb = NULL; + Ext2DerefMcb(Mcb); } - - } else { - DbgBreak(); + Fcb->Mcb = NULL; } - Ext2RemoveFcb(Fcb->Vcb, Fcb); + ExReleaseResourceLite(&Vcb->McbLock); +} - FsRtlUninitializeFileLock(&Fcb->FileLockAnchor); - FsRtlUninitializeOplock(&Fcb->Oplock); - ExDeleteResourceLite(&Fcb->MainResource); - ExDeleteResourceLite(&Fcb->PagingIoResource); +VOID +Ext2FreeFcb (IN PEXT2_FCB Fcb) +{ + PEXT2_VCB Vcb = Fcb->Vcb; - DEBUG(DL_RES, ( "Ext2FreeFcb: Fcb (%p) is being released: %wZ.\n", - Fcb, &Fcb->Mcb->FullName)); + __try { - Fcb->Identifier.Type = 0; - Fcb->Identifier.Size = 0; + ASSERT((Fcb != NULL) && (Fcb->Identifier.Type == EXT2FCB) && + (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + ASSERT(0 == Fcb->ReferenceCount); - ExFreeToNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList), Fcb); - DEC_MEM_COUNT(PS_FCB, Fcb, sizeof(EXT2_FCB)); -} +#ifndef _WIN2K_TARGET_ + FsRtlTeardownPerStreamContexts(&Fcb->Header); +#endif -/* Insert Fcb to Vcb->FcbList queue */ + FsRtlUninitializeFileLock(&Fcb->FileLockAnchor); + FsRtlUninitializeOplock(&Fcb->Oplock); + ExDeleteResourceLite(&Fcb->MainResource); + ExDeleteResourceLite(&Fcb->PagingIoResource); + + Fcb->Identifier.Type = 0; + Fcb->Identifier.Size = 0; + + ExFreeToNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList), Fcb); + DEC_MEM_COUNT(PS_FCB, Fcb, sizeof(EXT2_FCB)); + + if (0 == Ext2DerefXcb(&Vcb->ReferenceCount)) { + if (!IsMounted(Vcb) || IsDispending(Vcb)) { + Ext2CheckDismount(NULL, Vcb, FALSE); + } + } + + } __finally { + } +} VOID -Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb) +Ext2ReleaseFcb (IN PEXT2_FCB Fcb) { - ExInterlockedInsertTailList(&Vcb->FcbList, &Fcb->Next, &Vcb->FcbLock); - Ext2ReferXcb(&Vcb->FcbCount); + PEXT2_VCB Vcb = Fcb->Vcb; + PEXT2_MCB Mcb; + + if (0 != Ext2DerefXcb(&Fcb->ReferenceCount)) + return; + + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); + + Mcb = Fcb->Mcb; + RemoveEntryList(&Fcb->Next); + + if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) || + NULL == Mcb || IsFileDeleted(Mcb)) { + InsertHeadList(&Vcb->FcbList, &Fcb->Next); + Fcb->TsDrop.QuadPart = 0; + } else { + InsertTailList(&Vcb->FcbList, &Fcb->Next); + KeQuerySystemTime(&Fcb->TsDrop); + } + ExReleaseResourceLite(&Fcb->MainResource); + ExReleaseResourceLite(&Vcb->FcbLock); + + if ((Vcb->FcbCount >> 6) > (ULONG)(Ext2Global->MaxDepth)) { + KeSetEvent(&Ext2Global->FcbReaper.Wait, 0, FALSE); + } } -/* Remove Fcb from Vcb->FcbList queue */ +/* Insert Fcb to Vcb->FcbList queue, with Vcb->FcbLock Acquired. */ VOID -Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb) +Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb) { - KIRQL irql; + ASSERT(ExIsResourceAcquiredExclusiveLite(&Vcb->FcbLock)); - KeAcquireSpinLock(&Vcb->FcbLock, &irql); - RemoveEntryList(&(Fcb->Next)); - if (Vcb->FcbCount > 0) { - Ext2DerefXcb(&Vcb->FcbCount); - } else { - DbgBreak(); - } - KeReleaseSpinLock(&Vcb->FcbLock, irql); + KeQuerySystemTime(&Fcb->TsDrop); + Ext2ReferXcb(&Vcb->FcbCount); + Ext2ReferXcb(&Vcb->ReferenceCount); + InsertTailList(&Vcb->FcbList, &Fcb->Next); } PEXT2_CCB @@ -321,7 +356,6 @@ VOID Ext2FreeCcb (IN PEXT2_VCB Vcb, IN PEXT2_CCB Ccb) { ASSERT(Ccb != NULL); - ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB))); @@ -2325,7 +2359,7 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext, /* initialize Fcb list head */ InitializeListHead(&Vcb->FcbList); - KeInitializeSpinLock(&Vcb->FcbLock); + ExInitializeResourceLite(&Vcb->FcbLock); /* initialize Mcb list head */ InitializeListHead(&(Vcb->McbList)); @@ -2796,6 +2830,7 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb) ObDereferenceObject(Vcb->TargetDeviceObject); ExDeleteNPagedLookasideList(&(Vcb->InodeLookasideList)); + ExDeleteResourceLite(&Vcb->FcbLock); ExDeleteResourceLite(&Vcb->McbLock); ExDeleteResourceLite(&Vcb->MetaInode); ExDeleteResourceLite(&Vcb->MetaBlock); @@ -2985,6 +3020,8 @@ Ext2McbReaperThread( __try { + Reaper->Thread = PsGetCurrentThread(); + /* wake up DirverEntry */ KeSetEvent(&Reaper->Engine, 0, FALSE); @@ -3088,24 +3125,26 @@ Ext2McbReaperThread( } -/* get the first Mcb record in Vcb->McbList */ +/* get buffer heads from global Vcb BH list */ BOOLEAN Ext2QueryUnusedBH(PEXT2_VCB Vcb, PLIST_ENTRY head) { struct buffer_head *bh = NULL; - PLIST_ENTRY list = NULL; - LARGE_INTEGER now; - BOOLEAN wake = FALSE; + PLIST_ENTRY next = NULL; + LARGE_INTEGER now; + BOOLEAN wake = FALSE; KeQuerySystemTime(&now); ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE); + while (!IsListEmpty(&Vcb->bd.bd_bh_free)) { - list = RemoveHeadList(&Vcb->bd.bd_bh_free); - bh = CONTAINING_RECORD(list, struct buffer_head, b_link); + next = RemoveHeadList(&Vcb->bd.bd_bh_free); + bh = CONTAINING_RECORD(next, struct buffer_head, b_link); if (atomic_read(&bh->b_count)) { InitializeListHead(&bh->b_link); + /* to be inserted by brelse */ continue; } @@ -3118,6 +3157,7 @@ Ext2QueryUnusedBH(PEXT2_VCB Vcb, PLIST_ENTRY head) break; } } + wake = IsListEmpty(&Vcb->bd.bd_bh_free); ExReleaseResourceLite(&Vcb->bd.bd_bh_lock); @@ -3145,6 +3185,8 @@ Ext2bhReaperThread( __try { + Reaper->Thread = PsGetCurrentThread(); + /* wake up DirverEntry */ KeSetEvent(&Reaper->Engine, 0, FALSE); @@ -3182,8 +3224,7 @@ Ext2bhReaperThread( Link = Link->Flink ) { Vcb = CONTAINING_RECORD(Link, EXT2_VCB, Next); - if (Ext2QueryUnusedBH(Vcb, &List)) - NonWait = TRUE; + NonWait = Ext2QueryUnusedBH(Vcb, &List); } if (GlobalAcquired) { ExReleaseResourceLite(&Ext2Global->Resource); @@ -3212,6 +3253,146 @@ Ext2bhReaperThread( PsTerminateSystemThread(STATUS_SUCCESS); } +/* get unused Fcbs to free */ + +BOOLEAN +Ext2QueryUnusedFcb(PEXT2_VCB Vcb, PLIST_ENTRY list) +{ + PEXT2_FCB Fcb; + PLIST_ENTRY next = NULL; + LARGE_INTEGER now; + + ULONG count = 0; + ULONG tries = 0; + BOOLEAN wake = FALSE; + BOOLEAN retry = TRUE; + + KeQuerySystemTime(&now); + + ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); + +again: + + while (!IsListEmpty(&Vcb->FcbList)) { + + next = RemoveHeadList(&Vcb->FcbList); + Fcb = CONTAINING_RECORD(next, EXT2_FCB, Next); + + if (Fcb->ReferenceCount > 0) { + InsertTailList(&Vcb->FcbList, &Fcb->Next); + break; + } + + retry = FALSE; + + if (now.QuadPart < Fcb->TsDrop.QuadPart + 10*1000*1000*120) { + InsertHeadList(&Vcb->FcbList, &Fcb->Next); + break; + } + + Ext2UnlinkFcb(Fcb); + Ext2DerefXcb(&Vcb->FcbCount); + InsertTailList(list, &Fcb->Next); + if (++count >= Ext2Global->MaxDepth) { + break; + } + } + + if (retry) { + if (++tries < (Vcb->FcbCount >> 4) ) + goto again; + } + + ExReleaseResourceLite(&Vcb->FcbLock); + + return 0; +} + +/* Reaper thread to release Fcb */ +VOID +Ext2FcbReaperThread( + PVOID Context +) +{ + PEXT2_REAPER Reaper = Context; + PEXT2_VCB Vcb = NULL; + LIST_ENTRY List, *Link; + LARGE_INTEGER Timeout; + + BOOLEAN GlobalAcquired = FALSE; + BOOLEAN DidNothing = FALSE; + BOOLEAN NonWait = FALSE; + + __try { + + Reaper->Thread = PsGetCurrentThread(); + + /* wake up DirverEntry */ + KeSetEvent(&Reaper->Engine, 0, FALSE); + + /* now process looping */ + while (!IsFlagOn(Reaper->Flags, EXT2_REAPER_FLAG_STOP)) { + + /* wait until it is waken or it times out */ + if (NonWait) { + Timeout.QuadPart = (LONGLONG)-10*1000*100; + NonWait = FALSE; + } else if (DidNothing) { + Timeout.QuadPart = Timeout.QuadPart * 2; + } else { + Timeout.QuadPart = (LONGLONG)-10*1000*1000*20; /* 20 seconds */ + } + KeWaitForSingleObject( + &Reaper->Wait, + Executive, + KernelMode, + FALSE, + &Timeout + ); + + if (IsFlagOn(Reaper->Flags, EXT2_REAPER_FLAG_STOP)) + break; + + InitializeListHead(&List); + + /* acquire global exclusive lock */ + ExAcquireResourceSharedLite(&Ext2Global->Resource, TRUE); + GlobalAcquired = TRUE; + /* search all Vcb to get unused resources freed to system */ + for (Link = Ext2Global->VcbList.Flink; + Link != &(Ext2Global->VcbList); + Link = Link->Flink ) { + + Vcb = CONTAINING_RECORD(Link, EXT2_VCB, Next); + NonWait = Ext2QueryUnusedFcb(Vcb, &List); + } + if (GlobalAcquired) { + ExReleaseResourceLite(&Ext2Global->Resource); + GlobalAcquired = FALSE; + } + + DidNothing = IsListEmpty(&List); + while (!IsListEmpty(&List)) { + PEXT2_FCB Fcb; + Link = RemoveHeadList(&List); + Fcb = CONTAINING_RECORD(Link, EXT2_FCB, Next); + ASSERT(0 == Fcb->ReferenceCount); + Ext2FreeFcb(Fcb); + } + } + + } __finally { + + if (GlobalAcquired) { + ExReleaseResourceLite(&Ext2Global->Resource); + } + + KeSetEvent(&Reaper->Engine, 0, FALSE); + } + + PsTerminateSystemThread(STATUS_SUCCESS); +} + NTSTATUS Ext2StartReaper(PEXT2_REAPER Reaper, EXT2_REAPER_RELEASE Free) { |