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******************************************************/
|
/* STRUCTS & CONSTS******************************************************/
|
||||||
|
|
||||||
#define EXT2FSD_VERSION "0.66"
|
#define EXT2FSD_VERSION "0.68"
|
||||||
|
|
||||||
|
|
||||||
/* WDK DEFINITIONS ******************************************************/
|
/* WDK DEFINITIONS ******************************************************/
|
||||||
|
@ -491,6 +491,7 @@ typedef PVOID PBCB;
|
||||||
typedef VOID (NTAPI *EXT2_REAPER_RELEASE)(PVOID);
|
typedef VOID (NTAPI *EXT2_REAPER_RELEASE)(PVOID);
|
||||||
|
|
||||||
typedef struct _EXT2_REAPER {
|
typedef struct _EXT2_REAPER {
|
||||||
|
PETHREAD Thread;
|
||||||
KEVENT Engine;
|
KEVENT Engine;
|
||||||
KEVENT Wait;
|
KEVENT Wait;
|
||||||
EXT2_REAPER_RELEASE Free;
|
EXT2_REAPER_RELEASE Free;
|
||||||
|
@ -534,6 +535,7 @@ typedef struct _EXT2_GLOBAL {
|
||||||
LIST_ENTRY VcbList;
|
LIST_ENTRY VcbList;
|
||||||
|
|
||||||
/* Cleaning thread related: resource cleaner */
|
/* Cleaning thread related: resource cleaner */
|
||||||
|
EXT2_REAPER FcbReaper;
|
||||||
EXT2_REAPER McbReaper;
|
EXT2_REAPER McbReaper;
|
||||||
EXT2_REAPER bhReaper;
|
EXT2_REAPER bhReaper;
|
||||||
|
|
||||||
|
@ -647,12 +649,17 @@ typedef struct _EXT2_VCB {
|
||||||
// Resource for Mcb (Meta data control block)
|
// Resource for Mcb (Meta data control block)
|
||||||
ERESOURCE McbLock;
|
ERESOURCE McbLock;
|
||||||
|
|
||||||
// Entry of Mcb Tree (Root Node)
|
// List of FCBs for open files on this volume
|
||||||
PEXT2_MCB McbTree;
|
ERESOURCE FcbLock;
|
||||||
|
LIST_ENTRY FcbList;
|
||||||
|
ULONG FcbCount;
|
||||||
|
|
||||||
// Mcb list
|
// Mcb list
|
||||||
LIST_ENTRY McbList;
|
|
||||||
ULONG NumOfMcb;
|
ULONG NumOfMcb;
|
||||||
|
LIST_ENTRY McbList;
|
||||||
|
|
||||||
|
// Entry of Mcb Tree (Root Node)
|
||||||
|
PEXT2_MCB McbTree;
|
||||||
|
|
||||||
// Link list to Global
|
// Link list to Global
|
||||||
LIST_ENTRY Next;
|
LIST_ENTRY Next;
|
||||||
|
@ -663,10 +670,6 @@ typedef struct _EXT2_VCB {
|
||||||
// Dirty Mcbs of modifications for volume stream
|
// Dirty Mcbs of modifications for volume stream
|
||||||
LARGE_MCB Extents;
|
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 for the file object
|
||||||
SHARE_ACCESS ShareAccess;
|
SHARE_ACCESS ShareAccess;
|
||||||
|
@ -817,6 +820,7 @@ typedef struct _EXT2_FCB {
|
||||||
|
|
||||||
// List of FCBs for this volume
|
// List of FCBs for this volume
|
||||||
LIST_ENTRY Next;
|
LIST_ENTRY Next;
|
||||||
|
LARGE_INTEGER TsDrop; /* drop time */
|
||||||
|
|
||||||
SECTION_OBJECT_POINTERS SectionObject;
|
SECTION_OBJECT_POINTERS SectionObject;
|
||||||
|
|
||||||
|
@ -863,7 +867,7 @@ typedef struct _EXT2_FCB {
|
||||||
#define FCB_FROM_POOL 0x00000001
|
#define FCB_FROM_POOL 0x00000001
|
||||||
#define FCB_PAGE_FILE 0x00000002
|
#define FCB_PAGE_FILE 0x00000002
|
||||||
#define FCB_FILE_MODIFIED 0x00000020
|
#define FCB_FILE_MODIFIED 0x00000020
|
||||||
#define FCB_STATE_BUSY 0x00000040
|
|
||||||
#define FCB_ALLOC_IN_CREATE 0x00000080
|
#define FCB_ALLOC_IN_CREATE 0x00000080
|
||||||
#define FCB_ALLOC_IN_WRITE 0x00000100
|
#define FCB_ALLOC_IN_WRITE 0x00000100
|
||||||
#define FCB_ALLOC_IN_SETINFO 0x00000200
|
#define FCB_ALLOC_IN_SETINFO 0x00000200
|
||||||
|
@ -961,12 +965,10 @@ struct _EXT2_MCB {
|
||||||
static
|
static
|
||||||
#endif
|
#endif
|
||||||
__inline ULONG DEC_OBJ_CNT(PULONG _C) {
|
__inline ULONG DEC_OBJ_CNT(PULONG _C) {
|
||||||
if (*_C > 0) {
|
if (*_C <= 0) {
|
||||||
return InterlockedDecrement(_C);
|
|
||||||
} else {
|
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
}
|
}
|
||||||
return 0;
|
return InterlockedDecrement(_C);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if EXT2_DEBUG
|
#if EXT2_DEBUG
|
||||||
|
@ -1774,7 +1776,7 @@ VOID
|
||||||
Ext2PutGroup(IN PEXT2_VCB Vcb);
|
Ext2PutGroup(IN PEXT2_VCB Vcb);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2DropGroup(IN PEXT2_VCB Vcb);
|
Ext2DropBH(IN PEXT2_VCB Vcb);
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Ext2SaveGroup(
|
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,
|
int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry,
|
||||||
struct inode *inode, struct ext3_dir_entry_2 *de,
|
struct inode *inode, struct ext3_dir_entry_2 *de,
|
||||||
struct buffer_head *bh);
|
struct buffer_head *bh);
|
||||||
|
|
||||||
#if !defined(__REACTOS__) || defined(_MSC_VER)
|
#if !defined(__REACTOS__) || defined(_MSC_VER)
|
||||||
struct ext3_dir_entry_2 *
|
struct ext3_dir_entry_2 *
|
||||||
do_split(struct ext2_icb *icb, struct inode *dir,
|
do_split(struct ext2_icb *icb, struct inode *dir,
|
||||||
|
@ -2523,6 +2524,12 @@ Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext);
|
||||||
// Memory.c
|
// Memory.c
|
||||||
//
|
//
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
Ext2FcbReaperThread(
|
||||||
|
PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
Ext2McbReaperThread(
|
Ext2McbReaperThread(
|
||||||
|
@ -2550,15 +2557,17 @@ Ext2AllocateFcb (
|
||||||
IN PEXT2_MCB Mcb
|
IN PEXT2_MCB Mcb
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
Ext2UnlinkFcb(IN PEXT2_FCB Fcb);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2FreeFcb (IN PEXT2_FCB Fcb);
|
Ext2FreeFcb (IN PEXT2_FCB Fcb);
|
||||||
|
VOID
|
||||||
|
Ext2ReleaseFcb (IN PEXT2_FCB Fcb);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb);
|
Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb);
|
||||||
|
|
||||||
VOID
|
|
||||||
Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb);
|
|
||||||
|
|
||||||
PEXT2_CCB
|
PEXT2_CCB
|
||||||
Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink);
|
Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink);
|
||||||
|
|
||||||
|
|
|
@ -351,7 +351,7 @@ Ext2ReadWriteBlocks(
|
||||||
|
|
||||||
IoBuildPartialMdl( MasterIrp->MdlAddress,
|
IoBuildPartialMdl( MasterIrp->MdlAddress,
|
||||||
Mdl,
|
Mdl,
|
||||||
(PCHAR)MasterIrp->UserBuffer +Extent->Offset,
|
(PCHAR)MasterIrp->UserBuffer+Extent->Offset,
|
||||||
Extent->Length );
|
Extent->Length );
|
||||||
|
|
||||||
IoSetNextIrpStackLocation(Irp);
|
IoSetNextIrpStackLocation(Irp);
|
||||||
|
@ -568,8 +568,7 @@ Ext2ReadDisk(
|
||||||
FALSE );
|
FALSE );
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
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;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,14 +73,12 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VcbResourceAcquired =
|
|
||||||
ExAcquireResourceExclusiveLite(
|
|
||||||
&Vcb->MainResource,
|
|
||||||
TRUE
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Fcb->Identifier.Type == EXT2VCB) {
|
if (Fcb->Identifier.Type == EXT2VCB) {
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(
|
||||||
|
&Vcb->MainResource, TRUE);
|
||||||
|
VcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
||||||
Vcb->LockFile == FileObject ){
|
Vcb->LockFile == FileObject ){
|
||||||
|
|
||||||
|
@ -103,6 +101,12 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
|
|
||||||
|
FcbResourceAcquired =
|
||||||
|
ExAcquireResourceExclusiveLite(
|
||||||
|
&Fcb->MainResource,
|
||||||
|
TRUE
|
||||||
|
);
|
||||||
|
|
||||||
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
|
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
|
||||||
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
|
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
|
||||||
IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
|
IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
|
||||||
|
@ -135,18 +139,8 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
|
FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
|
||||||
VcbResourceAcquired = FALSE;
|
|
||||||
|
|
||||||
FcbResourceAcquired =
|
|
||||||
ExAcquireResourceExclusiveLite(
|
|
||||||
&Fcb->MainResource,
|
|
||||||
TRUE
|
|
||||||
);
|
|
||||||
|
|
||||||
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
|
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
|
||||||
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
|
(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 ||
|
if (SymLinkDelete ||
|
||||||
(IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) &&
|
(IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) &&
|
||||||
Fcb->OpenHandleCount == 0) ) {
|
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",
|
DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
|
||||||
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
|
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,10 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
PEXT2_FCB Fcb = NULL;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_CCB Ccb = NULL;
|
PEXT2_CCB Ccb = NULL;
|
||||||
|
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbResourceAcquired = FALSE;
|
BOOLEAN FcbResourceAcquired = FALSE;
|
||||||
BOOLEAN bDeleteVcb = FALSE;
|
BOOLEAN FcbDerefDeferred = FALSE;
|
||||||
BOOLEAN bBeingClosed = FALSE;
|
|
||||||
BOOLEAN bSkipLeave = FALSE;
|
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
@ -55,25 +54,6 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
||||||
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
(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)) {
|
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
|
||||||
|
|
||||||
FileObject = NULL;
|
FileObject = NULL;
|
||||||
|
@ -92,11 +72,30 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2Close: (VCB) bBeingClosed = %d Vcb = %p ReferCount = %d\n",
|
DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n",
|
||||||
bBeingClosed, Vcb, Vcb->ReferenceCount));
|
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 (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) {
|
if (Ccb) {
|
||||||
|
|
||||||
Ext2DerefXcb(&Vcb->ReferenceCount);
|
Ext2DerefXcb(&Vcb->ReferenceCount);
|
||||||
|
@ -126,68 +125,40 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
|
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
|
||||||
|
|
||||||
if (!Ccb) {
|
if (Ccb == NULL ||
|
||||||
|
Ccb->Identifier.Type != EXT2CCB ||
|
||||||
|
Ccb->Identifier.Size != sizeof(EXT2_CCB)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
_SEH2_LEAVE;
|
_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",
|
DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n",
|
||||||
Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));
|
Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));
|
||||||
|
|
||||||
if (Ccb) {
|
|
||||||
|
|
||||||
Ext2FreeCcb(Vcb, Ccb);
|
Ext2FreeCcb(Vcb, Ccb);
|
||||||
|
|
||||||
if (FileObject) {
|
if (FileObject) {
|
||||||
FileObject->FsContext2 = Ccb = NULL;
|
FileObject->FsContext2 = Ccb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* only deref fcb, Ext2ReleaseFcb might lead deadlock */
|
||||||
|
FcbDerefDeferred = TRUE;
|
||||||
|
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) ||
|
||||||
|
NULL == Fcb->Mcb ||
|
||||||
|
IsFileDeleted(Fcb->Mcb)) {
|
||||||
|
Fcb->TsDrop.QuadPart = 0;
|
||||||
|
} else {
|
||||||
|
KeQuerySystemTime(&Fcb->TsDrop);
|
||||||
}
|
}
|
||||||
|
Ext2DerefXcb(&Vcb->ReferenceCount);
|
||||||
if (0 == Ext2DerefXcb(&Fcb->ReferenceCount)) {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Remove Fcb from Vcb->FcbList ...
|
|
||||||
//
|
|
||||||
|
|
||||||
if (FcbResourceAcquired) {
|
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
|
||||||
FcbResourceAcquired = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ext2FreeFcb(Fcb);
|
|
||||||
|
|
||||||
if (FileObject) {
|
if (FileObject) {
|
||||||
FileObject->FsContext = Fcb = NULL;
|
FileObject->FsContext = NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ext2DerefXcb(&Vcb->ReferenceCount);
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _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) {
|
if (FcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
}
|
}
|
||||||
|
@ -205,17 +176,11 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
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;
|
} _SEH2_END;
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
|
|
@ -698,13 +698,14 @@ Ext2CreateFile(
|
||||||
ULONG CreateDisposition;
|
ULONG CreateDisposition;
|
||||||
|
|
||||||
BOOLEAN bParentFcbCreated = FALSE;
|
BOOLEAN bParentFcbCreated = FALSE;
|
||||||
|
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
BOOLEAN bDir = FALSE;
|
BOOLEAN bDir = FALSE;
|
||||||
#endif
|
#endif
|
||||||
BOOLEAN bFcbAllocated = FALSE;
|
BOOLEAN bFcbAllocated = FALSE;
|
||||||
BOOLEAN bCreated = FALSE;
|
BOOLEAN bCreated = FALSE;
|
||||||
|
|
||||||
BOOLEAN bMainResourceAcquired = FALSE;
|
BOOLEAN bMainResourceAcquired = FALSE;
|
||||||
|
BOOLEAN bFcbLockAcquired = FALSE;
|
||||||
|
|
||||||
BOOLEAN OpenDirectory;
|
BOOLEAN OpenDirectory;
|
||||||
BOOLEAN OpenTargetDirectory;
|
BOOLEAN OpenTargetDirectory;
|
||||||
|
@ -776,14 +777,14 @@ Ext2CreateFile(
|
||||||
|
|
||||||
if (ParentFcb) {
|
if (ParentFcb) {
|
||||||
ParentMcb = ParentFcb->Mcb;
|
ParentMcb = ParentFcb->Mcb;
|
||||||
SetLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
|
|
||||||
Ext2ReferMcb(ParentMcb);
|
Ext2ReferMcb(ParentMcb);
|
||||||
|
ParentFcb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileName.Length == 0) {
|
if (FileName.Length == 0) {
|
||||||
|
|
||||||
if (ParentFcb) {
|
if (ParentMcb) {
|
||||||
Mcb = ParentFcb->Mcb;
|
Mcb = ParentMcb;
|
||||||
Ext2ReferMcb(Mcb);
|
Ext2ReferMcb(Mcb);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
goto McbExisting;
|
goto McbExisting;
|
||||||
|
@ -811,7 +812,7 @@ Ext2CreateFile(
|
||||||
RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
|
RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
|
||||||
RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
|
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;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
@ -952,9 +953,9 @@ Dissecting:
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear BUSY bit from original ParentFcb */
|
if (!bFcbLockAcquired) {
|
||||||
if (ParentFcb) {
|
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
|
||||||
ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
|
bFcbLockAcquired = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the ParentFcb, allocate it if needed ... */
|
/* get the ParentFcb, allocate it if needed ... */
|
||||||
|
@ -966,9 +967,13 @@ Dissecting:
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
bParentFcbCreated = TRUE;
|
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 ?
|
// We need to create a new one ?
|
||||||
if ((CreateDisposition == FILE_CREATE ) ||
|
if ((CreateDisposition == FILE_CREATE ) ||
|
||||||
|
@ -1157,6 +1162,12 @@ Dissecting:
|
||||||
}
|
}
|
||||||
|
|
||||||
Openit:
|
Openit:
|
||||||
|
|
||||||
|
if (!bFcbLockAcquired) {
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
|
||||||
|
bFcbLockAcquired = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mcb should already be referred and symlink is too */
|
/* Mcb should already be referred and symlink is too */
|
||||||
if (Mcb) {
|
if (Mcb) {
|
||||||
|
|
||||||
|
@ -1221,10 +1232,15 @@ Openit:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Fcb) {
|
if (Fcb) {
|
||||||
|
|
||||||
/* grab Fcb's reference first to avoid the race between
|
/* grab Fcb's reference first to avoid the race between
|
||||||
Ext2Close (it could free the Fcb we are accessing) */
|
Ext2Close (it could free the Fcb we are accessing) */
|
||||||
Ext2ReferXcb(&Fcb->ReferenceCount);
|
Ext2ReferXcb(&Fcb->ReferenceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
bFcbLockAcquired = FALSE;
|
||||||
|
|
||||||
|
if (Fcb) {
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
|
||||||
bMainResourceAcquired = TRUE;
|
bMainResourceAcquired = TRUE;
|
||||||
|
@ -1565,6 +1581,9 @@ Openit:
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
if (bFcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
}
|
||||||
|
|
||||||
if (ParentMcb) {
|
if (ParentMcb) {
|
||||||
Ext2DerefMcb(ParentMcb);
|
Ext2DerefMcb(ParentMcb);
|
||||||
|
@ -1606,12 +1625,10 @@ Openit:
|
||||||
|
|
||||||
Ext2FreeCcb(Vcb, Ccb);
|
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;
|
LARGE_INTEGER Size;
|
||||||
ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
|
ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
@ -1625,10 +1642,7 @@ Openit:
|
||||||
if (bCreated) {
|
if (bCreated) {
|
||||||
Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
|
Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Ext2FreeFcb(Fcb);
|
|
||||||
Fcb = NULL;
|
|
||||||
bMainResourceAcquired = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bMainResourceAcquired) {
|
if (bMainResourceAcquired) {
|
||||||
|
@ -1641,14 +1655,12 @@ Openit:
|
||||||
Ext2FreePool(FileName.Buffer, EXT2_FNAME_MAGIC);
|
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) {
|
if (ParentFcb) {
|
||||||
ClearLongFlag(ParentFcb->Flags, FCB_STATE_BUSY);
|
Ext2ReleaseFcb(ParentFcb);
|
||||||
if (bParentFcbCreated) {
|
|
||||||
if (Ext2DerefXcb(&ParentFcb->ReferenceCount) == 0) {
|
|
||||||
Ext2FreeFcb(ParentFcb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drop SymLink's refer: If succeeds, Ext2AllocateCcb should refer
|
/* drop SymLink's refer: If succeeds, Ext2AllocateCcb should refer
|
||||||
|
|
|
@ -48,9 +48,6 @@ Ext2LoadSuper(IN PEXT2_VCB Vcb,
|
||||||
bVerify );
|
bVerify );
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
DEBUG(DL_ERR, ( "Ext2ReadDisk: disk device error.\n"));
|
|
||||||
|
|
||||||
Ext2FreePool(Ext2Sb, EXT2_SB_MAGIC);
|
Ext2FreePool(Ext2Sb, EXT2_SB_MAGIC);
|
||||||
Ext2Sb = NULL;
|
Ext2Sb = NULL;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +206,7 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2DropGroup(IN PEXT2_VCB Vcb)
|
Ext2DropBH(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext3_sb_info *sbi = &Vcb->sbi;
|
||||||
LARGE_INTEGER timeout;
|
LARGE_INTEGER timeout;
|
||||||
|
@ -220,17 +217,26 @@ Ext2DropGroup(IN PEXT2_VCB Vcb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
/* acquire bd lock to avoid bh creation */
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE);
|
||||||
|
|
||||||
SetFlag(Vcb->Flags, VCB_BEING_DROPPED);
|
SetFlag(Vcb->Flags, VCB_BEING_DROPPED);
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
|
|
||||||
Ext2PutGroup(Vcb);
|
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 {
|
} _SEH2_FINALLY {
|
||||||
ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
|
ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
|
||||||
} _SEH2_END;
|
} _SEH2_END;
|
||||||
|
|
||||||
timeout.QuadPart = (LONGLONG)-10*1000*1000;
|
|
||||||
KeWaitForSingleObject(&Vcb->bd.bd_bh_notify,
|
|
||||||
Executive, KernelMode,
|
|
||||||
FALSE, &timeout);
|
|
||||||
ClearFlag(Vcb->Flags, VCB_BEING_DROPPED);
|
ClearFlag(Vcb->Flags, VCB_BEING_DROPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1099,77 +1099,6 @@ out:
|
||||||
return err;
|
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:
|
* ext4_ext_create_new_leaf:
|
||||||
* finds empty index and adds new leaf.
|
* finds empty index and adds new leaf.
|
||||||
|
@ -1427,25 +1356,29 @@ found_extent:
|
||||||
* with leaves.
|
* with leaves.
|
||||||
*/
|
*/
|
||||||
ext4_lblk_t
|
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;
|
return EXT_MAX_BLOCKS;
|
||||||
|
|
||||||
while (at >= 0) {
|
while (depth >= 0) {
|
||||||
if (at == path->p_depth) {
|
if (depth == path->p_depth) {
|
||||||
/* leaf */
|
/* leaf */
|
||||||
if (path[at].p_ext &&
|
if (path[depth].p_ext &&
|
||||||
path[at].p_ext !=
|
path[depth].p_ext !=
|
||||||
EXT_LAST_EXTENT(path[at].p_hdr))
|
EXT_LAST_EXTENT(path[depth].p_hdr))
|
||||||
return le32_to_cpu(path[at].p_ext[1].ee_block);
|
return le32_to_cpu(path[depth].p_ext[1].ee_block);
|
||||||
} else {
|
} else {
|
||||||
/* index */
|
/* index */
|
||||||
if (path[at].p_idx !=
|
if (path[depth].p_idx !=
|
||||||
EXT_LAST_INDEX(path[at].p_hdr))
|
EXT_LAST_INDEX(path[depth].p_hdr))
|
||||||
return le32_to_cpu(path[at].p_idx[1].ei_block);
|
return le32_to_cpu(path[depth].p_idx[1].ei_block);
|
||||||
}
|
}
|
||||||
at--;
|
depth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXT_MAX_BLOCKS;
|
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:
|
* ext4_ext_correct_indexes:
|
||||||
* if leaf/node gets modified and modified extent/index
|
* if leaf gets modified and modified extent is first in the leaf,
|
||||||
* is first in the leaf/node,
|
|
||||||
* then we have to correct all indexes above.
|
* 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,
|
static int ext4_ext_correct_indexes(void *icb, handle_t *handle, struct inode *inode,
|
||||||
struct inode *inode,
|
struct ext4_ext_path *path)
|
||||||
struct ext4_ext_path *path,
|
|
||||||
int at)
|
|
||||||
{
|
{
|
||||||
struct ext4_extent_header *eh;
|
struct ext4_extent_header *eh;
|
||||||
int depth = ext_depth(inode);
|
int depth = ext_depth(inode);
|
||||||
|
@ -1497,18 +1428,16 @@ static int ext4_ext_correct_indexes(void *icb, handle_t *handle,
|
||||||
__le32 border;
|
__le32 border;
|
||||||
int k, err = 0;
|
int k, err = 0;
|
||||||
|
|
||||||
assert(at >= 0);
|
eh = path[depth].p_hdr;
|
||||||
if (!at)
|
ex = path[depth].p_ext;
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (depth == at) {
|
if (unlikely(ex == NULL || eh == NULL)) {
|
||||||
eh = path[at].p_hdr;
|
EXT4_ERROR_INODE(inode,
|
||||||
ex = path[at].p_ext;
|
"ex %p == NULL or eh %p == NULL", ex, eh);
|
||||||
|
|
||||||
if (ex == NULL || eh == NULL)
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (at == 0) {
|
if (depth == 0) {
|
||||||
/* there is no tree at all */
|
/* there is no tree at all */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1518,28 +1447,30 @@ static int ext4_ext_correct_indexes(void *icb, handle_t *handle,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
k = at - 1;
|
/*
|
||||||
border = path[at].p_ext->ee_block;
|
* 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;
|
path[k].p_idx->ei_block = border;
|
||||||
err = ext4_ext_dirty(icb, handle, inode, path + k);
|
err = ext4_ext_dirty(icb, handle, inode, path + k);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
} else {
|
while (k--) {
|
||||||
border = path[at].p_idx->ei_block;
|
|
||||||
k = at;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (k) {
|
|
||||||
/* change all left-side indexes */
|
/* change all left-side indexes */
|
||||||
if (path[k].p_idx != EXT_FIRST_INDEX(path[k].p_hdr))
|
if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
|
||||||
break;
|
break;
|
||||||
path[k-1].p_idx->ei_block = border;
|
err = ext4_ext_get_access(icb, handle, inode, path + k);
|
||||||
err = ext4_ext_dirty(icb, handle, inode, path + k-1);
|
if (err)
|
||||||
|
break;
|
||||||
|
path[k].p_idx->ei_block = border;
|
||||||
|
err = ext4_ext_dirty(icb, handle, inode, path + k);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
k--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -1914,11 +1845,9 @@ merge:
|
||||||
if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
|
if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
|
||||||
ext4_ext_try_to_merge(icb, handle, inode, path, nearex);
|
ext4_ext_try_to_merge(icb, handle, inode, path, nearex);
|
||||||
|
|
||||||
depth = ext_depth(inode);
|
|
||||||
|
|
||||||
/* time to correct all indexes above */
|
/* time to correct all indexes above */
|
||||||
err = ext4_ext_correct_indexes(icb, handle,
|
err = ext4_ext_correct_indexes(icb, handle, inode, path);
|
||||||
inode, path, depth);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -1952,351 +1881,156 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ext4_ext_remove_blocks(
|
static int ext4_remove_blocks(void *icb, handle_t *handle, struct inode *inode,
|
||||||
void *icb,
|
struct ext4_extent *ex,
|
||||||
handle_t *handle,
|
unsigned long from, unsigned long to)
|
||||||
struct inode *inode, struct ext4_extent *ex,
|
|
||||||
ext4_lblk_t from, ext4_lblk_t to)
|
|
||||||
{
|
{
|
||||||
int len = to - from + 1;
|
struct buffer_head *bh;
|
||||||
ext4_lblk_t num;
|
int i;
|
||||||
ext4_fsblk_t start;
|
|
||||||
num = from - le32_to_cpu(ex->ee_block);
|
|
||||||
start = ext4_ext_pblock(ex) + num;
|
|
||||||
ext_debug("Freeing %lu at %I64u, %d\n", from, start, len);
|
|
||||||
ext4_free_blocks(icb, handle, inode, NULL,
|
|
||||||
start, len, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ext4_ext_remove_idx(void *icb,
|
if (from >= le32_to_cpu(ex->ee_block)
|
||||||
handle_t *handle,
|
&& to == le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1) {
|
||||||
struct inode *inode,
|
/* tail removal */
|
||||||
struct ext4_ext_path *path,
|
unsigned long num, start;
|
||||||
int depth)
|
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;
|
||||||
int err, i = depth;
|
ext4_free_blocks(icb, handle, inode, NULL, start, num, 0);
|
||||||
ext4_fsblk_t leaf;
|
} else if (from == le32_to_cpu(ex->ee_block)
|
||||||
|
&& to <= le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1) {
|
||||||
/* 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));
|
|
||||||
} else {
|
} 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);
|
return 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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,
|
int ext4_ext_rm_idx(void *icb, handle_t *handle, struct inode *inode,
|
||||||
handle_t *handle,
|
struct ext4_ext_path *path)
|
||||||
struct inode *inode, struct ext4_ext_path **path)
|
|
||||||
{
|
{
|
||||||
int len;
|
int err;
|
||||||
int err = 0;
|
ext4_fsblk_t leaf;
|
||||||
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);
|
|
||||||
|
|
||||||
|
/* 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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __ext4_ext_truncate(void *icb,
|
static int
|
||||||
handle_t *handle,
|
ext4_ext_rm_leaf(void *icb, handle_t *handle, struct inode *inode,
|
||||||
struct inode *inode,
|
struct ext4_ext_path *path, unsigned long start)
|
||||||
ext4_lblk_t from, ext4_lblk_t to)
|
|
||||||
{
|
{
|
||||||
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_extent *ex;
|
||||||
struct ext4_ext_path *path = NULL, *npath;
|
|
||||||
ext4_lblk_t now = from;
|
|
||||||
|
|
||||||
if (to < from)
|
/* the header must be checked already in ext4_ext_remove_space() */
|
||||||
return -EINVAL;
|
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);
|
/* find where to start removing */
|
||||||
if (IS_ERR(npath))
|
ex = EXT_LAST_EXTENT(eh);
|
||||||
goto out;
|
|
||||||
|
|
||||||
path = npath;
|
ex_ee_block = le32_to_cpu(ex->ee_block);
|
||||||
ex = path[depth].p_ext;
|
ex_ee_len = ext4_ext_get_actual_len(ex);
|
||||||
if (!ex)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (from < le32_to_cpu(ex->ee_block) &&
|
while (ex >= EXT_FIRST_EXTENT(eh) &&
|
||||||
to < le32_to_cpu(ex->ee_block)) {
|
ex_ee_block + ex_ee_len > start) {
|
||||||
ret = 0;
|
path[depth].p_ext = ex;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
/* If we do remove_space inside the range of an extent */
|
|
||||||
if ((le32_to_cpu(ex->ee_block) < from) &&
|
|
||||||
(to < le32_to_cpu(ex->ee_block) +
|
|
||||||
ext4_ext_get_actual_len(ex) - 1)) {
|
|
||||||
|
|
||||||
struct ext4_extent newex;
|
a = ex_ee_block > start ? ex_ee_block : start;
|
||||||
int unwritten = ext4_ext_is_unwritten(ex);
|
b = (unsigned long long)ex_ee_block + ex_ee_len - 1 <
|
||||||
ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
|
EXT_MAX_BLOCKS ? ex_ee_block + ex_ee_len - 1 : EXT_MAX_BLOCKS;
|
||||||
int len = ext4_ext_get_actual_len(ex);
|
|
||||||
ext4_fsblk_t newblock =
|
|
||||||
to + 1 - ee_block + ext4_ext_pblock(ex);
|
|
||||||
|
|
||||||
ex->ee_len = cpu_to_le16(from - ee_block);
|
|
||||||
if (unwritten)
|
|
||||||
ext4_ext_mark_unwritten(ex);
|
|
||||||
|
|
||||||
ext4_ext_dirty(icb, handle, inode, path + depth);
|
if (a != ex_ee_block && b != ex_ee_block + ex_ee_len - 1) {
|
||||||
|
block = 0;
|
||||||
ext4_ext_remove_blocks(icb, handle,
|
num = 0;
|
||||||
inode,
|
BUG();
|
||||||
ex, from, to);
|
} else if (a != ex_ee_block) {
|
||||||
|
/* remove tail of the extent */
|
||||||
newex.ee_block = cpu_to_le32(to + 1);
|
block = ex_ee_block;
|
||||||
newex.ee_len = cpu_to_le16(ee_block + len - 1 - to);
|
num = a - block;
|
||||||
ext4_ext_store_pblock(&newex, newblock);
|
} else if (b != ex_ee_block + ex_ee_len - 1) {
|
||||||
if (unwritten)
|
/* remove head of the extent */
|
||||||
ext4_ext_mark_unwritten(&newex);
|
block = a;
|
||||||
|
num = b - a;
|
||||||
ret = ext4_ext_insert_extent(icb, handle,
|
/* there is no "make a hole" API yet */
|
||||||
inode, &path, &newex, 0);
|
BUG();
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1 < from) {
|
|
||||||
now = ext4_ext_next_allocated_block(path, depth);
|
|
||||||
npath = ext4_find_extent(inode, now, &path, 0);
|
|
||||||
if (IS_ERR(npath))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
path = npath;
|
|
||||||
ex = path[depth].p_ext;
|
|
||||||
}
|
|
||||||
while (ex &&
|
|
||||||
le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1 >= now &&
|
|
||||||
le32_to_cpu(ex->ee_block) <= to) {
|
|
||||||
int len, new_len = 0;
|
|
||||||
int unwritten;
|
|
||||||
ext4_lblk_t start, new_start;
|
|
||||||
ext4_fsblk_t newblock;
|
|
||||||
|
|
||||||
new_start = start = le32_to_cpu(ex->ee_block);
|
|
||||||
len = ext4_ext_get_actual_len(ex);
|
|
||||||
newblock = ext4_ext_pblock(ex);
|
|
||||||
if (start < from) {
|
|
||||||
len -= from - start;
|
|
||||||
new_len = from - start;
|
|
||||||
start = from;
|
|
||||||
} else {
|
} else {
|
||||||
if (start + len - 1 > to) {
|
/* remove whole extent: excellent! */
|
||||||
new_len = start + len - 1 - to;
|
block = ex_ee_block;
|
||||||
len -= new_len;
|
num = 0;
|
||||||
new_start = to + 1;
|
BUG_ON(a != ex_ee_block);
|
||||||
newblock += to + 1 - start;
|
BUG_ON(b != ex_ee_block + ex_ee_len - 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
now = ext4_ext_next_allocated_block(path, depth);
|
/* at present, extent can't cross block group */
|
||||||
if (!new_len) {
|
/* leaf + bitmap + group desc + sb + inode */
|
||||||
ret = ext4_ext_remove_extent(icb, handle,
|
credits = 5;
|
||||||
inode, &path);
|
if (ex == EXT_FIRST_EXTENT(eh)) {
|
||||||
if (ret)
|
correct_index = 1;
|
||||||
|
credits += (ext_depth(inode)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*handle = ext4_ext_journal_restart(icb, handle, credits);*/
|
||||||
|
/*if (IS_ERR(icb, handle)) {*/
|
||||||
|
/*err = PTR_ERR(icb, handle);*/
|
||||||
|
/*goto out;*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
err = ext4_ext_get_access(icb, handle, inode, path + depth);
|
||||||
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
} else {
|
err = ext4_remove_blocks(icb, handle, inode, ex, a, b);
|
||||||
ext4_ext_remove_blocks(icb, handle,
|
if (err)
|
||||||
inode,
|
|
||||||
ex, start, start + len - 1);
|
|
||||||
ex->ee_block = cpu_to_le32(new_start);
|
|
||||||
unwritten = ext4_ext_is_unwritten(ex);
|
|
||||||
ex->ee_len = cpu_to_le16(new_len);
|
|
||||||
ext4_ext_store_pblock(ex, newblock);
|
|
||||||
if (unwritten)
|
|
||||||
ext4_ext_mark_unwritten(ex);
|
|
||||||
|
|
||||||
ext4_ext_dirty(icb, handle,
|
|
||||||
inode, path + depth);
|
|
||||||
}
|
|
||||||
npath = ext4_find_extent(inode, now, &path, 0);
|
|
||||||
if (IS_ERR(npath))
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
path = npath;
|
if (num == 0) {
|
||||||
depth = ext_depth(inode);
|
/* this extent is removed entirely mark slot unused */
|
||||||
ex = path[depth].p_ext;
|
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:
|
out:
|
||||||
if (path) {
|
return err;
|
||||||
ext4_ext_drop_refs(path);
|
|
||||||
kfree(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_ERR(npath))
|
|
||||||
ret = PTR_ERR(npath);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2438,6 +2172,140 @@ fix_extent_len:
|
||||||
return err;
|
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)
|
int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode)
|
||||||
{
|
{
|
||||||
struct ext4_extent_header *eh;
|
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
|
/* find next allocated block so that we know how many
|
||||||
* blocks we can allocate without ovelapping next extent */
|
* 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);
|
BUG_ON(next <= iblock);
|
||||||
allocated = next - iblock;
|
allocated = next - iblock;
|
||||||
if (flags & EXT4_GET_BLOCKS_PRE_IO && max_blocks > EXT_UNWRITTEN_MAX_LEN)
|
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 ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start)
|
||||||
{
|
{
|
||||||
int ret = __ext4_ext_truncate(icb, NULL, inode,
|
int ret = ext4_ext_remove_space(icb, inode, start);
|
||||||
start, EXT_MAX_BLOCKS);
|
|
||||||
|
|
||||||
/* Save modifications on i_blocks field of the inode. */
|
/* Save modifications on i_blocks field of the inode. */
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
|
@ -504,7 +504,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
|
|
||||||
BOOLEAN VcbMainResourceAcquired = FALSE;
|
|
||||||
BOOLEAN FcbMainResourceAcquired = FALSE;
|
BOOLEAN FcbMainResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
|
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
|
||||||
|
|
||||||
|
@ -542,18 +541,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
_SEH2_LEAVE;
|
_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)) {
|
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
|
||||||
Status = STATUS_ACCESS_DENIED;
|
Status = STATUS_ACCESS_DENIED;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
@ -1047,10 +1034,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VcbMainResourceAcquired) {
|
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
if (Status == STATUS_PENDING ||
|
if (Status == STATUS_PENDING ||
|
||||||
Status == STATUS_CANT_WAIT ) {
|
Status == STATUS_CANT_WAIT ) {
|
||||||
|
@ -1347,8 +1330,7 @@ Ext2SetRenameInfo(
|
||||||
BOOLEAN bMove = FALSE;
|
BOOLEAN bMove = FALSE;
|
||||||
BOOLEAN bTargetRemoved = FALSE;
|
BOOLEAN bTargetRemoved = FALSE;
|
||||||
|
|
||||||
BOOLEAN bNewTargetDcb = FALSE;
|
BOOLEAN bFcbLockAcquired = FALSE;
|
||||||
BOOLEAN bNewParentDcb = FALSE;
|
|
||||||
|
|
||||||
PFILE_RENAME_INFORMATION FRI;
|
PFILE_RENAME_INFORMATION FRI;
|
||||||
|
|
||||||
|
@ -1435,16 +1417,17 @@ Ext2SetRenameInfo(
|
||||||
bMove = TRUE;
|
bMove = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bFcbLockAcquired) {
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
|
||||||
|
bFcbLockAcquired = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
TargetDcb = TargetMcb->Fcb;
|
TargetDcb = TargetMcb->Fcb;
|
||||||
if (TargetDcb == NULL) {
|
if (TargetDcb == NULL) {
|
||||||
TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb);
|
TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb);
|
||||||
|
}
|
||||||
if (TargetDcb) {
|
if (TargetDcb) {
|
||||||
Ext2ReferXcb(&TargetDcb->ReferenceCount);
|
Ext2ReferXcb(&TargetDcb->ReferenceCount);
|
||||||
bNewTargetDcb = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (TargetDcb) {
|
|
||||||
SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParentMcb = Mcb->Parent;
|
ParentMcb = Mcb->Parent;
|
||||||
|
@ -1454,14 +1437,15 @@ Ext2SetRenameInfo(
|
||||||
|
|
||||||
if (ParentDcb == NULL) {
|
if (ParentDcb == NULL) {
|
||||||
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
|
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ParentDcb) {
|
if (ParentDcb) {
|
||||||
Ext2ReferXcb(&ParentDcb->ReferenceCount);
|
Ext2ReferXcb(&ParentDcb->ReferenceCount);
|
||||||
bNewParentDcb = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ParentDcb) {
|
|
||||||
SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bFcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
bFcbLockAcquired = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TargetDcb || !ParentDcb) {
|
if (!TargetDcb || !ParentDcb) {
|
||||||
|
@ -1625,40 +1609,25 @@ Ext2SetRenameInfo(
|
||||||
FILE_NOTIFY_CHANGE_DIR_NAME :
|
FILE_NOTIFY_CHANGE_DIR_NAME :
|
||||||
FILE_NOTIFY_CHANGE_FILE_NAME ),
|
FILE_NOTIFY_CHANGE_FILE_NAME ),
|
||||||
FILE_ACTION_RENAMED_NEW_NAME );
|
FILE_ACTION_RENAMED_NEW_NAME );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
|
|
||||||
|
if (bFcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
bFcbLockAcquired = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (NewEntry)
|
if (NewEntry)
|
||||||
Ext2FreeEntry(NewEntry);
|
Ext2FreeEntry(NewEntry);
|
||||||
|
|
||||||
if (TargetDcb) {
|
if (TargetDcb) {
|
||||||
if (ParentDcb && ParentDcb->Inode->i_ino != TargetDcb->Inode->i_ino) {
|
Ext2ReleaseFcb(TargetDcb);
|
||||||
ClearLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
|
|
||||||
}
|
|
||||||
ClearLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bNewTargetDcb) {
|
if (ParentDcb) {
|
||||||
ASSERT(TargetDcb != NULL);
|
Ext2ReleaseFcb(ParentDcb);
|
||||||
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 (ExistingMcb)
|
if (ExistingMcb)
|
||||||
|
@ -1698,8 +1667,8 @@ Ext2SetLinkInfo(
|
||||||
|
|
||||||
BOOLEAN ReplaceIfExists;
|
BOOLEAN ReplaceIfExists;
|
||||||
BOOLEAN bTargetRemoved = FALSE;
|
BOOLEAN bTargetRemoved = FALSE;
|
||||||
BOOLEAN bNewTargetDcb = FALSE;
|
|
||||||
BOOLEAN bNewParentDcb = FALSE;
|
BOOLEAN bFcbLockAcquired = FALSE;
|
||||||
|
|
||||||
PFILE_LINK_INFORMATION FLI;
|
PFILE_LINK_INFORMATION FLI;
|
||||||
|
|
||||||
|
@ -1781,17 +1750,15 @@ Ext2SetLinkInfo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
|
||||||
|
bFcbLockAcquired = TRUE;
|
||||||
|
|
||||||
TargetDcb = TargetMcb->Fcb;
|
TargetDcb = TargetMcb->Fcb;
|
||||||
if (TargetDcb == NULL) {
|
if (TargetDcb == NULL) {
|
||||||
TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb);
|
TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb);
|
||||||
|
}
|
||||||
if (TargetDcb) {
|
if (TargetDcb) {
|
||||||
Ext2ReferXcb(&TargetDcb->ReferenceCount);
|
Ext2ReferXcb(&TargetDcb->ReferenceCount);
|
||||||
bNewTargetDcb = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TargetDcb) {
|
|
||||||
SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParentMcb = Mcb->Parent;
|
ParentMcb = Mcb->Parent;
|
||||||
|
@ -1801,14 +1768,15 @@ Ext2SetLinkInfo(
|
||||||
|
|
||||||
if (ParentDcb == NULL) {
|
if (ParentDcb == NULL) {
|
||||||
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
|
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ParentDcb) {
|
if (ParentDcb) {
|
||||||
Ext2ReferXcb(&ParentDcb->ReferenceCount);
|
Ext2ReferXcb(&ParentDcb->ReferenceCount);
|
||||||
bNewParentDcb = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ParentDcb) {
|
|
||||||
SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bFcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
bFcbLockAcquired = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TargetDcb || !ParentDcb) {
|
if (!TargetDcb || !ParentDcb) {
|
||||||
|
@ -1887,31 +1855,17 @@ Ext2SetLinkInfo(
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
|
|
||||||
|
if (bFcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
bFcbLockAcquired = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (TargetDcb) {
|
if (TargetDcb) {
|
||||||
if (ParentDcb && ParentDcb->Inode->i_ino != TargetDcb->Inode->i_ino) {
|
Ext2ReleaseFcb(TargetDcb);
|
||||||
ClearLongFlag(ParentDcb->Flags, FCB_STATE_BUSY);
|
|
||||||
}
|
|
||||||
ClearLongFlag(TargetDcb->Flags, FCB_STATE_BUSY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bNewTargetDcb) {
|
if (ParentDcb) {
|
||||||
ASSERT(TargetDcb != NULL);
|
Ext2ReleaseFcb(ParentDcb);
|
||||||
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 (ExistingMcb)
|
if (ExistingMcb)
|
||||||
|
@ -1957,7 +1911,7 @@ Ext2DeleteFile(
|
||||||
LARGE_INTEGER Size;
|
LARGE_INTEGER Size;
|
||||||
LARGE_INTEGER SysTime;
|
LARGE_INTEGER SysTime;
|
||||||
|
|
||||||
BOOLEAN bNewDcb = FALSE;
|
BOOLEAN bFcbLockAcquired = FALSE;
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2DeleteFile: File %wZ (%xh) will be deleted!\n",
|
DEBUG(DL_INF, ( "Ext2DeleteFile: File %wZ (%xh) will be deleted!\n",
|
||||||
&Mcb->FullName, Mcb->Inode.i_ino));
|
&Mcb->FullName, Mcb->Inode.i_ino));
|
||||||
|
@ -1979,16 +1933,22 @@ Ext2DeleteFile(
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
|
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
|
||||||
VcbResourceAcquired = TRUE;
|
VcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
|
||||||
|
bFcbLockAcquired = TRUE;
|
||||||
|
|
||||||
if (!(Dcb = Mcb->Parent->Fcb)) {
|
if (!(Dcb = Mcb->Parent->Fcb)) {
|
||||||
Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent);
|
Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent);
|
||||||
|
}
|
||||||
if (Dcb) {
|
if (Dcb) {
|
||||||
Ext2ReferXcb(&Dcb->ReferenceCount);
|
Ext2ReferXcb(&Dcb->ReferenceCount);
|
||||||
bNewDcb = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bFcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
bFcbLockAcquired = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Dcb) {
|
if (Dcb) {
|
||||||
SetLongFlag(Dcb->Flags, FCB_STATE_BUSY);
|
|
||||||
DcbResourceAcquired =
|
DcbResourceAcquired =
|
||||||
ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
|
ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
|
||||||
|
|
||||||
|
@ -2090,21 +2050,18 @@ Ext2DeleteFile(
|
||||||
ExReleaseResourceLite(&Dcb->MainResource);
|
ExReleaseResourceLite(&Dcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Dcb) {
|
if (bFcbLockAcquired) {
|
||||||
ClearLongFlag(Dcb->Flags, FCB_STATE_BUSY);
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
if (bNewDcb) {
|
|
||||||
if (Ext2DerefXcb(&Dcb->ReferenceCount) == 0) {
|
|
||||||
Ext2FreeFcb(Dcb);
|
|
||||||
} else {
|
|
||||||
DEBUG(DL_ERR, ( "Ext2DeleteFile: Dcb %wZ used by other threads.\n",
|
|
||||||
&Mcb->FullName ));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VcbResourceAcquired) {
|
if (VcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Dcb) {
|
||||||
|
Ext2ReleaseFcb(Dcb);
|
||||||
|
}
|
||||||
|
|
||||||
Ext2DerefMcb(Mcb);
|
Ext2DerefMcb(Mcb);
|
||||||
} _SEH2_END;
|
} _SEH2_END;
|
||||||
|
|
||||||
|
|
|
@ -81,14 +81,21 @@ Ext2FlushVolume (
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
|
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
|
||||||
|
|
||||||
/* discard buffer_headers for group_desc */
|
|
||||||
Ext2DropGroup(Vcb);
|
|
||||||
|
|
||||||
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
||||||
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
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);
|
CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
|
||||||
|
|
||||||
|
/* release gd lock */
|
||||||
|
ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
|
||||||
|
|
||||||
return IoStatus.Status;
|
return IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1582,8 +1582,6 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
PEXT2_MCB Mcb = NULL;
|
PEXT2_MCB Mcb = NULL;
|
||||||
|
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
BOOLEAN bNewParentDcb = FALSE;
|
|
||||||
BOOLEAN MainResourceAcquired = FALSE;
|
|
||||||
|
|
||||||
PVOID InputBuffer;
|
PVOID InputBuffer;
|
||||||
ULONG InputBufferLength;
|
ULONG InputBufferLength;
|
||||||
|
@ -1600,6 +1598,8 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
PCHAR OemNameBuffer = NULL;
|
PCHAR OemNameBuffer = NULL;
|
||||||
int OemNameLength = 0, i;
|
int OemNameLength = 0, i;
|
||||||
|
|
||||||
|
BOOLEAN MainResourceAcquired = FALSE;
|
||||||
|
BOOLEAN FcbLockAcquired = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
@ -1614,19 +1614,26 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
|
||||||
|
FcbLockAcquired = TRUE;
|
||||||
|
|
||||||
ParentMcb = Mcb->Parent;
|
ParentMcb = Mcb->Parent;
|
||||||
ParentDcb = ParentMcb->Fcb;
|
ParentDcb = ParentMcb->Fcb;
|
||||||
if (ParentDcb == NULL) {
|
if (ParentDcb == NULL) {
|
||||||
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
|
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
|
||||||
|
}
|
||||||
if (ParentDcb) {
|
if (ParentDcb) {
|
||||||
Ext2ReferXcb(&ParentDcb->ReferenceCount);
|
Ext2ReferXcb(&ParentDcb->ReferenceCount);
|
||||||
bNewParentDcb = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Mcb)
|
if (!Mcb)
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
|
||||||
|
if (FcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
FcbLockAcquired = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ExAcquireResourceSharedLite(
|
if (!ExAcquireResourceSharedLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
|
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
|
||||||
|
@ -1702,6 +1709,11 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
if (FcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
FcbLockAcquired = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (MainResourceAcquired) {
|
if (MainResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
}
|
}
|
||||||
|
@ -1719,16 +1731,6 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
FILE_ACTION_MODIFIED );
|
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 (!_SEH2_AbnormalTermination()) {
|
||||||
if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) {
|
if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) {
|
||||||
Status = Ext2QueueRequest(IrpContext);
|
Status = Ext2QueueRequest(IrpContext);
|
||||||
|
@ -1736,6 +1738,10 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ParentDcb) {
|
||||||
|
Ext2ReleaseFcb(ParentDcb);
|
||||||
|
}
|
||||||
} _SEH2_END;
|
} _SEH2_END;
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -1786,14 +1792,15 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
PEXT2_CCB Ccb = NULL;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PEXT2_MCB Mcb = 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_FCB ParentDcb = NULL; /* Dcb of it's current parent */
|
||||||
PEXT2_MCB ParentMcb = NULL;
|
PEXT2_MCB ParentMcb = NULL;
|
||||||
|
|
||||||
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
BOOLEAN FcbLockAcquired = FALSE;
|
||||||
|
BOOLEAN MainResourceAcquired = FALSE;
|
||||||
|
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
Ccb = IrpContext->Ccb;
|
Ccb = IrpContext->Ccb;
|
||||||
|
@ -1805,14 +1812,16 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
Mcb = IrpContext->Fcb->Mcb;
|
Mcb = IrpContext->Fcb->Mcb;
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
|
||||||
|
FcbLockAcquired = TRUE;
|
||||||
|
|
||||||
ParentMcb = Mcb->Parent;
|
ParentMcb = Mcb->Parent;
|
||||||
ParentDcb = ParentMcb->Fcb;
|
ParentDcb = ParentMcb->Fcb;
|
||||||
if (ParentDcb == NULL) {
|
if (ParentDcb == NULL) {
|
||||||
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
|
ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb);
|
||||||
|
}
|
||||||
if (ParentDcb) {
|
if (ParentDcb) {
|
||||||
Ext2ReferXcb(&ParentDcb->ReferenceCount);
|
Ext2ReferXcb(&ParentDcb->ReferenceCount);
|
||||||
bNewParentDcb = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Mcb || !IsInodeSymLink(&Mcb->Inode) ||
|
if (!Mcb || !IsInodeSymLink(&Mcb->Inode) ||
|
||||||
|
@ -1823,12 +1832,16 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
Fcb = Ext2AllocateFcb (Vcb, Mcb);
|
Fcb = Ext2AllocateFcb (Vcb, Mcb);
|
||||||
if (Fcb) {
|
if (Fcb) {
|
||||||
bFcbAllocated = TRUE;
|
Ext2ReferXcb(&Fcb->ReferenceCount);
|
||||||
} else {
|
} else {
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
Ext2ReferXcb(&Fcb->ReferenceCount);
|
|
||||||
|
if (FcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
FcbLockAcquired = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ExAcquireResourceSharedLite(
|
if (!ExAcquireResourceSharedLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
|
@ -1848,6 +1861,10 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
if (FcbLockAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
}
|
||||||
|
|
||||||
if (MainResourceAcquired) {
|
if (MainResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
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 (!_SEH2_AbnormalTermination()) {
|
||||||
if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) {
|
if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) {
|
||||||
Status = Ext2QueueRequest(IrpContext);
|
Status = Ext2QueueRequest(IrpContext);
|
||||||
|
@ -1880,10 +1887,12 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bFcbAllocated) {
|
if (ParentDcb) {
|
||||||
if (Ext2DerefXcb(&Fcb->ReferenceCount) == 0) {
|
Ext2ReleaseFcb(ParentDcb);
|
||||||
Ext2FreeFcb(Fcb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Fcb) {
|
||||||
|
Ext2ReleaseFcb(Fcb);
|
||||||
}
|
}
|
||||||
} _SEH2_END;
|
} _SEH2_END;
|
||||||
|
|
||||||
|
@ -2450,13 +2459,7 @@ Ext2VerifyVolume (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Status = STATUS_WRONG_VOLUME;
|
Status = STATUS_WRONG_VOLUME;
|
||||||
if (VcbResourceAcquired) {
|
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
|
||||||
VcbResourceAcquired = FALSE;
|
|
||||||
}
|
|
||||||
Ext2PurgeVolume(Vcb, FALSE);
|
Ext2PurgeVolume(Vcb, FALSE);
|
||||||
VcbResourceAcquired =
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
|
|
||||||
|
|
||||||
SetLongFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);
|
SetLongFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);
|
||||||
ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);
|
ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);
|
||||||
|
@ -2607,8 +2610,9 @@ Ext2CheckDismount (
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource, TRUE );
|
&Vcb->MainResource, TRUE );
|
||||||
|
|
||||||
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
if (IrpContext &&
|
||||||
(IrpContext->RealDevice == Vcb->RealDevice)) {
|
IrpContext->MajorFunction == IRP_MJ_CREATE &&
|
||||||
|
IrpContext->RealDevice == Vcb->RealDevice) {
|
||||||
UnCleanCount = 2;
|
UnCleanCount = 2;
|
||||||
} else {
|
} else {
|
||||||
UnCleanCount = 1;
|
UnCleanCount = 1;
|
||||||
|
@ -2696,59 +2700,44 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
|
||||||
IN BOOLEAN FlushBeforePurge )
|
IN BOOLEAN FlushBeforePurge )
|
||||||
{
|
{
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb;
|
||||||
LIST_ENTRY FcbList;
|
LIST_ENTRY List, *Next;
|
||||||
PLIST_ENTRY ListEntry;
|
|
||||||
PFCB_LIST_ENTRY FcbListEntry;
|
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
BOOLEAN FcbResourceAcquired = FALSE;
|
||||||
|
BOOLEAN gdResourceAcquired = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
ASSERT(Vcb != NULL);
|
ASSERT(Vcb != NULL);
|
||||||
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
||||||
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
||||||
|
|
||||||
VcbResourceAcquired =
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
|
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
|
||||||
|
VcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
if (IsVcbReadOnly(Vcb)) {
|
if (IsVcbReadOnly(Vcb)) {
|
||||||
FlushBeforePurge = FALSE;
|
FlushBeforePurge = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* discard buffer_headers for group_desc */
|
InitializeListHead(&List);
|
||||||
Ext2DropGroup(Vcb);
|
|
||||||
|
|
||||||
FcbListEntry= NULL;
|
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
|
||||||
InitializeListHead(&FcbList);
|
FcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
for (ListEntry = Vcb->FcbList.Flink;
|
while (!IsListEmpty(&Vcb->FcbList)) {
|
||||||
ListEntry != &Vcb->FcbList;
|
|
||||||
ListEntry = ListEntry->Flink ) {
|
|
||||||
|
|
||||||
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));
|
DEBUG(DL_INF, ( "Ext2PurgeVolume: %wZ refercount=%xh\n",
|
||||||
|
&Fcb->Mcb->FullName, Fcb->ReferenceCount));
|
||||||
FcbListEntry = Ext2AllocatePool(
|
InsertTailList(&List, &Fcb->Next);
|
||||||
PagedPool,
|
|
||||||
sizeof(FCB_LIST_ENTRY),
|
|
||||||
EXT2_FLIST_MAGIC
|
|
||||||
);
|
|
||||||
|
|
||||||
if (FcbListEntry) {
|
|
||||||
FcbListEntry->Fcb = Fcb;
|
|
||||||
Ext2ReferXcb(&Fcb->ReferenceCount);
|
|
||||||
InsertTailList(&FcbList, &FcbListEntry->Next);
|
|
||||||
} else {
|
|
||||||
DEBUG(DL_ERR, ( "Ext2PurgeVolume: failed to allocate FcbListEntry ...\n"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!IsListEmpty(&FcbList)) {
|
while (!IsListEmpty(&List)) {
|
||||||
|
|
||||||
ListEntry = RemoveHeadList(&FcbList);
|
Next = RemoveHeadList(&List);
|
||||||
|
Fcb = CONTAINING_RECORD(Next, EXT2_FCB, Next);
|
||||||
FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next);
|
|
||||||
|
|
||||||
Fcb = FcbListEntry->Fcb;
|
|
||||||
|
|
||||||
if (ExAcquireResourceExclusiveLite(
|
if (ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
|
@ -2756,16 +2745,28 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
|
||||||
|
|
||||||
Ext2PurgeFile(Fcb, FlushBeforePurge);
|
Ext2PurgeFile(Fcb, FlushBeforePurge);
|
||||||
|
|
||||||
if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1) {
|
if (Fcb->ReferenceCount <= 1) {
|
||||||
Ext2FreeFcb(Fcb);
|
Fcb->TsDrop.QuadPart = 0;
|
||||||
|
InsertHeadList(&Vcb->FcbList, &Fcb->Next);
|
||||||
} else {
|
} else {
|
||||||
|
InsertTailList(&Vcb->FcbList, &Fcb->Next);
|
||||||
|
}
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
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) {
|
if (FlushBeforePurge) {
|
||||||
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
||||||
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
||||||
|
@ -2777,11 +2778,6 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
|
||||||
MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite);
|
MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VcbResourceAcquired) {
|
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
|
||||||
VcbResourceAcquired = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Vcb->SectionObject.DataSectionObject) {
|
if (Vcb->SectionObject.DataSectionObject) {
|
||||||
CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE);
|
CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE);
|
||||||
}
|
}
|
||||||
|
@ -2790,6 +2786,14 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
if (gdResourceAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FcbResourceAcquired) {
|
||||||
|
ExReleaseResourceLite(&Vcb->FcbLock);
|
||||||
|
}
|
||||||
|
|
||||||
if (VcbResourceAcquired) {
|
if (VcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
}
|
}
|
||||||
|
@ -2811,30 +2815,23 @@ Ext2PurgeFile ( IN PEXT2_FCB Fcb,
|
||||||
|
|
||||||
|
|
||||||
if (!IsVcbReadOnly(Fcb->Vcb) && FlushBeforePurge) {
|
if (!IsVcbReadOnly(Fcb->Vcb) && FlushBeforePurge) {
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2PurgeFile: CcFlushCache on %wZ.\n",
|
DEBUG(DL_INF, ( "Ext2PurgeFile: CcFlushCache on %wZ.\n",
|
||||||
&Fcb->Mcb->FullName));
|
&Fcb->Mcb->FullName));
|
||||||
|
|
||||||
ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
|
ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
|
||||||
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
||||||
|
|
||||||
CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus);
|
CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus);
|
||||||
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Fcb->SectionObject.ImageSectionObject) {
|
if (Fcb->SectionObject.ImageSectionObject) {
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2PurgeFile: MmFlushImageSection on %wZ.\n",
|
DEBUG(DL_INF, ( "Ext2PurgeFile: MmFlushImageSection on %wZ.\n",
|
||||||
&Fcb->Mcb->FullName));
|
&Fcb->Mcb->FullName));
|
||||||
|
|
||||||
MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite);
|
MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Fcb->SectionObject.DataSectionObject) {
|
if (Fcb->SectionObject.DataSectionObject) {
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2PurgeFile: CcPurgeCacheSection on %wZ.\n",
|
DEBUG(DL_INF, ( "Ext2PurgeFile: CcPurgeCacheSection on %wZ.\n",
|
||||||
&Fcb->Mcb->FullName));
|
&Fcb->Mcb->FullName));
|
||||||
|
|
||||||
CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
|
CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,7 @@ Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath)
|
||||||
* 1 writing support
|
* 1 writing support
|
||||||
*/
|
*/
|
||||||
QueryTable[i].Flags = 0;
|
QueryTable[i].Flags = 0;
|
||||||
QueryTable[0].Name = WRITING_SUPPORT;
|
QueryTable[i].Name = WRITING_SUPPORT;
|
||||||
QueryTable[i].DefaultType = REG_NONE;
|
QueryTable[i].DefaultType = REG_NONE;
|
||||||
QueryTable[i].DefaultLength = 0;
|
QueryTable[i].DefaultLength = 0;
|
||||||
QueryTable[i].DefaultData = NULL;
|
QueryTable[i].DefaultData = NULL;
|
||||||
|
@ -431,6 +431,7 @@ Ext2EresourceAlignmentChecking()
|
||||||
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaInode) & 7) == 0);
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaInode) & 7) == 0);
|
||||||
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaBlock) & 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, 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, bd.bd_bh_lock) & 7) == 0);
|
||||||
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, sbi.s_gd_lock) & 7) == 0);
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, sbi.s_gd_lock) & 7) == 0);
|
||||||
CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0);
|
CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0);
|
||||||
|
@ -555,11 +556,19 @@ DriverEntry (
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status= Ext2StartReaper(
|
||||||
|
&Ext2Global->FcbReaper,
|
||||||
|
Ext2FcbReaperThread);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
|
||||||
/* start resource reaper thread */
|
/* start resource reaper thread */
|
||||||
Status= Ext2StartReaper(
|
Status= Ext2StartReaper(
|
||||||
&Ext2Global->McbReaper,
|
&Ext2Global->McbReaper,
|
||||||
Ext2McbReaperThread);
|
Ext2McbReaperThread);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
Ext2StopReaper(&Ext2Global->FcbReaper);
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,6 +576,7 @@ DriverEntry (
|
||||||
&Ext2Global->bhReaper,
|
&Ext2Global->bhReaper,
|
||||||
Ext2bhReaperThread);
|
Ext2bhReaperThread);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
Ext2StopReaper(&Ext2Global->FcbReaper);
|
||||||
Ext2StopReaper(&Ext2Global->McbReaper);
|
Ext2StopReaper(&Ext2Global->McbReaper);
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,11 @@ extern PEXT2_GLOBAL Ext2Global;
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, Ext2AllocateFcb)
|
|
||||||
#pragma alloc_text(PAGE, Ext2FreeFcb)
|
|
||||||
#pragma alloc_text(PAGE, Ext2AllocateInode)
|
#pragma alloc_text(PAGE, Ext2AllocateInode)
|
||||||
#pragma alloc_text(PAGE, Ext2DestroyInode)
|
#pragma alloc_text(PAGE, Ext2DestroyInode)
|
||||||
#pragma alloc_text(PAGE, Ext2CheckBitmapConsistency)
|
#pragma alloc_text(PAGE, Ext2CheckBitmapConsistency)
|
||||||
#pragma alloc_text(PAGE, Ext2CheckSetBlock)
|
#pragma alloc_text(PAGE, Ext2CheckSetBlock)
|
||||||
#pragma alloc_text(PAGE, Ext2InitializeVcb)
|
#pragma alloc_text(PAGE, Ext2InitializeVcb)
|
||||||
#pragma alloc_text(PAGE, Ext2FreeCcb)
|
|
||||||
#pragma alloc_text(PAGE, Ext2AllocateCcb)
|
|
||||||
#pragma alloc_text(PAGE, Ext2TearDownStream)
|
#pragma alloc_text(PAGE, Ext2TearDownStream)
|
||||||
#pragma alloc_text(PAGE, Ext2DestroyVcb)
|
#pragma alloc_text(PAGE, Ext2DestroyVcb)
|
||||||
#pragma alloc_text(PAGE, Ext2SyncUninitializeCacheMap)
|
#pragma alloc_text(PAGE, Ext2SyncUninitializeCacheMap)
|
||||||
|
@ -139,6 +135,8 @@ Ext2AllocateFcb (
|
||||||
{
|
{
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb;
|
||||||
|
|
||||||
|
ASSERT(ExIsResourceAcquiredExclusiveLite(&Vcb->FcbLock));
|
||||||
|
|
||||||
Fcb = (PEXT2_FCB) ExAllocateFromNPagedLookasideList(
|
Fcb = (PEXT2_FCB) ExAllocateFromNPagedLookasideList(
|
||||||
&(Ext2Global->Ext2FcbLookasideList));
|
&(Ext2Global->Ext2FcbLookasideList));
|
||||||
|
|
||||||
|
@ -200,85 +198,122 @@ Ext2AllocateFcb (
|
||||||
return Fcb;
|
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
|
VOID
|
||||||
Ext2FreeFcb (IN PEXT2_FCB Fcb)
|
Ext2FreeFcb (IN PEXT2_FCB Fcb)
|
||||||
{
|
{
|
||||||
PEXT2_VCB Vcb = Fcb->Vcb;
|
PEXT2_VCB Vcb = Fcb->Vcb;
|
||||||
|
|
||||||
|
_SEH2_TRY {
|
||||||
|
|
||||||
ASSERT((Fcb != NULL) && (Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb != NULL) && (Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
ASSERT((Fcb->Mcb->Identifier.Type == EXT2MCB) &&
|
ASSERT(0 == Fcb->ReferenceCount);
|
||||||
(Fcb->Mcb->Identifier.Size == sizeof(EXT2_MCB)));
|
|
||||||
|
|
||||||
#ifndef _WIN2K_TARGET_
|
#ifndef _WIN2K_TARGET_
|
||||||
FsRtlTeardownPerStreamContexts(&Fcb->Header);
|
FsRtlTeardownPerStreamContexts(&Fcb->Header);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((Fcb->Mcb->Identifier.Type == EXT2MCB) &&
|
|
||||||
(Fcb->Mcb->Identifier.Size == sizeof(EXT2_MCB))) {
|
|
||||||
|
|
||||||
ASSERT (Fcb->Mcb->Fcb == Fcb);
|
|
||||||
if (IsMcbSpecialFile(Fcb->Mcb) || IsFileDeleted(Fcb->Mcb)) {
|
|
||||||
|
|
||||||
ASSERT(!IsRoot(Fcb));
|
|
||||||
Ext2RemoveMcb(Fcb->Vcb, Fcb->Mcb);
|
|
||||||
Fcb->Mcb->Fcb = NULL;
|
|
||||||
|
|
||||||
Ext2UnlinkMcb(Vcb, Fcb->Mcb);
|
|
||||||
Ext2DerefMcb(Fcb->Mcb);
|
|
||||||
Ext2LinkHeadMcb(Vcb, Fcb->Mcb);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Fcb->Mcb->Fcb = NULL;
|
|
||||||
Ext2DerefMcb(Fcb->Mcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
DbgBreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ext2RemoveFcb(Fcb->Vcb, Fcb);
|
|
||||||
|
|
||||||
FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
|
FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
|
||||||
FsRtlUninitializeOplock(&Fcb->Oplock);
|
FsRtlUninitializeOplock(&Fcb->Oplock);
|
||||||
ExDeleteResourceLite(&Fcb->MainResource);
|
ExDeleteResourceLite(&Fcb->MainResource);
|
||||||
ExDeleteResourceLite(&Fcb->PagingIoResource);
|
ExDeleteResourceLite(&Fcb->PagingIoResource);
|
||||||
|
|
||||||
DEBUG(DL_RES, ( "Ext2FreeFcb: Fcb (%p) is being released: %wZ.\n",
|
|
||||||
Fcb, &Fcb->Mcb->FullName));
|
|
||||||
|
|
||||||
Fcb->Identifier.Type = 0;
|
Fcb->Identifier.Type = 0;
|
||||||
Fcb->Identifier.Size = 0;
|
Fcb->Identifier.Size = 0;
|
||||||
|
|
||||||
ExFreeToNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList), Fcb);
|
ExFreeToNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList), Fcb);
|
||||||
DEC_MEM_COUNT(PS_FCB, Fcb, sizeof(EXT2_FCB));
|
DEC_MEM_COUNT(PS_FCB, Fcb, sizeof(EXT2_FCB));
|
||||||
|
|
||||||
|
if (0 == Ext2DerefXcb(&Vcb->ReferenceCount)) {
|
||||||
|
if (!IsMounted(Vcb) || IsDispending(Vcb)) {
|
||||||
|
Ext2CheckDismount(NULL, Vcb, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} _SEH2_FINALLY {
|
||||||
|
} _SEH2_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
VOID
|
||||||
Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb)
|
Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb)
|
||||||
{
|
{
|
||||||
ExInterlockedInsertTailList(&Vcb->FcbList, &Fcb->Next, &Vcb->FcbLock);
|
ASSERT(ExIsResourceAcquiredExclusiveLite(&Vcb->FcbLock));
|
||||||
|
|
||||||
|
KeQuerySystemTime(&Fcb->TsDrop);
|
||||||
Ext2ReferXcb(&Vcb->FcbCount);
|
Ext2ReferXcb(&Vcb->FcbCount);
|
||||||
}
|
Ext2ReferXcb(&Vcb->ReferenceCount);
|
||||||
|
InsertTailList(&Vcb->FcbList, &Fcb->Next);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PEXT2_CCB
|
PEXT2_CCB
|
||||||
|
@ -321,7 +356,6 @@ VOID
|
||||||
Ext2FreeCcb (IN PEXT2_VCB Vcb, IN PEXT2_CCB Ccb)
|
Ext2FreeCcb (IN PEXT2_VCB Vcb, IN PEXT2_CCB Ccb)
|
||||||
{
|
{
|
||||||
ASSERT(Ccb != NULL);
|
ASSERT(Ccb != NULL);
|
||||||
|
|
||||||
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
|
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
|
||||||
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
|
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
|
||||||
|
|
||||||
|
@ -2334,7 +2368,7 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
|
||||||
/* initialize Fcb list head */
|
/* initialize Fcb list head */
|
||||||
InitializeListHead(&Vcb->FcbList);
|
InitializeListHead(&Vcb->FcbList);
|
||||||
KeInitializeSpinLock(&Vcb->FcbLock);
|
ExInitializeResourceLite(&Vcb->FcbLock);
|
||||||
|
|
||||||
/* initialize Mcb list head */
|
/* initialize Mcb list head */
|
||||||
InitializeListHead(&(Vcb->McbList));
|
InitializeListHead(&(Vcb->McbList));
|
||||||
|
@ -2783,7 +2817,7 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb)
|
||||||
|
|
||||||
Ext2CleanupAllMcbs(Vcb);
|
Ext2CleanupAllMcbs(Vcb);
|
||||||
|
|
||||||
Ext2DropGroup(Vcb);
|
Ext2DropBH(Vcb);
|
||||||
|
|
||||||
if (Vcb->bd.bd_bh_cache)
|
if (Vcb->bd.bd_bh_cache)
|
||||||
kmem_cache_destroy(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);
|
ObDereferenceObject(Vcb->TargetDeviceObject);
|
||||||
|
|
||||||
ExDeleteNPagedLookasideList(&(Vcb->InodeLookasideList));
|
ExDeleteNPagedLookasideList(&(Vcb->InodeLookasideList));
|
||||||
|
ExDeleteResourceLite(&Vcb->FcbLock);
|
||||||
ExDeleteResourceLite(&Vcb->McbLock);
|
ExDeleteResourceLite(&Vcb->McbLock);
|
||||||
ExDeleteResourceLite(&Vcb->MetaInode);
|
ExDeleteResourceLite(&Vcb->MetaInode);
|
||||||
ExDeleteResourceLite(&Vcb->MetaBlock);
|
ExDeleteResourceLite(&Vcb->MetaBlock);
|
||||||
|
@ -2994,6 +3029,8 @@ Ext2McbReaperThread(
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
Reaper->Thread = PsGetCurrentThread();
|
||||||
|
|
||||||
/* wake up DirverEntry */
|
/* wake up DirverEntry */
|
||||||
KeSetEvent(&Reaper->Engine, 0, FALSE);
|
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
|
BOOLEAN
|
||||||
Ext2QueryUnusedBH(PEXT2_VCB Vcb, PLIST_ENTRY head)
|
Ext2QueryUnusedBH(PEXT2_VCB Vcb, PLIST_ENTRY head)
|
||||||
{
|
{
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
PLIST_ENTRY list = NULL;
|
PLIST_ENTRY next = NULL;
|
||||||
LARGE_INTEGER now;
|
LARGE_INTEGER now;
|
||||||
BOOLEAN wake = FALSE;
|
BOOLEAN wake = FALSE;
|
||||||
|
|
||||||
KeQuerySystemTime(&now);
|
KeQuerySystemTime(&now);
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE);
|
ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE);
|
||||||
|
|
||||||
while (!IsListEmpty(&Vcb->bd.bd_bh_free)) {
|
while (!IsListEmpty(&Vcb->bd.bd_bh_free)) {
|
||||||
list = RemoveHeadList(&Vcb->bd.bd_bh_free);
|
next = RemoveHeadList(&Vcb->bd.bd_bh_free);
|
||||||
bh = CONTAINING_RECORD(list, struct buffer_head, b_link);
|
bh = CONTAINING_RECORD(next, struct buffer_head, b_link);
|
||||||
if (atomic_read(&bh->b_count)) {
|
if (atomic_read(&bh->b_count)) {
|
||||||
InitializeListHead(&bh->b_link);
|
InitializeListHead(&bh->b_link);
|
||||||
|
/* to be inserted by brelse */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3127,6 +3166,7 @@ Ext2QueryUnusedBH(PEXT2_VCB Vcb, PLIST_ENTRY head)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wake = IsListEmpty(&Vcb->bd.bd_bh_free);
|
wake = IsListEmpty(&Vcb->bd.bd_bh_free);
|
||||||
ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
|
ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
|
||||||
|
|
||||||
|
@ -3154,6 +3194,8 @@ Ext2bhReaperThread(
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
Reaper->Thread = PsGetCurrentThread();
|
||||||
|
|
||||||
/* wake up DirverEntry */
|
/* wake up DirverEntry */
|
||||||
KeSetEvent(&Reaper->Engine, 0, FALSE);
|
KeSetEvent(&Reaper->Engine, 0, FALSE);
|
||||||
|
|
||||||
|
@ -3191,8 +3233,7 @@ Ext2bhReaperThread(
|
||||||
Link = Link->Flink ) {
|
Link = Link->Flink ) {
|
||||||
|
|
||||||
Vcb = CONTAINING_RECORD(Link, EXT2_VCB, Next);
|
Vcb = CONTAINING_RECORD(Link, EXT2_VCB, Next);
|
||||||
if (Ext2QueryUnusedBH(Vcb, &List))
|
NonWait = Ext2QueryUnusedBH(Vcb, &List);
|
||||||
NonWait = TRUE;
|
|
||||||
}
|
}
|
||||||
if (GlobalAcquired) {
|
if (GlobalAcquired) {
|
||||||
ExReleaseResourceLite(&Ext2Global->Resource);
|
ExReleaseResourceLite(&Ext2Global->Resource);
|
||||||
|
@ -3221,6 +3262,146 @@ Ext2bhReaperThread(
|
||||||
PsTerminateSystemThread(STATUS_SUCCESS);
|
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
|
NTSTATUS
|
||||||
Ext2StartReaper(PEXT2_REAPER Reaper, EXT2_REAPER_RELEASE Free)
|
Ext2StartReaper(PEXT2_REAPER Reaper, EXT2_REAPER_RELEASE Free)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,7 +91,10 @@ Ext2FloppyFlush(IN PVOID Parameter)
|
||||||
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
||||||
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
|
||||||
|
Ext2DropBH(Vcb);
|
||||||
CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
|
CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
|
||||||
|
ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
IoSetTopLevelIrp(NULL);
|
IoSetTopLevelIrp(NULL);
|
||||||
|
|
|
@ -7,7 +7,7 @@ reactos/drivers/filesystems/btrfs # Synced to 0.5
|
||||||
|
|
||||||
The following FSD are shared with: http://www.ext2fsd.com/
|
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/
|
The following FSD are shared with: http://www.acc.umu.se/~bosse/
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue