mirror of
https://github.com/reactos/reactos.git
synced 2025-05-25 12:14:32 +00:00
[EXT2]
Upgrade the driver to release 0.68. CORE-11714 svn path=/trunk/; revision=72042
This commit is contained in:
parent
45aa3e9f88
commit
b5746c9e6b
14 changed files with 935 additions and 926 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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/
|
||||
|
||||
|
|
Loading…
Reference in a new issue