Upgrade the driver to release 0.68.

CORE-11714

svn path=/trunk/; revision=72042
This commit is contained in:
Pierre Schweitzer 2016-07-29 10:29:16 +00:00
parent 45aa3e9f88
commit b5746c9e6b
14 changed files with 935 additions and 926 deletions

View file

@ -47,7 +47,7 @@
/* STRUCTS & CONSTS******************************************************/
#define EXT2FSD_VERSION "0.66"
#define EXT2FSD_VERSION "0.68"
/* WDK DEFINITIONS ******************************************************/
@ -491,6 +491,7 @@ typedef PVOID PBCB;
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 @@ typedef struct _EXT2_GLOBAL {
LIST_ENTRY VcbList;
/* Cleaning thread related: resource cleaner */
EXT2_REAPER FcbReaper;
EXT2_REAPER McbReaper;
EXT2_REAPER bhReaper;
@ -647,12 +649,17 @@ typedef struct _EXT2_VCB {
// Resource for Mcb (Meta data control block)
ERESOURCE McbLock;
// Entry of Mcb Tree (Root Node)
PEXT2_MCB McbTree;
// List of FCBs for open files on this volume
ERESOURCE FcbLock;
LIST_ENTRY FcbList;
ULONG FcbCount;
// Mcb list
LIST_ENTRY McbList;
ULONG NumOfMcb;
LIST_ENTRY McbList;
// Entry of Mcb Tree (Root Node)
PEXT2_MCB McbTree;
// Link list to Global
LIST_ENTRY Next;
@ -663,10 +670,6 @@ typedef struct _EXT2_VCB {
// 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 @@ typedef struct _EXT2_FCB {
// List of FCBs for this volume
LIST_ENTRY Next;
LARGE_INTEGER TsDrop; /* drop time */
SECTION_OBJECT_POINTERS SectionObject;
@ -863,7 +867,7 @@ typedef struct _EXT2_FCB {
#define FCB_FROM_POOL 0x00000001
#define FCB_PAGE_FILE 0x00000002
#define FCB_FILE_MODIFIED 0x00000020
#define FCB_STATE_BUSY 0x00000040
#define FCB_ALLOC_IN_CREATE 0x00000080
#define FCB_ALLOC_IN_WRITE 0x00000100
#define FCB_ALLOC_IN_SETINFO 0x00000200
@ -961,12 +965,10 @@ struct _EXT2_MCB {
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 @@ VOID
Ext2PutGroup(IN PEXT2_VCB Vcb);
VOID
Ext2DropGroup(IN PEXT2_VCB Vcb);
Ext2DropBH(IN PEXT2_VCB Vcb);
BOOLEAN
Ext2SaveGroup(
@ -2438,7 +2440,6 @@ struct buffer_head *ext3_bread(struct ext2_icb *icb, struct inode *inode,
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,
@ -2523,6 +2524,12 @@ Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext);
// Memory.c
//
VOID
NTAPI
Ext2FcbReaperThread(
PVOID Context
);
VOID
NTAPI
Ext2McbReaperThread(
@ -2550,15 +2557,17 @@ Ext2AllocateFcb (
IN PEXT2_MCB Mcb
);
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);

View file

@ -351,7 +351,7 @@ Ext2ReadWriteBlocks(
IoBuildPartialMdl( MasterIrp->MdlAddress,
Mdl,
(PCHAR)MasterIrp->UserBuffer +Extent->Offset,
(PCHAR)MasterIrp->UserBuffer+Extent->Offset,
Extent->Length );
IoSetNextIrpStackLocation(Irp);
@ -568,8 +568,7 @@ Ext2ReadDisk(
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;
}

View file

@ -73,14 +73,12 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
_SEH2_LEAVE;
}
VcbResourceAcquired =
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE
);
if (Fcb->Identifier.Type == EXT2VCB) {
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE);
VcbResourceAcquired = TRUE;
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
Vcb->LockFile == FileObject ){
@ -103,6 +101,12 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
FcbResourceAcquired =
ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
TRUE
);
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
@ -135,18 +139,8 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
}
FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
}
ExReleaseResourceLite(&Vcb->MainResource);
VcbResourceAcquired = FALSE;
FcbResourceAcquired =
ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
TRUE
);
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
@ -284,6 +278,37 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
}
}
IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
if (!IsDirectory(Fcb)) {
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
(Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) &&
(Fcb->SectionObject.DataSectionObject != NULL)) {
if (!IsVcbReadOnly(Vcb)) {
CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
}
/* purge cache if all remaining openings are non-cached */
if (Fcb->NonCachedOpenCount > 0 ||
IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
ExReleaseResourceLite(&(Fcb->PagingIoResource));
}
/* CcPurge could generate recursive IRP_MJ_CLOSE request */
CcPurgeCacheSection( &Fcb->SectionObject,
NULL,
0,
FALSE );
}
}
CcUninitializeCacheMap(FileObject, NULL, NULL);
}
if (SymLinkDelete ||
(IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) &&
Fcb->OpenHandleCount == 0) ) {
@ -337,35 +362,6 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
}
}
if (!IsDirectory(Fcb)) {
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
(Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) &&
(Fcb->SectionObject.DataSectionObject != NULL)) {
if (!IsVcbReadOnly(Vcb)) {
CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
}
/* purge cache if all remaining openings are non-cached */
if (Fcb->NonCachedOpenCount > 0) {
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
ExReleaseResourceLite(&(Fcb->PagingIoResource));
}
CcPurgeCacheSection( &Fcb->SectionObject,
NULL,
0,
FALSE );
}
}
CcUninitializeCacheMap(FileObject, NULL, NULL);
}
IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));

View file

@ -31,11 +31,10 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
PFILE_OBJECT FileObject;
PEXT2_FCB Fcb = NULL;
PEXT2_CCB Ccb = NULL;
BOOLEAN VcbResourceAcquired = FALSE;
BOOLEAN FcbResourceAcquired = FALSE;
BOOLEAN bDeleteVcb = FALSE;
BOOLEAN bBeingClosed = FALSE;
BOOLEAN bSkipLeave = FALSE;
BOOLEAN FcbDerefDeferred = FALSE;
_SEH2_TRY {
@ -55,25 +54,6 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE )) {
DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
Vcb->OpenHandleCount, Vcb->ReferenceCount));
Status = STATUS_PENDING;
_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)) {
FileObject = NULL;
@ -92,11 +72,30 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
Ccb = (PEXT2_CCB) FileObject->FsContext2;
}
DEBUG(DL_INF, ( "Ext2Close: (VCB) bBeingClosed = %d Vcb = %p ReferCount = %d\n",
bBeingClosed, Vcb, Vcb->ReferenceCount));
DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n",
Vcb, Vcb->ReferenceCount));
/*
* WARNING: don't release Vcb resource lock here.
*
* CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE
* which would cause revrese order of lock acquirision:
* 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock
* 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock
*/
if (Fcb->Identifier.Type == EXT2VCB) {
if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE )) {
DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
Vcb->OpenHandleCount, Vcb->ReferenceCount));
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
VcbResourceAcquired = TRUE;
if (Ccb) {
Ext2DerefXcb(&Vcb->ReferenceCount);
@ -112,7 +111,7 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
}
if ( Fcb->Identifier.Type != EXT2FCB ||
Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
_SEH2_LEAVE;
}
@ -126,68 +125,40 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
if (!Ccb) {
if (Ccb == NULL ||
Ccb->Identifier.Type != EXT2CCB ||
Ccb->Identifier.Size != sizeof(EXT2_CCB)) {
Status = STATUS_SUCCESS;
_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;
}
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;
}
/* 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 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
} else {
Ext2CompleteIrpContext(IrpContext, Status);
if (bDeleteVcb) {
PVPB Vpb = Vcb->Vpb;
DEBUG(DL_DBG, ( "Ext2Close: Try to free Vcb %p and Vpb %p\n",
Vcb, Vpb));
Ext2CheckDismount(IrpContext, Vcb, FALSE);
}
}
}
if (FcbDerefDeferred)
Ext2DerefXcb(&Fcb->ReferenceCount);
} _SEH2_END;
return Status;

View file

@ -698,13 +698,14 @@ Ext2CreateFile(
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 @@ Ext2CreateFile(
if (ParentFcb) {
ParentMcb = ParentFcb->Mcb;
SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
Ext2ReferMcb(ParentMcb);
ParentFcb = NULL;
}
if (FileName.Length == 0) {
if (ParentFcb) {
Mcb = ParentFcb->Mcb;
if (ParentMcb) {
Mcb = ParentMcb;
Ext2ReferMcb(Mcb);
Status = STATUS_SUCCESS;
goto McbExisting;
@ -811,7 +812,7 @@ Ext2CreateFile(
RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
if (ParentFcb && FileName.Buffer[0] == L'\\') {
if (IrpSp->FileObject->RelatedFileObject && FileName.Buffer[0] == L'\\') {
Status = STATUS_INVALID_PARAMETER;
_SEH2_LEAVE;
}
@ -952,9 +953,9 @@ Dissecting:
_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 @@ Dissecting:
_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 @@ Dissecting:
}
Openit:
if (!bFcbLockAcquired) {
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
bFcbLockAcquired = TRUE;
}
/* Mcb should already be referred and symlink is too */
if (Mcb) {
@ -1221,10 +1232,15 @@ Openit:
}
if (Fcb) {
/* grab Fcb's reference first to avoid the race between
Ext2Close (it could free the Fcb we are accessing) */
Ext2ReferXcb(&Fcb->ReferenceCount);
}
ExReleaseResourceLite(&Vcb->FcbLock);
bFcbLockAcquired = FALSE;
if (Fcb) {
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
bMainResourceAcquired = TRUE;
@ -1565,6 +1581,9 @@ Openit:
} _SEH2_FINALLY {
if (bFcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
}
if (ParentMcb) {
Ext2DerefMcb(ParentMcb);
@ -1606,29 +1625,24 @@ Openit:
Ext2FreeCcb(Vcb, Ccb);
}
}
if (Fcb && Ext2DerefXcb(&Fcb->ReferenceCount) == 0) {
if (Fcb != NULL) {
if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
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;
}
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 (bCreated) {
Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
}
Ext2FreeFcb(Fcb);
Fcb = NULL;
bMainResourceAcquired = FALSE;
}
if (bMainResourceAcquired) {
@ -1641,14 +1655,12 @@ Openit:
Ext2FreePool(FileName.Buffer, EXT2_FNAME_MAGIC);
}
/* dereference parent Fcb, free it if it goes to zero */
/* dereference Fcb and parent */
if (Fcb) {
Ext2ReleaseFcb(Fcb);
}
if (ParentFcb) {
ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
if (bParentFcbCreated) {
if (Ext2DerefXcb(&ParentFcb->ReferenceCount) == 0) {
Ext2FreeFcb(ParentFcb);
}
}
Ext2ReleaseFcb(ParentFcb);
}
/* drop SymLink's refer: If succeeds, Ext2AllocateCcb should refer

View file

@ -48,9 +48,6 @@ Ext2LoadSuper(IN PEXT2_VCB Vcb,
bVerify );
if (!NT_SUCCESS(Status)) {
DEBUG(DL_ERR, ( "Ext2ReadDisk: disk device error.\n"));
Ext2FreePool(Ext2Sb, EXT2_SB_MAGIC);
Ext2Sb = NULL;
}
@ -209,7 +206,7 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb)
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 @@ Ext2DropGroup(IN PEXT2_VCB Vcb)
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);
}

View file

@ -1099,77 +1099,6 @@ out:
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 @@ found_extent:
* with leaves.
*/
ext4_lblk_t
ext4_ext_next_allocated_block(struct ext4_ext_path *path, int at)
ext4_ext_next_allocated_block(struct ext4_ext_path *path)
{
if (at == 0 && !path->p_ext && !path->p_idx)
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);
if (path[depth].p_idx !=
EXT_LAST_INDEX(path[depth].p_hdr))
return le32_to_cpu(path[depth].p_idx[1].ei_block);
}
at--;
depth--;
}
return EXT_MAX_BLOCKS;
@ -1482,14 +1415,12 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct ext4_ext_path *path)
/*
* 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 @@ static int ext4_ext_correct_indexes(void *icb, handle_t *handle,
__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 != EXT_FIRST_EXTENT(eh)) {
/* we correct tree if first leaf got modified only */
return 0;
}
if (ex == NULL || eh == NULL)
return -EIO;
/*
* 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;
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;
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 @@ merge:
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 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
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)
static int ext4_remove_blocks(void *icb, handle_t *handle, struct inode *inode,
struct ext4_extent *ex,
unsigned long from, unsigned long 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);
}
struct buffer_head *bh;
int i;
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;
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)
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);
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));
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 {
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);
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;
return 0;
}
/*
* NOTE: After removal, path should not be reused.
* 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_remove_extent(void *icb,
handle_t *handle,
struct inode *inode, struct ext4_ext_path **path)
int ext4_ext_rm_idx(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);
int err;
ext4_fsblk_t leaf;
/* free index block */
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;
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;
}
int __ext4_ext_truncate(void *icb,
handle_t *handle,
struct inode *inode,
ext4_lblk_t from, ext4_lblk_t to)
static int
ext4_ext_rm_leaf(void *icb, handle_t *handle, struct inode *inode,
struct ext4_ext_path *path, unsigned long start)
{
int depth = ext_depth(inode), ret = -EIO;
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;
struct ext4_ext_path *path = NULL, *npath;
ext4_lblk_t now = from;
if (to < from)
return -EINVAL;
/* 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);
npath = ext4_find_extent(inode, from, &path, 0);
if (IS_ERR(npath))
goto out;
/* find where to start removing */
ex = EXT_LAST_EXTENT(eh);
path = npath;
ex = path[depth].p_ext;
if (!ex)
goto out;
ex_ee_block = le32_to_cpu(ex->ee_block);
ex_ee_len = ext4_ext_get_actual_len(ex);
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)) {
while (ex >= EXT_FIRST_EXTENT(eh) &&
ex_ee_block + ex_ee_len > start) {
path[depth].p_ext = ex;
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);
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;
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;
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 {
if (start + len - 1 > to) {
new_len = start + len - 1 - to;
len -= new_len;
new_start = to + 1;
newblock += to + 1 - start;
}
/* 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);
}
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);
/* 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;
}
npath = ext4_find_extent(inode, now, &path, 0);
if (IS_ERR(npath))
/*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;
path = npath;
depth = ext_depth(inode);
ex = path[depth].p_ext;
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 (path) {
ext4_ext_drop_refs(path);
kfree(path);
}
if (IS_ERR(npath))
ret = PTR_ERR(npath);
return ret;
return err;
}
/*
@ -2438,6 +2172,140 @@ fix_extent_len:
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 @@ int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_f
/* 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 @@ out2:
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)

View file

@ -504,7 +504,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
ULONG Length;
PVOID Buffer;
BOOLEAN VcbMainResourceAcquired = FALSE;
BOOLEAN FcbMainResourceAcquired = FALSE;
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
@ -542,18 +541,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
_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)) {
Status = STATUS_ACCESS_DENIED;
_SEH2_LEAVE;
@ -1047,10 +1034,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
ExReleaseResourceLite(&Fcb->MainResource);
}
if (VcbMainResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource);
}
if (!IrpContext->ExceptionInProgress) {
if (Status == STATUS_PENDING ||
Status == STATUS_CANT_WAIT ) {
@ -1347,8 +1330,7 @@ Ext2SetRenameInfo(
BOOLEAN bMove = FALSE;
BOOLEAN bTargetRemoved = FALSE;
BOOLEAN bNewTargetDcb = FALSE;
BOOLEAN bNewParentDcb = FALSE;
BOOLEAN bFcbLockAcquired = FALSE;
PFILE_RENAME_INFORMATION FRI;
@ -1435,16 +1417,17 @@ Ext2SetRenameInfo(
bMove = TRUE;
}
if (!bFcbLockAcquired) {
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
bFcbLockAcquired = TRUE;
}
TargetDcb = TargetMcb->Fcb;
if (TargetDcb == NULL) {
TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb);
if (TargetDcb) {
Ext2ReferXcb(&TargetDcb->ReferenceCount);
bNewTargetDcb = TRUE;
}
}
if (TargetDcb) {
SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
Ext2ReferXcb(&TargetDcb->ReferenceCount);
}
ParentMcb = Mcb->Parent;
@ -1454,15 +1437,16 @@ Ext2SetRenameInfo(
if (ParentDcb == NULL) {
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
if (ParentDcb) {
Ext2ReferXcb(&ParentDcb->ReferenceCount);
bNewParentDcb = TRUE;
}
}
if (ParentDcb) {
SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
}
}
if (ParentDcb) {
Ext2ReferXcb(&ParentDcb->ReferenceCount);
}
if (bFcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
bFcbLockAcquired = FALSE;
}
if (!TargetDcb || !ParentDcb) {
Status = STATUS_INSUFFICIENT_RESOURCES;
@ -1625,40 +1609,25 @@ Ext2SetRenameInfo(
FILE_NOTIFY_CHANGE_DIR_NAME :
FILE_NOTIFY_CHANGE_FILE_NAME ),
FILE_ACTION_RENAMED_NEW_NAME );
}
}
errorout:
if (bFcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
bFcbLockAcquired = FALSE;
}
if (NewEntry)
Ext2FreeEntry(NewEntry);
if (TargetDcb) {
if (ParentDcb && ParentDcb->Inode->i_ino != TargetDcb->Inode->i_ino) {
ClearLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
}
ClearLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
Ext2ReleaseFcb(TargetDcb);
}
if (bNewTargetDcb) {
ASSERT(TargetDcb != NULL);
if (Ext2DerefXcb(&TargetDcb->ReferenceCount) == 0) {
Ext2FreeFcb(TargetDcb);
TargetDcb = NULL;
} else {
DEBUG(DL_RES, ( "Ext2SetRenameInfo: TargetDcb is resued by other threads.\n"));
}
}
if (bNewParentDcb) {
ASSERT(ParentDcb != NULL);
if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) {
Ext2FreeFcb(ParentDcb);
ParentDcb = NULL;
} else {
DEBUG(DL_RES, ( "Ext2SetRenameInfo: ParentDcb is resued by other threads.\n"));
}
if (ParentDcb) {
Ext2ReleaseFcb(ParentDcb);
}
if (ExistingMcb)
@ -1698,8 +1667,8 @@ Ext2SetLinkInfo(
BOOLEAN ReplaceIfExists;
BOOLEAN bTargetRemoved = FALSE;
BOOLEAN bNewTargetDcb = FALSE;
BOOLEAN bNewParentDcb = FALSE;
BOOLEAN bFcbLockAcquired = FALSE;
PFILE_LINK_INFORMATION FLI;
@ -1781,17 +1750,15 @@ Ext2SetLinkInfo(
}
}
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
bFcbLockAcquired = TRUE;
TargetDcb = TargetMcb->Fcb;
if (TargetDcb == NULL) {
TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb);
if (TargetDcb) {
Ext2ReferXcb(&TargetDcb->ReferenceCount);
bNewTargetDcb = TRUE;
}
}
if (TargetDcb) {
SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
Ext2ReferXcb(&TargetDcb->ReferenceCount);
}
ParentMcb = Mcb->Parent;
@ -1801,15 +1768,16 @@ Ext2SetLinkInfo(
if (ParentDcb == NULL) {
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
if (ParentDcb) {
Ext2ReferXcb(&ParentDcb->ReferenceCount);
bNewParentDcb = TRUE;
}
}
if (ParentDcb) {
SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
}
}
if (ParentDcb) {
Ext2ReferXcb(&ParentDcb->ReferenceCount);
}
if (bFcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
bFcbLockAcquired = FALSE;
}
if (!TargetDcb || !ParentDcb) {
Status = STATUS_INSUFFICIENT_RESOURCES;
@ -1887,31 +1855,17 @@ Ext2SetLinkInfo(
errorout:
if (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);
Ext2ReleaseFcb(TargetDcb);
}
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"));
}
if (ParentDcb) {
Ext2ReleaseFcb(ParentDcb);
}
if (ExistingMcb)
@ -1957,7 +1911,7 @@ Ext2DeleteFile(
LARGE_INTEGER Size;
LARGE_INTEGER SysTime;
BOOLEAN bNewDcb = FALSE;
BOOLEAN bFcbLockAcquired = FALSE;
DEBUG(DL_INF, ( "Ext2DeleteFile: File %wZ (%xh) will be deleted!\n",
&Mcb->FullName, Mcb->Inode.i_ino));
@ -1979,16 +1933,22 @@ Ext2DeleteFile(
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
VcbResourceAcquired = TRUE;
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
bFcbLockAcquired = TRUE;
if (!(Dcb = Mcb->Parent->Fcb)) {
Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent);
if (Dcb) {
Ext2ReferXcb(&Dcb->ReferenceCount);
bNewDcb = TRUE;
}
}
if (Dcb) {
Ext2ReferXcb(&Dcb->ReferenceCount);
}
if (bFcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
bFcbLockAcquired = FALSE;
}
if (Dcb) {
SetLongFlag(Dcb->Flags, FCB_STATE_BUSY);
DcbResourceAcquired =
ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
@ -2090,21 +2050,18 @@ Ext2DeleteFile(
ExReleaseResourceLite(&Dcb->MainResource);
}
if (Dcb) {
ClearLongFlag(Dcb->Flags, FCB_STATE_BUSY);
if (bNewDcb) {
if (Ext2DerefXcb(&Dcb->ReferenceCount) == 0) {
Ext2FreeFcb(Dcb);
} else {
DEBUG(DL_ERR, ( "Ext2DeleteFile: Dcb %wZ used by other threads.\n",
&Mcb->FullName ));
}
}
if (bFcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
}
if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource);
}
if (Dcb) {
Ext2ReleaseFcb(Dcb);
}
Ext2DerefMcb(Mcb);
} _SEH2_END;

View file

@ -81,14 +81,21 @@ Ext2FlushVolume (
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;
}

View file

@ -1582,8 +1582,6 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
PEXT2_MCB Mcb = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN bNewParentDcb = FALSE;
BOOLEAN MainResourceAcquired = FALSE;
PVOID InputBuffer;
ULONG InputBufferLength;
@ -1600,6 +1598,8 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
PCHAR OemNameBuffer = NULL;
int OemNameLength = 0, i;
BOOLEAN MainResourceAcquired = FALSE;
BOOLEAN FcbLockAcquired = FALSE;
_SEH2_TRY {
@ -1614,19 +1614,26 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
FcbLockAcquired = TRUE;
ParentMcb = Mcb->Parent;
ParentDcb = ParentMcb->Fcb;
if (ParentDcb == NULL) {
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
if (ParentDcb) {
Ext2ReferXcb(&ParentDcb->ReferenceCount);
bNewParentDcb = TRUE;
}
}
if (ParentDcb) {
Ext2ReferXcb(&ParentDcb->ReferenceCount);
}
if (!Mcb)
_SEH2_LEAVE;
if (FcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
FcbLockAcquired = FALSE;
}
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
@ -1702,6 +1709,11 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
} _SEH2_FINALLY {
if (FcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
FcbLockAcquired = FALSE;
}
if (MainResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource);
}
@ -1719,16 +1731,6 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
FILE_ACTION_MODIFIED );
}
if (bNewParentDcb) {
ASSERT(ParentDcb != NULL);
if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) {
Ext2FreeFcb(ParentDcb);
ParentDcb = NULL;
} else {
DEBUG(DL_RES, ( "Ext2SetRenameInfo: ParentDcb is resued by other threads.\n"));
}
}
if (!_SEH2_AbnormalTermination()) {
if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) {
Status = Ext2QueueRequest(IrpContext);
@ -1736,6 +1738,10 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
Ext2CompleteIrpContext(IrpContext, Status);
}
}
if (ParentDcb) {
Ext2ReleaseFcb(ParentDcb);
}
} _SEH2_END;
return Status;
@ -1786,14 +1792,15 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
PEXT2_CCB Ccb = NULL;
PEXT2_MCB Mcb = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN bNewParentDcb = FALSE;
BOOLEAN bFcbAllocated = FALSE;
BOOLEAN MainResourceAcquired = FALSE;
PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */
PEXT2_MCB ParentMcb = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN FcbLockAcquired = FALSE;
BOOLEAN MainResourceAcquired = FALSE;
_SEH2_TRY {
Ccb = IrpContext->Ccb;
@ -1805,14 +1812,16 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
Mcb = IrpContext->Fcb->Mcb;
Irp = IrpContext->Irp;
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
FcbLockAcquired = TRUE;
ParentMcb = Mcb->Parent;
ParentDcb = ParentMcb->Fcb;
if (ParentDcb == NULL) {
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
if (ParentDcb) {
Ext2ReferXcb(&ParentDcb->ReferenceCount);
bNewParentDcb = TRUE;
}
}
if (ParentDcb) {
Ext2ReferXcb(&ParentDcb->ReferenceCount);
}
if (!Mcb || !IsInodeSymLink(&Mcb->Inode) ||
@ -1820,15 +1829,19 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
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,
@ -1848,6 +1861,10 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
} _SEH2_FINALLY {
if (FcbLockAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
}
if (MainResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource);
}
@ -1862,16 +1879,6 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
}
if (bNewParentDcb) {
ASSERT(ParentDcb != NULL);
if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) {
Ext2FreeFcb(ParentDcb);
ParentDcb = NULL;
} else {
DEBUG(DL_RES, ( "Ext2DeleteReparsePoint: ParentDcb is resued.\n"));
}
}
if (!_SEH2_AbnormalTermination()) {
if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) {
Status = Ext2QueueRequest(IrpContext);
@ -1879,11 +1886,13 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
Ext2CompleteIrpContext(IrpContext, Status);
}
}
if (bFcbAllocated) {
if (Ext2DerefXcb(&Fcb->ReferenceCount) == 0) {
Ext2FreeFcb(Fcb);
}
if (ParentDcb) {
Ext2ReleaseFcb(ParentDcb);
}
if (Fcb) {
Ext2ReleaseFcb(Fcb);
}
} _SEH2_END;
@ -2450,13 +2459,7 @@ Ext2VerifyVolume (IN PEXT2_IRP_CONTEXT IrpContext)
} else {
Status = STATUS_WRONG_VOLUME;
if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource);
VcbResourceAcquired = FALSE;
}
Ext2PurgeVolume(Vcb, FALSE);
VcbResourceAcquired =
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
SetLongFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);
ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);
@ -2607,8 +2610,9 @@ Ext2CheckDismount (
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE );
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
(IrpContext->RealDevice == Vcb->RealDevice)) {
if (IrpContext &&
IrpContext->MajorFunction == IRP_MJ_CREATE &&
IrpContext->RealDevice == Vcb->RealDevice) {
UnCleanCount = 2;
} else {
UnCleanCount = 1;
@ -2696,59 +2700,44 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
IN BOOLEAN FlushBeforePurge )
{
PEXT2_FCB Fcb;
LIST_ENTRY FcbList;
PLIST_ENTRY ListEntry;
PFCB_LIST_ENTRY FcbListEntry;
LIST_ENTRY List, *Next;
BOOLEAN VcbResourceAcquired = FALSE;
BOOLEAN FcbResourceAcquired = FALSE;
BOOLEAN gdResourceAcquired = FALSE;
_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);
InitializeListHead(&List);
FcbListEntry= NULL;
InitializeListHead(&FcbList);
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
FcbResourceAcquired = TRUE;
for (ListEntry = Vcb->FcbList.Flink;
ListEntry != &Vcb->FcbList;
ListEntry = ListEntry->Flink ) {
while (!IsListEmpty(&Vcb->FcbList)) {
Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
Next = RemoveHeadList(&Vcb->FcbList);
Fcb = CONTAINING_RECORD(Next, 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"));
}
DEBUG(DL_INF, ( "Ext2PurgeVolume: %wZ refercount=%xh\n",
&Fcb->Mcb->FullName, Fcb->ReferenceCount));
InsertTailList(&List, &Fcb->Next);
}
while (!IsListEmpty(&FcbList)) {
while (!IsListEmpty(&List)) {
ListEntry = RemoveHeadList(&FcbList);
FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next);
Fcb = FcbListEntry->Fcb;
Next = RemoveHeadList(&List);
Fcb = CONTAINING_RECORD(Next, EXT2_FCB, Next);
if (ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
@ -2756,16 +2745,28 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
Ext2PurgeFile(Fcb, FlushBeforePurge);
if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1) {
Ext2FreeFcb(Fcb);
if (Fcb->ReferenceCount <= 1) {
Fcb->TsDrop.QuadPart = 0;
InsertHeadList(&Vcb->FcbList, &Fcb->Next);
} else {
ExReleaseResourceLite(&Fcb->MainResource);
InsertTailList(&Vcb->FcbList, &Fcb->Next);
}
ExReleaseResourceLite(&Fcb->MainResource);
}
Ext2FreePool(FcbListEntry, EXT2_FLIST_MAGIC);
}
if (FcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
FcbResourceAcquired = FALSE;
}
/* acquire bd lock to avoid bh creation */
ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
gdResourceAcquired = TRUE;
/* discard buffer_headers for group_desc */
Ext2DropBH(Vcb);
if (FlushBeforePurge) {
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Vcb->PagingIoResource);
@ -2777,11 +2778,6 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite);
}
if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource);
VcbResourceAcquired = FALSE;
}
if (Vcb->SectionObject.DataSectionObject) {
CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE);
}
@ -2790,6 +2786,14 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
} _SEH2_FINALLY {
if (gdResourceAcquired) {
ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
}
if (FcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->FcbLock);
}
if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource);
}
@ -2811,30 +2815,23 @@ Ext2PurgeFile ( IN PEXT2_FCB Fcb,
if (!IsVcbReadOnly(Fcb->Vcb) && FlushBeforePurge) {
DEBUG(DL_INF, ( "Ext2PurgeFile: CcFlushCache on %wZ.\n",
&Fcb->Mcb->FullName));
ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Fcb->PagingIoResource);
CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus);
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
}
if (Fcb->SectionObject.ImageSectionObject) {
DEBUG(DL_INF, ( "Ext2PurgeFile: MmFlushImageSection on %wZ.\n",
&Fcb->Mcb->FullName));
MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite);
}
if (Fcb->SectionObject.DataSectionObject) {
DEBUG(DL_INF, ( "Ext2PurgeFile: CcPurgeCacheSection on %wZ.\n",
&Fcb->Mcb->FullName));
CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
}

View file

@ -197,7 +197,7 @@ Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath)
* 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 @@ Ext2EresourceAlignmentChecking()
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaInode) & 7) == 0);
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaBlock) & 7) == 0);
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, McbLock) & 7) == 0);
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, FcbLock) & 7) == 0);
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, bd.bd_bh_lock) & 7) == 0);
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, sbi.s_gd_lock) & 7) == 0);
CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0);
@ -555,11 +556,19 @@ DriverEntry (
goto errorout;
}
Status= Ext2StartReaper(
&Ext2Global->FcbReaper,
Ext2FcbReaperThread);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
/* start resource reaper thread */
Status= Ext2StartReaper(
&Ext2Global->McbReaper,
Ext2McbReaperThread);
if (!NT_SUCCESS(Status)) {
Ext2StopReaper(&Ext2Global->FcbReaper);
goto errorout;
}
@ -567,6 +576,7 @@ DriverEntry (
&Ext2Global->bhReaper,
Ext2bhReaperThread);
if (!NT_SUCCESS(Status)) {
Ext2StopReaper(&Ext2Global->FcbReaper);
Ext2StopReaper(&Ext2Global->McbReaper);
goto errorout;
}

View file

@ -18,15 +18,11 @@ extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2AllocateFcb)
#pragma alloc_text(PAGE, Ext2FreeFcb)
#pragma alloc_text(PAGE, Ext2AllocateInode)
#pragma alloc_text(PAGE, Ext2DestroyInode)
#pragma alloc_text(PAGE, Ext2CheckBitmapConsistency)
#pragma alloc_text(PAGE, Ext2CheckSetBlock)
#pragma alloc_text(PAGE, Ext2InitializeVcb)
#pragma alloc_text(PAGE, Ext2FreeCcb)
#pragma alloc_text(PAGE, Ext2AllocateCcb)
#pragma alloc_text(PAGE, Ext2TearDownStream)
#pragma alloc_text(PAGE, Ext2DestroyVcb)
#pragma alloc_text(PAGE, Ext2SyncUninitializeCacheMap)
@ -139,6 +135,8 @@ Ext2AllocateFcb (
{
PEXT2_FCB Fcb;
ASSERT(ExIsResourceAcquiredExclusiveLite(&Vcb->FcbLock));
Fcb = (PEXT2_FCB) ExAllocateFromNPagedLookasideList(
&(Ext2Global->Ext2FcbLookasideList));
@ -200,85 +198,122 @@ Ext2AllocateFcb (
return Fcb;
}
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))) {
FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
FsRtlUninitializeOplock(&Fcb->Oplock);
ExDeleteResourceLite(&Fcb->MainResource);
ExDeleteResourceLite(&Fcb->PagingIoResource);
ASSERT (Fcb->Mcb->Fcb == Fcb);
if (IsMcbSpecialFile(Fcb->Mcb) || IsFileDeleted(Fcb->Mcb)) {
Fcb->Identifier.Type = 0;
Fcb->Identifier.Size = 0;
ASSERT(!IsRoot(Fcb));
Ext2RemoveMcb(Fcb->Vcb, Fcb->Mcb);
Fcb->Mcb->Fcb = NULL;
ExFreeToNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList), Fcb);
DEC_MEM_COUNT(PS_FCB, Fcb, sizeof(EXT2_FCB));
Ext2UnlinkMcb(Vcb, Fcb->Mcb);
Ext2DerefMcb(Fcb->Mcb);
Ext2LinkHeadMcb(Vcb, Fcb->Mcb);
} else {
Fcb->Mcb->Fcb = NULL;
Ext2DerefMcb(Fcb->Mcb);
if (0 == Ext2DerefXcb(&Vcb->ReferenceCount)) {
if (!IsMounted(Vcb) || IsDispending(Vcb)) {
Ext2CheckDismount(NULL, Vcb, FALSE);
}
}
} 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));
} _SEH2_FINALLY {
} _SEH2_END;
}
/* Insert Fcb to Vcb->FcbList queue */
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 {
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 @@ VOID
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 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
/* initialize Fcb list head */
InitializeListHead(&Vcb->FcbList);
KeInitializeSpinLock(&Vcb->FcbLock);
ExInitializeResourceLite(&Vcb->FcbLock);
/* initialize Mcb list head */
InitializeListHead(&(Vcb->McbList));
@ -2783,7 +2817,7 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb)
Ext2CleanupAllMcbs(Vcb);
Ext2DropGroup(Vcb);
Ext2DropBH(Vcb);
if (Vcb->bd.bd_bh_cache)
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
@ -2805,6 +2839,7 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb)
ObDereferenceObject(Vcb->TargetDeviceObject);
ExDeleteNPagedLookasideList(&(Vcb->InodeLookasideList));
ExDeleteResourceLite(&Vcb->FcbLock);
ExDeleteResourceLite(&Vcb->McbLock);
ExDeleteResourceLite(&Vcb->MetaInode);
ExDeleteResourceLite(&Vcb->MetaBlock);
@ -2994,6 +3029,8 @@ Ext2McbReaperThread(
_SEH2_TRY {
Reaper->Thread = PsGetCurrentThread();
/* wake up DirverEntry */
KeSetEvent(&Reaper->Engine, 0, FALSE);
@ -3097,24 +3134,26 @@ Ext2McbReaperThread(
}
/* get the first Mcb record in Vcb->McbList */
/* get buffer heads from global Vcb BH list */
BOOLEAN
Ext2QueryUnusedBH(PEXT2_VCB Vcb, PLIST_ENTRY head)
{
struct buffer_head *bh = NULL;
PLIST_ENTRY list = NULL;
LARGE_INTEGER now;
BOOLEAN wake = FALSE;
PLIST_ENTRY next = NULL;
LARGE_INTEGER now;
BOOLEAN wake = FALSE;
KeQuerySystemTime(&now);
ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE);
while (!IsListEmpty(&Vcb->bd.bd_bh_free)) {
list = RemoveHeadList(&Vcb->bd.bd_bh_free);
bh = CONTAINING_RECORD(list, struct buffer_head, b_link);
next = RemoveHeadList(&Vcb->bd.bd_bh_free);
bh = CONTAINING_RECORD(next, struct buffer_head, b_link);
if (atomic_read(&bh->b_count)) {
InitializeListHead(&bh->b_link);
/* to be inserted by brelse */
continue;
}
@ -3127,6 +3166,7 @@ Ext2QueryUnusedBH(PEXT2_VCB Vcb, PLIST_ENTRY head)
break;
}
}
wake = IsListEmpty(&Vcb->bd.bd_bh_free);
ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
@ -3154,6 +3194,8 @@ Ext2bhReaperThread(
_SEH2_TRY {
Reaper->Thread = PsGetCurrentThread();
/* wake up DirverEntry */
KeSetEvent(&Reaper->Engine, 0, FALSE);
@ -3191,8 +3233,7 @@ Ext2bhReaperThread(
Link = Link->Flink ) {
Vcb = CONTAINING_RECORD(Link, EXT2_VCB, Next);
if (Ext2QueryUnusedBH(Vcb, &List))
NonWait = TRUE;
NonWait = Ext2QueryUnusedBH(Vcb, &List);
}
if (GlobalAcquired) {
ExReleaseResourceLite(&Ext2Global->Resource);
@ -3221,6 +3262,146 @@ Ext2bhReaperThread(
PsTerminateSystemThread(STATUS_SUCCESS);
}
/* get unused Fcbs to free */
BOOLEAN
Ext2QueryUnusedFcb(PEXT2_VCB Vcb, PLIST_ENTRY list)
{
PEXT2_FCB Fcb;
PLIST_ENTRY next = NULL;
LARGE_INTEGER now;
ULONG count = 0;
ULONG tries = 0;
BOOLEAN wake = FALSE;
BOOLEAN retry = TRUE;
KeQuerySystemTime(&now);
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
again:
while (!IsListEmpty(&Vcb->FcbList)) {
next = RemoveHeadList(&Vcb->FcbList);
Fcb = CONTAINING_RECORD(next, EXT2_FCB, Next);
if (Fcb->ReferenceCount > 0) {
InsertTailList(&Vcb->FcbList, &Fcb->Next);
break;
}
retry = FALSE;
if (now.QuadPart < Fcb->TsDrop.QuadPart + 10*1000*1000*120) {
InsertHeadList(&Vcb->FcbList, &Fcb->Next);
break;
}
Ext2UnlinkFcb(Fcb);
Ext2DerefXcb(&Vcb->FcbCount);
InsertTailList(list, &Fcb->Next);
if (++count >= Ext2Global->MaxDepth) {
break;
}
}
if (retry) {
if (++tries < (Vcb->FcbCount >> 4) )
goto again;
}
ExReleaseResourceLite(&Vcb->FcbLock);
return 0;
}
/* Reaper thread to release Fcb */
VOID 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);
}
}
} _SEH2_FINALLY {
if (GlobalAcquired) {
ExReleaseResourceLite(&Ext2Global->Resource);
}
KeSetEvent(&Reaper->Engine, 0, FALSE);
} _SEH2_END;
PsTerminateSystemThread(STATUS_SUCCESS);
}
NTSTATUS
Ext2StartReaper(PEXT2_REAPER Reaper, EXT2_REAPER_RELEASE Free)
{

View file

@ -91,7 +91,10 @@ Ext2FloppyFlush(IN PVOID Parameter)
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);

View file

@ -7,7 +7,7 @@ reactos/drivers/filesystems/btrfs # Synced to 0.5
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/