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:
Diffstat (limited to 'Ext3Fsd/close.c')
-rw-r--r--Ext3Fsd/close.c125
1 files changed, 45 insertions, 80 deletions
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;