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/in... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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/sr... ============================================================================== --- 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=72... ============================================================================== --- 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/