Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matt-wu/Ext3Fsd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Wu <matt@ext2fsd.com>2016-04-27 19:42:05 +0300
committerMatt Wu <matt@ext2fsd.com>2016-04-27 19:42:05 +0300
commit8573bc8c1192be6e1f34745dbbb814f9b7fcdd79 (patch)
tree0bf4e9cf88e5c778f917818514a0efcb5ca2924d
parent5886485e82d1880a20d320a98915e341a1aabbcc (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-xExt3Fsd/cleanup.c86
-rw-r--r--Ext3Fsd/close.c125
-rwxr-xr-xExt3Fsd/create.c84
-rwxr-xr-xExt3Fsd/fileinfo.c171
-rw-r--r--Ext3Fsd/fsctl.c176
-rwxr-xr-xExt3Fsd/include/ext2fs.h26
-rwxr-xr-xExt3Fsd/init.c10
-rwxr-xr-xExt3Fsd/memory.c311
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)
{