Author: pschweitzer
Date: Fri Jul 29 10:29:16 2016
New Revision: 72042
URL:
http://svn.reactos.org/svn/reactos?rev=72042&view=rev
Log:
[EXT2]
Upgrade the driver to release 0.68.
CORE-11714
Modified:
trunk/reactos/drivers/filesystems/ext2/inc/ext2fs.h
trunk/reactos/drivers/filesystems/ext2/src/block.c
trunk/reactos/drivers/filesystems/ext2/src/cleanup.c
trunk/reactos/drivers/filesystems/ext2/src/close.c
trunk/reactos/drivers/filesystems/ext2/src/create.c
trunk/reactos/drivers/filesystems/ext2/src/ext3/generic.c
trunk/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c
trunk/reactos/drivers/filesystems/ext2/src/fileinfo.c
trunk/reactos/drivers/filesystems/ext2/src/flush.c
trunk/reactos/drivers/filesystems/ext2/src/fsctl.c
trunk/reactos/drivers/filesystems/ext2/src/init.c
trunk/reactos/drivers/filesystems/ext2/src/memory.c
trunk/reactos/drivers/filesystems/ext2/src/write.c
trunk/reactos/media/doc/README.FSD
Modified: trunk/reactos/drivers/filesystems/ext2/inc/ext2fs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/i…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/inc/ext2fs.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/inc/ext2fs.h [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -47,7 +47,7 @@
/* STRUCTS & CONSTS******************************************************/
-#define EXT2FSD_VERSION "0.66"
+#define EXT2FSD_VERSION "0.68"
/* WDK DEFINITIONS ******************************************************/
@@ -491,6 +491,7 @@
typedef VOID (NTAPI *EXT2_REAPER_RELEASE)(PVOID);
typedef struct _EXT2_REAPER {
+ PETHREAD Thread;
KEVENT Engine;
KEVENT Wait;
EXT2_REAPER_RELEASE Free;
@@ -534,6 +535,7 @@
LIST_ENTRY VcbList;
/* Cleaning thread related: resource cleaner */
+ EXT2_REAPER FcbReaper;
EXT2_REAPER McbReaper;
EXT2_REAPER bhReaper;
@@ -647,13 +649,18 @@
// Resource for Mcb (Meta data control block)
ERESOURCE McbLock;
+ // List of FCBs for open files on this volume
+ ERESOURCE FcbLock;
+ LIST_ENTRY FcbList;
+ ULONG FcbCount;
+
+ // Mcb list
+ ULONG NumOfMcb;
+ LIST_ENTRY McbList;
+
// Entry of Mcb Tree (Root Node)
PEXT2_MCB McbTree;
- // Mcb list
- LIST_ENTRY McbList;
- ULONG NumOfMcb;
-
// Link list to Global
LIST_ENTRY Next;
@@ -663,10 +670,6 @@
// Dirty Mcbs of modifications for volume stream
LARGE_MCB Extents;
- // List of FCBs for open files on this volume
- ULONG FcbCount;
- LIST_ENTRY FcbList;
- KSPIN_LOCK FcbLock;
// Share Access for the file object
SHARE_ACCESS ShareAccess;
@@ -817,6 +820,7 @@
// List of FCBs for this volume
LIST_ENTRY Next;
+ LARGE_INTEGER TsDrop; /* drop time */
SECTION_OBJECT_POINTERS SectionObject;
@@ -863,7 +867,7 @@
#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
@@ -961,12 +965,10 @@
static
#endif
__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
@@ -1774,7 +1776,7 @@
Ext2PutGroup(IN PEXT2_VCB Vcb);
VOID
-Ext2DropGroup(IN PEXT2_VCB Vcb);
+Ext2DropBH(IN PEXT2_VCB Vcb);
BOOLEAN
Ext2SaveGroup(
@@ -2438,7 +2440,6 @@
int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry,
struct inode *inode, struct ext3_dir_entry_2 *de,
struct buffer_head *bh);
-
#if !defined(__REACTOS__) || defined(_MSC_VER)
struct ext3_dir_entry_2 *
do_split(struct ext2_icb *icb, struct inode *dir,
@@ -2525,6 +2526,12 @@
VOID
NTAPI
+Ext2FcbReaperThread(
+ PVOID Context
+);
+
+VOID
+NTAPI
Ext2McbReaperThread(
PVOID Context
);
@@ -2551,13 +2558,15 @@
);
VOID
+Ext2UnlinkFcb(IN PEXT2_FCB Fcb);
+
+VOID
Ext2FreeFcb (IN PEXT2_FCB Fcb);
+VOID
+Ext2ReleaseFcb (IN PEXT2_FCB Fcb);
VOID
Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb);
-
-VOID
-Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb);
PEXT2_CCB
Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink);
Modified: trunk/reactos/drivers/filesystems/ext2/src/block.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/block.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/block.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -351,7 +351,7 @@
IoBuildPartialMdl( MasterIrp->MdlAddress,
Mdl,
- (PCHAR)MasterIrp->UserBuffer +Extent->Offset,
+ (PCHAR)MasterIrp->UserBuffer+Extent->Offset,
Extent->Length );
IoSetNextIrpStackLocation(Irp);
@@ -568,8 +568,7 @@
FALSE );
if (!NT_SUCCESS(Status)) {
- DEBUG(DL_ERR, ( "Ext2ReadDisk: disk device error.\n"));
-
+ DEBUG(DL_ERR, ("Ext2ReadDisk: disk i/o error: %xh.\n", Status));
goto errorout;
}
Modified: trunk/reactos/drivers/filesystems/ext2/src/cleanup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/cleanup.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/cleanup.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -73,13 +73,11 @@
_SEH2_LEAVE;
}
- VcbResourceAcquired =
+ if (Fcb->Identifier.Type == EXT2VCB) {
+
ExAcquireResourceExclusiveLite(
- &Vcb->MainResource,
- TRUE
- );
-
- if (Fcb->Identifier.Type == EXT2VCB) {
+ &Vcb->MainResource, TRUE);
+ VcbResourceAcquired = TRUE;
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
Vcb->LockFile == FileObject ){
@@ -102,6 +100,12 @@
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) &&
@@ -135,17 +139,7 @@
}
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 @@
}
}
+ 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 @@
}
}
- 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));
Modified: trunk/reactos/drivers/filesystems/ext2/src/close.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/close.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/close.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -31,11 +31,10 @@
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;
_SEH2_TRY {
@@ -54,25 +53,6 @@
ASSERT(Vcb != NULL);
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;
- _SEH2_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)) {
@@ -92,10 +72,29 @@
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;
+ _SEH2_LEAVE;
+ }
+ VcbResourceAcquired = TRUE;
if (Ccb) {
@@ -112,7 +111,7 @@
}
if ( Fcb->Identifier.Type != EXT2FCB ||
- Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
+ Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
_SEH2_LEAVE;
}
@@ -126,67 +125,39 @@
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
- if (!Ccb) {
+ if (Ccb == NULL ||
+ Ccb->Identifier.Type != EXT2CCB ||
+ Ccb->Identifier.Size != sizeof(EXT2_CCB)) {
Status = STATUS_SUCCESS;
- _SEH2_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;
_SEH2_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;
- }
- }
-
- if (0 == Ext2DerefXcb(&Fcb->ReferenceCount)) {
-
- //
- // Remove Fcb from Vcb->FcbList ...
- //
-
- if (FcbResourceAcquired) {
- ExReleaseResourceLite(&Fcb->MainResource);
- FcbResourceAcquired = FALSE;
- }
-
- Ext2FreeFcb(Fcb);
-
- if (FileObject) {
- FileObject->FsContext = Fcb = NULL;
- }
- }
-
+ Ext2FreeCcb(Vcb, Ccb);
+ if (FileObject) {
+ FileObject->FsContext2 = Ccb = NULL;
+ }
+
+ /* 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 = NULL;
+ }
+
Status = STATUS_SUCCESS;
} _SEH2_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 @@
} 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);
} _SEH2_END;
return Status;
Modified: trunk/reactos/drivers/filesystems/ext2/src/create.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/create.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/create.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -698,13 +698,14 @@
ULONG CreateDisposition;
BOOLEAN bParentFcbCreated = FALSE;
-
#ifndef __REACTOS__
BOOLEAN bDir = FALSE;
#endif
BOOLEAN bFcbAllocated = FALSE;
BOOLEAN bCreated = FALSE;
+
BOOLEAN bMainResourceAcquired = FALSE;
+ BOOLEAN bFcbLockAcquired = FALSE;
BOOLEAN OpenDirectory;
BOOLEAN OpenTargetDirectory;
@@ -776,14 +777,14 @@
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;
@@ -811,7 +812,7 @@
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;
_SEH2_LEAVE;
}
@@ -952,9 +953,9 @@
_SEH2_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 ... */
@@ -966,9 +967,13 @@
_SEH2_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 ) ||
@@ -1157,6 +1162,12 @@
}
Openit:
+
+ if (!bFcbLockAcquired) {
+ ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
+ bFcbLockAcquired = TRUE;
+ }
+
/* Mcb should already be referred and symlink is too */
if (Mcb) {
@@ -1221,10 +1232,15 @@
}
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;
@@ -1565,6 +1581,9 @@
} _SEH2_FINALLY {
+ if (bFcbLockAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ }
if (ParentMcb) {
Ext2DerefMcb(ParentMcb);
@@ -1606,29 +1625,24 @@
Ext2FreeCcb(Vcb, Ccb);
}
- }
-
- if (Fcb && Ext2DerefXcb(&Fcb->ReferenceCount) == 0) {
-
- if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
-
- LARGE_INTEGER Size;
- ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
- _SEH2_TRY {
- Size.QuadPart = 0;
- Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
- } _SEH2_FINALLY {
- ExReleaseResourceLite(&Fcb->PagingIoResource);
- } _SEH2_END;
- }
-
- if (bCreated) {
- Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
- }
-
- Ext2FreeFcb(Fcb);
- Fcb = NULL;
- bMainResourceAcquired = FALSE;
+
+ if (Fcb != NULL) {
+
+ if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
+ LARGE_INTEGER Size;
+ ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
+ _SEH2_TRY {
+ Size.QuadPart = 0;
+ Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
+ } _SEH2_FINALLY {
+ ExReleaseResourceLite(&Fcb->PagingIoResource);
+ } _SEH2_END;
+ }
+
+ if (bCreated) {
+ Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
+ }
+ }
}
if (bMainResourceAcquired) {
@@ -1641,14 +1655,12 @@
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
Modified: trunk/reactos/drivers/filesystems/ext2/src/ext3/generic.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/ext3/generic.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/ext3/generic.c [iso-8859-1] Fri Jul 29
10:29:16 2016
@@ -48,9 +48,6 @@
bVerify );
if (!NT_SUCCESS(Status)) {
-
- DEBUG(DL_ERR, ( "Ext2ReadDisk: disk device error.\n"));
-
Ext2FreePool(Ext2Sb, EXT2_SB_MAGIC);
Ext2Sb = NULL;
}
@@ -209,7 +206,7 @@
VOID
-Ext2DropGroup(IN PEXT2_VCB Vcb)
+Ext2DropBH(IN PEXT2_VCB Vcb)
{
struct ext3_sb_info *sbi = &Vcb->sbi;
LARGE_INTEGER timeout;
@@ -220,17 +217,26 @@
return;
_SEH2_TRY {
+
+ /* acquire bd lock to avoid bh creation */
+ ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE);
+
SetFlag(Vcb->Flags, VCB_BEING_DROPPED);
- ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
Ext2PutGroup(Vcb);
+
+ while (!IsListEmpty(&Vcb->bd.bd_bh_free)) {
+ struct buffer_head *bh;
+ PLIST_ENTRY l;
+ l = RemoveHeadList(&Vcb->bd.bd_bh_free);
+ bh = CONTAINING_RECORD(l, struct buffer_head, b_link);
+ ASSERT(0 == atomic_read(&bh->b_count));
+ free_buffer_head(bh);
+ }
+
} _SEH2_FINALLY {
- ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
+ ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
} _SEH2_END;
- timeout.QuadPart = (LONGLONG)-10*1000*1000;
- KeWaitForSingleObject(&Vcb->bd.bd_bh_notify,
- Executive, KernelMode,
- FALSE, &timeout);
ClearFlag(Vcb->Flags, VCB_BEING_DROPPED);
}
Modified: trunk/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c [iso-8859-1]
(original)
+++ trunk/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c [iso-8859-1] Fri Jul 29
10:29:16 2016
@@ -1099,77 +1099,6 @@
return err;
}
-static int ext4_ext_shrink_indepth(void *icb,
- handle_t *handle,
- struct inode *inode,
- unsigned int flags,
- int *shrinked)
-{
- struct ext4_extent_header *eh, *neh;
- struct ext4_extent_idx *ix;
- struct buffer_head *bh = NULL;
- ext4_fsblk_t block;
- int err = 0, depth = ext_depth(inode);
- int neh_entries;
- *shrinked = 0;
-
- if (!depth)
- return 0;
-
- eh = ext_inode_hdr(inode);
- if (le16_to_cpu(eh->eh_entries) != 1)
- return 0;
-
- ix = EXT_FIRST_INDEX(eh);
- block = ext4_idx_pblock(ix);
- bh = extents_bread(inode->i_sb, block);
- if (!bh)
- goto out;
-
- /* set size of new block */
- neh = ext_block_hdr(bh);
- neh_entries = le16_to_cpu(neh->eh_entries);
- if (!neh->eh_depth &&
- neh_entries > ext4_ext_space_root(inode, 0))
- goto out;
-
- if (neh->eh_depth &&
- neh_entries > ext4_ext_space_root_idx(inode, 0))
- goto out;
-
- /* old root could have indexes or leaves
- * so calculate e_max right way */
- if (neh->eh_depth)
- eh->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0));
- else
- eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0));
-
- eh->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC);
- eh->eh_entries = neh_entries;
- if (neh->eh_depth) {
- memmove(EXT_FIRST_INDEX(eh),
- EXT_FIRST_INDEX(neh),
- sizeof(struct ext4_extent_idx) * neh_entries);
- } else {
- memmove(EXT_FIRST_EXTENT(eh),
- EXT_FIRST_EXTENT(neh),
- sizeof(struct ext4_extent) * neh_entries);
- }
- le16_add_cpu(&eh->eh_depth, -1);
-
- ext4_mark_inode_dirty(icb, handle, inode);
- *shrinked = 1;
-out:
- if (bh)
- extents_brelse(bh);
-
- if (*shrinked)
- ext4_free_blocks(icb, handle, inode, NULL,
- block, 1, flags);
-
- return err;
-}
-
/*
* ext4_ext_create_new_leaf:
* finds empty index and adds new leaf.
@@ -1427,25 +1356,29 @@
* with leaves.
*/
ext4_lblk_t
-ext4_ext_next_allocated_block(struct ext4_ext_path *path, int at)
-{
- if (at == 0 && !path->p_ext && !path->p_idx)
+ext4_ext_next_allocated_block(struct ext4_ext_path *path)
+{
+ int depth;
+
+ depth = path->p_depth;
+
+ if (depth == 0 && path->p_ext == NULL)
return EXT_MAX_BLOCKS;
- while (at >= 0) {
- if (at == path->p_depth) {
+ while (depth >= 0) {
+ if (depth == path->p_depth) {
/* leaf */
- if (path[at].p_ext &&
- path[at].p_ext !=
- EXT_LAST_EXTENT(path[at].p_hdr))
- return le32_to_cpu(path[at].p_ext[1].ee_block);
+ if (path[depth].p_ext &&
+ path[depth].p_ext !=
+ EXT_LAST_EXTENT(path[depth].p_hdr))
+ return le32_to_cpu(path[depth].p_ext[1].ee_block);
} else {
/* index */
- if (path[at].p_idx !=
- EXT_LAST_INDEX(path[at].p_hdr))
- return le32_to_cpu(path[at].p_idx[1].ei_block);
- }
- at--;
+ if (path[depth].p_idx !=
+ EXT_LAST_INDEX(path[depth].p_hdr))
+ return le32_to_cpu(path[depth].p_idx[1].ei_block);
+ }
+ depth--;
}
return EXT_MAX_BLOCKS;
@@ -1482,14 +1415,12 @@
/*
* ext4_ext_correct_indexes:
- * if leaf/node gets modified and modified extent/index
- * is first in the leaf/node,
+ * if leaf gets modified and modified extent is first in the leaf,
* then we have to correct all indexes above.
+ * TODO: do we need to correct tree in all cases?
*/
-static int ext4_ext_correct_indexes(void *icb, handle_t *handle,
- struct inode *inode,
- struct ext4_ext_path *path,
- int at)
+static int ext4_ext_correct_indexes(void *icb, handle_t *handle, struct inode *inode,
+ struct ext4_ext_path *path)
{
struct ext4_extent_header *eh;
int depth = ext_depth(inode);
@@ -1497,49 +1428,49 @@
__le32 border;
int k, err = 0;
- assert(at >= 0);
- if (!at)
+ eh = path[depth].p_hdr;
+ ex = path[depth].p_ext;
+
+ if (unlikely(ex == NULL || eh == NULL)) {
+ EXT4_ERROR_INODE(inode,
+ "ex %p == NULL or eh %p == NULL", ex, eh);
+ return -EIO;
+ }
+
+ if (depth == 0) {
+ /* there is no tree at all */
return 0;
-
- if (depth == at) {
- eh = path[at].p_hdr;
- ex = path[at].p_ext;
-
- if (ex == NULL || eh == NULL)
- return -EIO;
-
- if (at == 0) {
- /* there is no tree at all */
- return 0;
- }
-
- if (ex != EXT_FIRST_EXTENT(eh)) {
- /* we correct tree if first leaf got modified only */
- return 0;
- }
-
- k = at - 1;
- border = path[at].p_ext->ee_block;
+ }
+
+ if (ex != EXT_FIRST_EXTENT(eh)) {
+ /* we correct tree if first leaf got modified only */
+ return 0;
+ }
+
+ /*
+ * TODO: we need correction if border is smaller than current one
+ */
+ k = depth - 1;
+ border = path[depth].p_ext->ee_block;
+ err = ext4_ext_get_access(icb, handle, inode, path + k);
+ if (err)
+ return err;
+ path[k].p_idx->ei_block = border;
+ err = ext4_ext_dirty(icb, handle, inode, path + k);
+ if (err)
+ return err;
+
+ while (k--) {
+ /* change all left-side indexes */
+ if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
+ break;
+ err = ext4_ext_get_access(icb, handle, inode, path + k);
+ if (err)
+ break;
path[k].p_idx->ei_block = border;
err = ext4_ext_dirty(icb, handle, inode, path + k);
if (err)
- return err;
-
- } else {
- border = path[at].p_idx->ei_block;
- k = at;
- }
-
- while (k) {
- /* change all left-side indexes */
- if (path[k].p_idx != EXT_FIRST_INDEX(path[k].p_hdr))
break;
- path[k-1].p_idx->ei_block = border;
- err = ext4_ext_dirty(icb, handle, inode, path + k-1);
- if (err)
- break;
-
- k--;
}
return err;
@@ -1914,11 +1845,9 @@
if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
ext4_ext_try_to_merge(icb, handle, inode, path, nearex);
- depth = ext_depth(inode);
/* time to correct all indexes above */
- err = ext4_ext_correct_indexes(icb, handle,
- inode, path, depth);
+ err = ext4_ext_correct_indexes(icb, handle, inode, path);
if (err)
goto cleanup;
@@ -1952,351 +1881,156 @@
return ret;
}
-static void ext4_ext_remove_blocks(
- void *icb,
- handle_t *handle,
- struct inode *inode, struct ext4_extent *ex,
- ext4_lblk_t from, ext4_lblk_t to)
-{
- int len = to - from + 1;
- ext4_lblk_t num;
- ext4_fsblk_t start;
- num = from - le32_to_cpu(ex->ee_block);
- start = ext4_ext_pblock(ex) + num;
- ext_debug("Freeing %lu at %I64u, %d\n", from, start, len);
- ext4_free_blocks(icb, handle, inode, NULL,
- start, len, 0);
-}
-
-static int ext4_ext_remove_idx(void *icb,
- handle_t *handle,
- struct inode *inode,
- struct ext4_ext_path *path,
- int depth)
-{
- int err, i = depth;
+static int ext4_remove_blocks(void *icb, handle_t *handle, struct inode *inode,
+ struct ext4_extent *ex,
+ unsigned long from, unsigned long to)
+{
+ struct buffer_head *bh;
+ int i;
+
+ if (from >= le32_to_cpu(ex->ee_block)
+ && to == le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1) {
+ /* tail removal */
+ unsigned long num, start;
+ num = le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - from;
+ start = ext4_ext_pblock(ex) + ext4_ext_get_actual_len(ex) - num;
+ ext4_free_blocks(icb, handle, inode, NULL, start, num, 0);
+ } else if (from == le32_to_cpu(ex->ee_block)
+ && to <= le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1) {
+ } else {
+ }
+ return 0;
+}
+
+/*
+ * routine removes index from the index block
+ * it's used in truncate case only. thus all requests are for
+ * last index in the block only
+ */
+int ext4_ext_rm_idx(void *icb, handle_t *handle, struct inode *inode,
+ struct ext4_ext_path *path)
+{
+ int err;
ext4_fsblk_t leaf;
/* free index block */
- leaf = ext4_idx_pblock(path[i].p_idx);
-
- if (path[i].p_idx != EXT_LAST_INDEX(path[i].p_hdr)) {
- int len = EXT_LAST_INDEX(path[i].p_hdr) - path[i].p_idx;
- memmove(path[i].p_idx, path[i].p_idx + 1,
- len * sizeof(struct ext4_extent_idx));
- }
-
- le16_add_cpu(&path[i].p_hdr->eh_entries, -1);
- err = ext4_ext_dirty(icb, handle, inode, path + i);
- if (err)
+ path--;
+ leaf = ext4_idx_pblock(path->p_idx);
+ BUG_ON(path->p_hdr->eh_entries == 0);
+ if ((err = ext4_ext_get_access(icb, handle, inode, path)))
return err;
-
- ext_debug("IDX: Freeing %lu at %I64u, %d\n",
- le32_to_cpu(path[i].p_idx->ei_block), leaf, 1);
- ext4_free_blocks(icb, handle, inode, NULL,
- leaf, 1, 0);
+ path->p_hdr->eh_entries =
cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1);
+ if ((err = ext4_ext_dirty(icb, handle, inode, path)))
+ return err;
+ ext4_free_blocks(icb, handle, inode, NULL, leaf, 1, 0);
return err;
}
-static int ext4_ext_amalgamate(void *icb,
- handle_t *handle,
- struct inode *inode,
- struct ext4_ext_path *path,
- int at)
-{
- int new_entries, right_entries;
- int depth = ext_depth(inode);
- struct ext4_ext_path *right_path = NULL;
- ext4_lblk_t now;
- int ret = 0;
- if (!at)
- return 0;
-
- now = ext4_ext_next_allocated_block(path, at - 1);
- if (now == EXT_MAX_BLOCKS)
- goto out;
-
- right_path = ext4_find_extent(inode, now, NULL, 0);
- if (IS_ERR(right_path)) {
- ret = PTR_ERR(right_path);
- right_path = NULL;
- goto out;
- }
-
- right_entries = le16_to_cpu(right_path[at].p_hdr->eh_entries);
- new_entries = le16_to_cpu(path[at].p_hdr->eh_entries) +
- right_entries;
- if (new_entries > path[at].p_hdr->eh_max) {
- ret = 0;
- goto out;
- }
- if (at == depth) {
- struct ext4_extent *last_ex = EXT_LAST_EXTENT(path[at].p_hdr);
- memmove(last_ex + 1,
- EXT_FIRST_EXTENT(right_path[at].p_hdr),
- right_entries * sizeof(struct ext4_extent));
- } else {
- struct ext4_extent_idx *last_ix = EXT_LAST_INDEX(path[at].p_hdr);
- memmove(last_ix + 1,
- EXT_FIRST_INDEX(right_path[at].p_hdr),
- right_entries * sizeof(struct ext4_extent_idx));
- }
- path[at].p_hdr->eh_entries = cpu_to_le16(new_entries);
- right_path[at].p_hdr->eh_entries = 0;
- ext4_ext_dirty(icb, handle, inode, path + at);
-
- /*
- * remove the empty node from index block above.
- */
- depth = at;
- while (depth > 0) {
- struct ext4_extent_header *eh = right_path[depth].p_hdr;
- if (eh->eh_entries == 0 && right_path[depth].p_bh != NULL) {
- ext4_ext_drop_refs(right_path + depth);
- ret = ext4_ext_remove_idx(icb, handle, inode, right_path, depth - 1);
- if (ret)
- goto out;
-
- } else
- break;
-
- depth--;
- }
- ret = ext4_ext_correct_indexes(icb, handle,
- inode, right_path, depth);
+static int
+ext4_ext_rm_leaf(void *icb, handle_t *handle, struct inode *inode,
+ struct ext4_ext_path *path, unsigned long start)
+{
+ int err = 0, correct_index = 0;
+ int depth = ext_depth(inode), credits;
+ struct ext4_extent_header *eh;
+ unsigned a, b, block, num;
+ unsigned long ex_ee_block;
+ unsigned short ex_ee_len;
+ struct ext4_extent *ex;
+
+ /* the header must be checked already in ext4_ext_remove_space() */
+ if (!path[depth].p_hdr)
+ path[depth].p_hdr = ext_block_hdr(path[depth].p_bh);
+ eh = path[depth].p_hdr;
+ BUG_ON(eh == NULL);
+
+ /* find where to start removing */
+ ex = EXT_LAST_EXTENT(eh);
+
+ ex_ee_block = le32_to_cpu(ex->ee_block);
+ ex_ee_len = ext4_ext_get_actual_len(ex);
+
+ while (ex >= EXT_FIRST_EXTENT(eh) &&
+ ex_ee_block + ex_ee_len > start) {
+ path[depth].p_ext = ex;
+
+ a = ex_ee_block > start ? ex_ee_block : start;
+ b = (unsigned long long)ex_ee_block + ex_ee_len - 1 <
+ EXT_MAX_BLOCKS ? ex_ee_block + ex_ee_len - 1 : EXT_MAX_BLOCKS;
+
+
+ if (a != ex_ee_block && b != ex_ee_block + ex_ee_len - 1) {
+ block = 0;
+ num = 0;
+ BUG();
+ } else if (a != ex_ee_block) {
+ /* remove tail of the extent */
+ block = ex_ee_block;
+ num = a - block;
+ } else if (b != ex_ee_block + ex_ee_len - 1) {
+ /* remove head of the extent */
+ block = a;
+ num = b - a;
+ /* there is no "make a hole" API yet */
+ BUG();
+ } else {
+ /* remove whole extent: excellent! */
+ block = ex_ee_block;
+ num = 0;
+ BUG_ON(a != ex_ee_block);
+ BUG_ON(b != ex_ee_block + ex_ee_len - 1);
+ }
+
+ /* at present, extent can't cross block group */
+ /* leaf + bitmap + group desc + sb + inode */
+ credits = 5;
+ if (ex == EXT_FIRST_EXTENT(eh)) {
+ correct_index = 1;
+ credits += (ext_depth(inode)) + 1;
+ }
+
+ /*handle = ext4_ext_journal_restart(icb, handle, credits);*/
+ /*if (IS_ERR(icb, handle)) {*/
+ /*err = PTR_ERR(icb, handle);*/
+ /*goto out;*/
+ /*}*/
+
+ err = ext4_ext_get_access(icb, handle, inode, path + depth);
+ if (err)
+ goto out;
+
+ err = ext4_remove_blocks(icb, handle, inode, ex, a, b);
+ if (err)
+ goto out;
+
+ if (num == 0) {
+ /* this extent is removed entirely mark slot unused */
+ ext4_ext_store_pblock(ex, 0);
+ eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)-1);
+ }
+
+ ex->ee_block = cpu_to_le32(block);
+ ex->ee_len = cpu_to_le16(num);
+
+ err = ext4_ext_dirty(icb, handle, inode, path + depth);
+ if (err)
+ goto out;
+
+ ex--;
+ ex_ee_block = le32_to_cpu(ex->ee_block);
+ ex_ee_len = ext4_ext_get_actual_len(ex);
+ }
+
+ if (correct_index && eh->eh_entries)
+ err = ext4_ext_correct_indexes(icb, handle, inode, path);
+
+ /* if this leaf is free, then we should
+ * remove it from index block above */
+ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
+ err = ext4_ext_rm_idx(icb, handle, inode, path + depth);
+
out:
- if (right_path) {
- ext4_ext_drop_refs(right_path);
- kfree(right_path);
- }
-
- return ret;
-}
-
-static int ext4_ext_balance(void *icb,
- handle_t *handle,
- struct inode *inode,
- struct ext4_ext_path **path,
- int at)
-{
- int ret, shrinked = 0;
- int depth = at;
-
- while (depth > 0) {
- ret = ext4_ext_amalgamate(icb, handle,
- inode, *path, depth);
- if (ret)
- goto out;
-
- depth--;
- }
- do {
- ret = ext4_ext_shrink_indepth(icb, handle,
- inode, 0, &shrinked);
- } while (!ret && shrinked);
-
-out:
- return ret;
-}
-
-/*
- * NOTE: After removal, path should not be reused.
- */
-int ext4_ext_remove_extent(void *icb,
- handle_t *handle,
- struct inode *inode, struct ext4_ext_path **path)
-{
- int len;
- int err = 0;
- ext4_lblk_t start;
- uint16_t new_entries;
- int depth = ext_depth(inode);
- struct ext4_extent *ex = (*path)[depth].p_ext,
- *ex2 = ex + 1;
- struct ext4_extent_header *eh = (*path)[depth].p_hdr;
- if (!ex)
- return -EINVAL;
-
- start = le32_to_cpu(ex->ee_block);
- len = ext4_ext_get_actual_len(ex);
- new_entries = le16_to_cpu(eh->eh_entries) - 1;
-
- ext4_ext_remove_blocks(icb, handle,
- inode, ex, start, start + len - 1);
- if (ex2 <= EXT_LAST_EXTENT(eh))
- memmove(ex, ex2,
- (EXT_LAST_EXTENT(eh) - ex2 + 1) * sizeof(struct ext4_extent));
- eh->eh_entries = cpu_to_le16(new_entries);
-
- ext4_ext_dirty(icb, handle, inode, (*path) + depth);
-
- /*
- * If the node is free, then we should
- * remove it from index block above.
- */
- while (depth > 0) {
- eh = (*path)[depth].p_hdr;
- if (eh->eh_entries == 0 && (*path)[depth].p_bh != NULL) {
- ext4_ext_drop_refs((*path) + depth);
- err = ext4_ext_remove_idx(icb, handle,
- inode, *path, depth - 1);
- if (err)
- break;
-
- } else
- break;
-
- depth--;
- }
- err = ext4_ext_correct_indexes(icb, handle,
- inode, *path, depth);
-
- if ((*path)->p_hdr->eh_entries == 0) {
- /*
- * truncate to zero freed all the tree,
- * so we need to correct eh_depth
- */
- ext_inode_hdr(inode)->eh_depth = 0;
- ext_inode_hdr(inode)->eh_max =
- cpu_to_le16(ext4_ext_space_root(inode, 0));
- err = ext4_ext_dirty(icb, handle, inode, *path);
- }
- err = ext4_ext_balance(icb, handle, inode, path, depth);
-
return err;
-}
-
-int __ext4_ext_truncate(void *icb,
- handle_t *handle,
- struct inode *inode,
- ext4_lblk_t from, ext4_lblk_t to)
-{
- int depth = ext_depth(inode), ret = -EIO;
- struct ext4_extent *ex;
- struct ext4_ext_path *path = NULL, *npath;
- ext4_lblk_t now = from;
-
- if (to < from)
- return -EINVAL;
-
- npath = ext4_find_extent(inode, from, &path, 0);
- if (IS_ERR(npath))
- goto out;
-
- path = npath;
- ex = path[depth].p_ext;
- if (!ex)
- goto out;
-
- if (from < le32_to_cpu(ex->ee_block) &&
- to < le32_to_cpu(ex->ee_block)) {
- ret = 0;
- goto out;
- }
- /* If we do remove_space inside the range of an extent */
- if ((le32_to_cpu(ex->ee_block) < from) &&
- (to < le32_to_cpu(ex->ee_block) +
- ext4_ext_get_actual_len(ex) - 1)) {
-
- struct ext4_extent newex;
- int unwritten = ext4_ext_is_unwritten(ex);
- ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
- int len = ext4_ext_get_actual_len(ex);
- ext4_fsblk_t newblock =
- to + 1 - ee_block + ext4_ext_pblock(ex);
-
- ex->ee_len = cpu_to_le16(from - ee_block);
- if (unwritten)
- ext4_ext_mark_unwritten(ex);
-
- ext4_ext_dirty(icb, handle, inode, path + depth);
-
- ext4_ext_remove_blocks(icb, handle,
- inode,
- ex, from, to);
-
- newex.ee_block = cpu_to_le32(to + 1);
- newex.ee_len = cpu_to_le16(ee_block + len - 1 - to);
- ext4_ext_store_pblock(&newex, newblock);
- if (unwritten)
- ext4_ext_mark_unwritten(&newex);
-
- ret = ext4_ext_insert_extent(icb, handle,
- inode, &path, &newex, 0);
- goto out;
- }
- if (le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1 < from) {
- now = ext4_ext_next_allocated_block(path, depth);
- npath = ext4_find_extent(inode, now, &path, 0);
- if (IS_ERR(npath))
- goto out;
-
- path = npath;
- ex = path[depth].p_ext;
- }
- while (ex &&
- le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1 >= now
&&
- le32_to_cpu(ex->ee_block) <= to) {
- int len, new_len = 0;
- int unwritten;
- ext4_lblk_t start, new_start;
- ext4_fsblk_t newblock;
-
- new_start = start = le32_to_cpu(ex->ee_block);
- len = ext4_ext_get_actual_len(ex);
- newblock = ext4_ext_pblock(ex);
- if (start < from) {
- len -= from - start;
- new_len = from - start;
- start = from;
- } else {
- if (start + len - 1 > to) {
- new_len = start + len - 1 - to;
- len -= new_len;
- new_start = to + 1;
- newblock += to + 1 - start;
- }
- }
-
- now = ext4_ext_next_allocated_block(path, depth);
- if (!new_len) {
- ret = ext4_ext_remove_extent(icb, handle,
- inode, &path);
- if (ret)
- goto out;
-
- } else {
- ext4_ext_remove_blocks(icb, handle,
- inode,
- ex, start, start + len - 1);
- ex->ee_block = cpu_to_le32(new_start);
- unwritten = ext4_ext_is_unwritten(ex);
- ex->ee_len = cpu_to_le16(new_len);
- ext4_ext_store_pblock(ex, newblock);
- if (unwritten)
- ext4_ext_mark_unwritten(ex);
-
- ext4_ext_dirty(icb, handle,
- inode, path + depth);
- }
- npath = ext4_find_extent(inode, now, &path, 0);
- if (IS_ERR(npath))
- goto out;
-
- path = npath;
- depth = ext_depth(inode);
- ex = path[depth].p_ext;
- }
-out:
- if (path) {
- ext4_ext_drop_refs(path);
- kfree(path);
- }
-
- if (IS_ERR(npath))
- ret = PTR_ERR(npath);
-
- return ret;
}
/*
@@ -2438,6 +2172,140 @@
return err;
}
+/*
+ * returns 1 if current index have to be freed (even partial)
+ */
+#ifndef __REACTOS__
+static int inline
+#else
+inline int
+#endif
+ext4_ext_more_to_rm(struct ext4_ext_path *path)
+{
+ BUG_ON(path->p_idx == NULL);
+
+ if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
+ return 0;
+
+ /*
+ * if truncate on deeper level happened it it wasn't partial
+ * so we have to consider current index for truncation
+ */
+ if (le16_to_cpu(path->p_hdr->eh_entries) == path->p_block)
+ return 0;
+ return 1;
+}
+
+int ext4_ext_remove_space(void *icb, struct inode *inode, unsigned long start)
+{
+ struct super_block *sb = inode->i_sb;
+ int depth = ext_depth(inode);
+ struct ext4_ext_path *path;
+ handle_t *handle = NULL;
+ int i = 0, err = 0;
+
+ /* probably first extent we're gonna free will be last in block */
+ /*handle = ext4_journal_start(inode, depth + 1);*/
+ /*if (IS_ERR(icb, handle))*/
+ /*return PTR_ERR(icb, handle);*/
+
+ /*
+ * we start scanning from right side freeing all the blocks
+ * after i_size and walking into the deep
+ */
+ path = kmalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_KERNEL);
+ if (path == NULL) {
+ ext4_journal_stop(icb, handle);
+ return -ENOMEM;
+ }
+ memset(path, 0, sizeof(struct ext4_ext_path) * (depth + 1));
+ path[0].p_hdr = ext_inode_hdr(inode);
+ if (ext4_ext_check_inode(inode)) {
+ err = -EIO;
+ goto out;
+ }
+ path[0].p_depth = depth;
+
+ while (i >= 0 && err == 0) {
+ if (i == depth) {
+ /* this is leaf block */
+ err = ext4_ext_rm_leaf(icb, handle, inode, path, start);
+ /* root level have p_bh == NULL, extents_brelse() eats this */
+ extents_brelse(path[i].p_bh);
+ path[i].p_bh = NULL;
+ i--;
+ continue;
+ }
+
+ /* this is index block */
+ if (!path[i].p_hdr) {
+ path[i].p_hdr = ext_block_hdr(path[i].p_bh);
+ }
+
+ if (!path[i].p_idx) {
+ /* this level hasn't touched yet */
+ path[i].p_idx = EXT_LAST_INDEX(path[i].p_hdr);
+ path[i].p_block = le16_to_cpu(path[i].p_hdr->eh_entries)+1;
+ } else {
+ /* we've already was here, see at next index */
+ path[i].p_idx--;
+ }
+
+ if (ext4_ext_more_to_rm(path + i)) {
+ struct buffer_head *bh;
+ /* go to the next level */
+ memset(path + i + 1, 0, sizeof(*path));
+ bh = read_extent_tree_block(inode, ext4_idx_pblock(path[i].p_idx), path[0].p_depth -
(i + 1), 0);
+ if (IS_ERR(bh)) {
+ /* should we reset i_size? */
+ err = -EIO;
+ break;
+ }
+ path[i+1].p_bh = bh;
+
+ /* put actual number of indexes to know is this
+ * number got changed at the next iteration */
+ path[i].p_block = le16_to_cpu(path[i].p_hdr->eh_entries);
+ i++;
+ } else {
+ /* we finish processing this index, go up */
+ if (path[i].p_hdr->eh_entries == 0 && i > 0) {
+ /* index is empty, remove it
+ * handle must be already prepared by the
+ * truncatei_leaf() */
+ err = ext4_ext_rm_idx(icb, handle, inode, path + i);
+ }
+ /* root level have p_bh == NULL, extents_brelse() eats this */
+ extents_brelse(path[i].p_bh);
+ path[i].p_bh = NULL;
+ i--;
+ }
+ }
+
+ /* TODO: flexible tree reduction should be here */
+ if (path->p_hdr->eh_entries == 0) {
+ /*
+ * truncate to zero freed all the tree
+ * so, we need to correct eh_depth
+ */
+ err = ext4_ext_get_access(icb, handle, inode, path);
+ if (err == 0) {
+ ext_inode_hdr(inode)->eh_depth = 0;
+ ext_inode_hdr(inode)->eh_max =
+ cpu_to_le16(ext4_ext_space_root(inode, 0));
+ err = ext4_ext_dirty(icb, handle, inode, path);
+ }
+ }
+out:
+ if (path) {
+ ext4_ext_drop_refs(path);
+ kfree(path);
+ }
+ ext4_journal_stop(icb, handle);
+
+ return err;
+}
+
int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode)
{
struct ext4_extent_header *eh;
@@ -2576,7 +2444,7 @@
/* find next allocated block so that we know how many
* blocks we can allocate without ovelapping next extent */
- next = ext4_ext_next_allocated_block(path, depth);
+ next = ext4_ext_next_allocated_block(path);
BUG_ON(next <= iblock);
allocated = next - iblock;
if (flags & EXT4_GET_BLOCKS_PRE_IO && max_blocks >
EXT_UNWRITTEN_MAX_LEN)
@@ -2639,8 +2507,7 @@
int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start)
{
- int ret = __ext4_ext_truncate(icb, NULL, inode,
- start, EXT_MAX_BLOCKS);
+ int ret = ext4_ext_remove_space(icb, inode, start);
/* Save modifications on i_blocks field of the inode. */
if (!ret)
Modified: trunk/reactos/drivers/filesystems/ext2/src/fileinfo.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/fileinfo.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/fileinfo.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -504,7 +504,6 @@
ULONG Length;
PVOID Buffer;
- BOOLEAN VcbMainResourceAcquired = FALSE;
BOOLEAN FcbMainResourceAcquired = FALSE;
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
@@ -540,18 +539,6 @@
if (!IsMounted(Vcb)) {
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_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;
- _SEH2_LEAVE;
- }
- VcbMainResourceAcquired = TRUE;
}
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
@@ -1045,10 +1032,6 @@
if (FcbMainResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource);
- }
-
- if (VcbMainResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
}
if (!IrpContext->ExceptionInProgress) {
@@ -1347,8 +1330,7 @@
BOOLEAN bMove = FALSE;
BOOLEAN bTargetRemoved = FALSE;
- BOOLEAN bNewTargetDcb = FALSE;
- BOOLEAN bNewParentDcb = FALSE;
+ BOOLEAN bFcbLockAcquired = FALSE;
PFILE_RENAME_INFORMATION FRI;
@@ -1435,16 +1417,17 @@
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,14 +1437,15 @@
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) {
@@ -1625,40 +1609,25 @@
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);
- }
-
- 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"));
- }
+ Ext2ReleaseFcb(TargetDcb);
+ }
+
+ if (ParentDcb) {
+ Ext2ReleaseFcb(ParentDcb);
}
if (ExistingMcb)
@@ -1698,8 +1667,8 @@
BOOLEAN ReplaceIfExists;
BOOLEAN bTargetRemoved = FALSE;
- BOOLEAN bNewTargetDcb = FALSE;
- BOOLEAN bNewParentDcb = FALSE;
+
+ BOOLEAN bFcbLockAcquired = FALSE;
PFILE_LINK_INFORMATION FLI;
@@ -1781,17 +1750,15 @@
}
}
+ 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,14 +1768,15 @@
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) {
@@ -1887,31 +1855,17 @@
errorout:
+ if (bFcbLockAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ bFcbLockAcquired = FALSE;
+ }
+
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 (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 (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"));
- }
+ Ext2ReleaseFcb(TargetDcb);
+ }
+
+ if (ParentDcb) {
+ Ext2ReleaseFcb(ParentDcb);
}
if (ExistingMcb)
@@ -1957,7 +1911,7 @@
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 @@
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) {
- SetLongFlag(Dcb->Flags, FCB_STATE_BUSY);
+ Ext2ReferXcb(&Dcb->ReferenceCount);
+ }
+
+ if (bFcbLockAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ bFcbLockAcquired = FALSE;
+ }
+
+ if (Dcb) {
DcbResourceAcquired =
ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
@@ -2090,21 +2050,18 @@
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);
} _SEH2_END;
Modified: trunk/reactos/drivers/filesystems/ext2/src/flush.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/flush.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/flush.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -81,13 +81,20 @@
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
- /* discard buffer_headers for group_desc */
- Ext2DropGroup(Vcb);
-
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Vcb->PagingIoResource);
+ /* acquire gd lock to avoid gd/bh creation */
+ ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
+
+ /* discard buffer_headers for group_desc */
+ Ext2DropBH(Vcb);
+
+ /* do flushing */
CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
+
+ /* release gd lock */
+ ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
return IoStatus.Status;
}
Modified: trunk/reactos/drivers/filesystems/ext2/src/fsctl.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/fsctl.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/fsctl.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -1582,8 +1582,6 @@
PEXT2_MCB Mcb = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
- BOOLEAN bNewParentDcb = FALSE;
- BOOLEAN MainResourceAcquired = FALSE;
PVOID InputBuffer;
ULONG InputBufferLength;
@@ -1600,6 +1598,8 @@
PCHAR OemNameBuffer = NULL;
int OemNameLength = 0, i;
+ BOOLEAN MainResourceAcquired = FALSE;
+ BOOLEAN FcbLockAcquired = FALSE;
_SEH2_TRY {
@@ -1614,18 +1614,25 @@
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)
_SEH2_LEAVE;
+
+ if (FcbLockAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ FcbLockAcquired = FALSE;
+ }
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource,
@@ -1701,6 +1708,11 @@
}
} _SEH2_FINALLY {
+
+ if (FcbLockAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ FcbLockAcquired = FALSE;
+ }
if (MainResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource);
@@ -1719,22 +1731,16 @@
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 (!_SEH2_AbnormalTermination()) {
if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) {
Status = Ext2QueueRequest(IrpContext);
} else {
Ext2CompleteIrpContext(IrpContext, Status);
}
+ }
+
+ if (ParentDcb) {
+ Ext2ReleaseFcb(ParentDcb);
}
} _SEH2_END;
@@ -1786,13 +1792,14 @@
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;
_SEH2_TRY {
@@ -1805,14 +1812,16 @@
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) ||
@@ -1820,15 +1829,19 @@
Status = STATUS_NOT_A_REPARSE_POINT;
_SEH2_LEAVE;
}
-
+
Fcb = Ext2AllocateFcb (Vcb, Mcb);
if (Fcb) {
- bFcbAllocated = TRUE;
+ Ext2ReferXcb(&Fcb->ReferenceCount);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH2_LEAVE;
}
- Ext2ReferXcb(&Fcb->ReferenceCount);
+
+ if (FcbLockAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ FcbLockAcquired = FALSE;
+ }
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource,
@@ -1847,6 +1860,10 @@
SetFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);
} _SEH2_FINALLY {
+
+ if (FcbLockAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ }
if (MainResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource);
@@ -1862,16 +1879,6 @@
}
- if (bNewParentDcb) {
- ASSERT(ParentDcb != NULL);
- if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) {
- Ext2FreeFcb(ParentDcb);
- ParentDcb = NULL;
- } else {
- DEBUG(DL_RES, ( "Ext2DeleteReparsePoint: ParentDcb is
resued.\n"));
- }
- }
-
if (!_SEH2_AbnormalTermination()) {
if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) {
Status = Ext2QueueRequest(IrpContext);
@@ -1879,11 +1886,13 @@
Ext2CompleteIrpContext(IrpContext, Status);
}
}
-
- if (bFcbAllocated) {
- if (Ext2DerefXcb(&Fcb->ReferenceCount) == 0) {
- Ext2FreeFcb(Fcb);
- }
+
+ if (ParentDcb) {
+ Ext2ReleaseFcb(ParentDcb);
+ }
+
+ if (Fcb) {
+ Ext2ReleaseFcb(Fcb);
}
} _SEH2_END;
@@ -2450,13 +2459,7 @@
} 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);
@@ -2607,8 +2610,9 @@
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;
@@ -2696,59 +2700,44 @@
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;
+
_SEH2_TRY {
ASSERT(Vcb != NULL);
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;
}
- /* discard buffer_headers for group_desc */
- Ext2DropGroup(Vcb);
-
- FcbListEntry= NULL;
- InitializeListHead(&FcbList);
-
- for (ListEntry = Vcb->FcbList.Flink;
- ListEntry != &Vcb->FcbList;
- ListEntry = ListEntry->Flink ) {
-
- Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
-
- DEBUG(DL_INF, ( "Ext2PurgeVolume: %wZ refercount=%xh\n",
&Fcb->Mcb->FullName, Fcb->ReferenceCount));
-
- FcbListEntry = Ext2AllocatePool(
- PagedPool,
- sizeof(FCB_LIST_ENTRY),
- EXT2_FLIST_MAGIC
- );
-
- if (FcbListEntry) {
- FcbListEntry->Fcb = Fcb;
- Ext2ReferXcb(&Fcb->ReferenceCount);
- InsertTailList(&FcbList, &FcbListEntry->Next);
- } else {
- DEBUG(DL_ERR, ( "Ext2PurgeVolume: failed to allocate FcbListEntry
...\n"));
- }
- }
-
- while (!IsListEmpty(&FcbList)) {
-
- ListEntry = RemoveHeadList(&FcbList);
-
- FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next);
-
- Fcb = FcbListEntry->Fcb;
+ InitializeListHead(&List);
+
+ ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
+ FcbResourceAcquired = TRUE;
+
+ while (!IsListEmpty(&Vcb->FcbList)) {
+
+ Next = RemoveHeadList(&Vcb->FcbList);
+ Fcb = CONTAINING_RECORD(Next, EXT2_FCB, Next);
+
+ DEBUG(DL_INF, ( "Ext2PurgeVolume: %wZ refercount=%xh\n",
+ &Fcb->Mcb->FullName, Fcb->ReferenceCount));
+ InsertTailList(&List, &Fcb->Next);
+ }
+
+ while (!IsListEmpty(&List)) {
+
+ Next = RemoveHeadList(&List);
+ Fcb = CONTAINING_RECORD(Next, EXT2_FCB, Next);
if (ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
@@ -2756,15 +2745,27 @@
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);
}
- }
-
- Ext2FreePool(FcbListEntry, EXT2_FLIST_MAGIC);
- }
+ ExReleaseResourceLite(&Fcb->MainResource);
+ }
+ }
+
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ FcbResourceAcquired = FALSE;
+ }
+
+ /* acquire bd lock to avoid bh creation */
+ ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
+ gdResourceAcquired = TRUE;
+
+ /* discard buffer_headers for group_desc */
+ Ext2DropBH(Vcb);
if (FlushBeforePurge) {
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
@@ -2777,11 +2778,6 @@
MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite);
}
- if (VcbResourceAcquired) {
- ExReleaseResourceLite(&Vcb->MainResource);
- VcbResourceAcquired = FALSE;
- }
-
if (Vcb->SectionObject.DataSectionObject) {
CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE);
}
@@ -2789,6 +2785,14 @@
DEBUG(DL_INF, ( "Ext2PurgeVolume: Volume flushed and purged.\n"));
} _SEH2_FINALLY {
+
+ if (gdResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
+ }
+
+ if (FcbResourceAcquired) {
+ ExReleaseResourceLite(&Vcb->FcbLock);
+ }
if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource);
@@ -2811,30 +2815,23 @@
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);
}
Modified: trunk/reactos/drivers/filesystems/ext2/src/init.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/init.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/init.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -197,7 +197,7 @@
* 1 writing support
*/
QueryTable[i].Flags = 0;
- QueryTable[0].Name = WRITING_SUPPORT;
+ QueryTable[i].Name = WRITING_SUPPORT;
QueryTable[i].DefaultType = REG_NONE;
QueryTable[i].DefaultLength = 0;
QueryTable[i].DefaultData = NULL;
@@ -431,6 +431,7 @@
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);
@@ -555,11 +556,19 @@
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;
}
@@ -567,6 +576,7 @@
&Ext2Global->bhReaper,
Ext2bhReaperThread);
if (!NT_SUCCESS(Status)) {
+ Ext2StopReaper(&Ext2Global->FcbReaper);
Ext2StopReaper(&Ext2Global->McbReaper);
goto errorout;
}
Modified: trunk/reactos/drivers/filesystems/ext2/src/memory.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/memory.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/memory.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -18,15 +18,11 @@
/* 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 @@
{
PEXT2_FCB Fcb;
+ ASSERT(ExIsResourceAcquiredExclusiveLite(&Vcb->FcbLock));
+
Fcb = (PEXT2_FCB) ExAllocateFromNPagedLookasideList(
&(Ext2Global->Ext2FcbLookasideList));
@@ -201,84 +199,121 @@
}
VOID
+Ext2UnlinkFcb(IN PEXT2_FCB Fcb)
+{
+ PEXT2_VCB Vcb = Fcb->Vcb;
+ PEXT2_MCB Mcb;
+
+ ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE);
+ Mcb = Fcb->Mcb;
+
+ DEBUG(DL_ERR, ("Ext2FreeFcb: Fcb (%p) to be unlinked: %wZ.\n",
+ Fcb, Mcb ? &Mcb->FullName : NULL));
+
+ if ((Mcb != NULL) &&
+ (Mcb->Identifier.Type == EXT2MCB) &&
+ (Mcb->Identifier.Size == sizeof(EXT2_MCB))) {
+
+ ASSERT (Mcb->Fcb == Fcb);
+ if (IsMcbSpecialFile(Mcb) ||
+ IsFileDeleted(Mcb)) {
+
+ ASSERT(!IsRoot(Fcb));
+ Ext2RemoveMcb(Vcb, Mcb);
+ Mcb->Fcb = NULL;
+
+ Ext2UnlinkMcb(Vcb, Mcb);
+ Ext2DerefMcb(Mcb);
+ Ext2LinkHeadMcb(Vcb, Mcb);
+
+ } else {
+ Mcb->Fcb = NULL;
+ Ext2DerefMcb(Mcb);
+ }
+ Fcb->Mcb = NULL;
+ }
+
+ ExReleaseResourceLite(&Vcb->McbLock);
+}
+
+VOID
Ext2FreeFcb (IN PEXT2_FCB Fcb)
{
PEXT2_VCB Vcb = Fcb->Vcb;
- 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)));
+ _SEH2_TRY {
+
+ ASSERT((Fcb != NULL) && (Fcb->Identifier.Type == EXT2FCB) &&
+ (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
+ ASSERT(0 == Fcb->ReferenceCount);
#ifndef _WIN2K_TARGET_
- FsRtlTeardownPerStreamContexts(&Fcb->Header);
+ FsRtlTeardownPerStreamContexts(&Fcb->Header);
#endif
- if ((Fcb->Mcb->Identifier.Type == EXT2MCB) &&
- (Fcb->Mcb->Identifier.Size == sizeof(EXT2_MCB))) {
-
- ASSERT (Fcb->Mcb->Fcb == Fcb);
- if (IsMcbSpecialFile(Fcb->Mcb) || IsFileDeleted(Fcb->Mcb)) {
-
- ASSERT(!IsRoot(Fcb));
- Ext2RemoveMcb(Fcb->Vcb, Fcb->Mcb);
- Fcb->Mcb->Fcb = NULL;
-
- Ext2UnlinkMcb(Vcb, Fcb->Mcb);
- Ext2DerefMcb(Fcb->Mcb);
- Ext2LinkHeadMcb(Vcb, Fcb->Mcb);
-
- } else {
-
- Fcb->Mcb->Fcb = NULL;
- Ext2DerefMcb(Fcb->Mcb);
- }
-
+ 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);
+ }
+ }
+
+ } _SEH2_FINALLY {
+ } _SEH2_END;
+}
+
+VOID
+Ext2ReleaseFcb (IN PEXT2_FCB Fcb)
+{
+ 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 {
- DbgBreak();
- }
-
- Ext2RemoveFcb(Fcb->Vcb, Fcb);
-
- FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
- FsRtlUninitializeOplock(&Fcb->Oplock);
- ExDeleteResourceLite(&Fcb->MainResource);
- ExDeleteResourceLite(&Fcb->PagingIoResource);
-
- DEBUG(DL_RES, ( "Ext2FreeFcb: Fcb (%p) is being released: %wZ.\n",
- Fcb, &Fcb->Mcb->FullName));
-
- Fcb->Identifier.Type = 0;
- Fcb->Identifier.Size = 0;
-
- ExFreeToNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList), Fcb);
- DEC_MEM_COUNT(PS_FCB, Fcb, sizeof(EXT2_FCB));
-}
-
-/* Insert Fcb to Vcb->FcbList queue */
+ 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);
+ }
+}
+
+/* Insert Fcb to Vcb->FcbList queue, with Vcb->FcbLock Acquired. */
VOID
Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb)
{
- ExInterlockedInsertTailList(&Vcb->FcbList, &Fcb->Next,
&Vcb->FcbLock);
+ ASSERT(ExIsResourceAcquiredExclusiveLite(&Vcb->FcbLock));
+
+ KeQuerySystemTime(&Fcb->TsDrop);
Ext2ReferXcb(&Vcb->FcbCount);
-}
-
-/* Remove Fcb from Vcb->FcbList queue */
-
-VOID
-Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb)
-{
- KIRQL irql;
-
- KeAcquireSpinLock(&Vcb->FcbLock, &irql);
- RemoveEntryList(&(Fcb->Next));
- if (Vcb->FcbCount > 0) {
- Ext2DerefXcb(&Vcb->FcbCount);
- } else {
- DbgBreak();
- }
- KeReleaseSpinLock(&Vcb->FcbLock, irql);
+ Ext2ReferXcb(&Vcb->ReferenceCount);
+ InsertTailList(&Vcb->FcbList, &Fcb->Next);
}
PEXT2_CCB
@@ -321,7 +356,6 @@
Ext2FreeCcb (IN PEXT2_VCB Vcb, IN PEXT2_CCB Ccb)
{
ASSERT(Ccb != NULL);
-
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
@@ -2334,7 +2368,7 @@
/* initialize Fcb list head */
InitializeListHead(&Vcb->FcbList);
- KeInitializeSpinLock(&Vcb->FcbLock);
+ ExInitializeResourceLite(&Vcb->FcbLock);
/* initialize Mcb list head */
InitializeListHead(&(Vcb->McbList));
@@ -2783,7 +2817,7 @@
Ext2CleanupAllMcbs(Vcb);
- Ext2DropGroup(Vcb);
+ Ext2DropBH(Vcb);
if (Vcb->bd.bd_bh_cache)
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
@@ -2805,6 +2839,7 @@
ObDereferenceObject(Vcb->TargetDeviceObject);
ExDeleteNPagedLookasideList(&(Vcb->InodeLookasideList));
+ ExDeleteResourceLite(&Vcb->FcbLock);
ExDeleteResourceLite(&Vcb->McbLock);
ExDeleteResourceLite(&Vcb->MetaInode);
ExDeleteResourceLite(&Vcb->MetaBlock);
@@ -2993,6 +3028,8 @@
BOOLEAN WaitLock;
_SEH2_TRY {
+
+ Reaper->Thread = PsGetCurrentThread();
/* wake up DirverEntry */
KeSetEvent(&Reaper->Engine, 0, FALSE);
@@ -3097,24 +3134,26 @@
}
-/* 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;
}
@@ -3127,6 +3166,7 @@
break;
}
}
+
wake = IsListEmpty(&Vcb->bd.bd_bh_free);
ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
@@ -3153,6 +3193,8 @@
BOOLEAN NonWait = FALSE;
_SEH2_TRY {
+
+ Reaper->Thread = PsGetCurrentThread();
/* wake up DirverEntry */
KeSetEvent(&Reaper->Engine, 0, FALSE);
@@ -3191,8 +3233,7 @@
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);
@@ -3206,6 +3247,146 @@
bh = CONTAINING_RECORD(Link, struct buffer_head, b_link);
ASSERT(0 == atomic_read(&bh->b_count));
free_buffer_head(bh);
+ }
+ }
+
+ } _SEH2_FINALLY {
+
+ if (GlobalAcquired) {
+ ExReleaseResourceLite(&Ext2Global->Resource);
+ }
+
+ KeSetEvent(&Reaper->Engine, 0, FALSE);
+ } _SEH2_END;
+
+ 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 NTAPI
+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;
+
+ _SEH2_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);
}
}
Modified: trunk/reactos/drivers/filesystems/ext2/src/write.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ext2/s…
==============================================================================
--- trunk/reactos/drivers/filesystems/ext2/src/write.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ext2/src/write.c [iso-8859-1] Fri Jul 29 10:29:16
2016
@@ -91,7 +91,10 @@
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Vcb->PagingIoResource);
+ ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
+ Ext2DropBH(Vcb);
CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
+ ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
}
IoSetTopLevelIrp(NULL);
Modified: trunk/reactos/media/doc/README.FSD
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.FSD?rev=7…
==============================================================================
--- trunk/reactos/media/doc/README.FSD [iso-8859-1] (original)
+++ trunk/reactos/media/doc/README.FSD [iso-8859-1] Fri Jul 29 10:29:16 2016
@@ -7,7 +7,7 @@
The following FSD are shared with:
http://www.ext2fsd.com/
-reactos/drivers/filesystems/ext2 # Synced to 0.66
+reactos/drivers/filesystems/ext2 # Synced to 0.68
The following FSD are shared with:
http://www.acc.umu.se/~bosse/