[EXT2_NEW]
Get rid of old ext2 driver and use new one

svn path=/trunk/; revision=69576
This commit is contained in:
Pierre Schweitzer 2015-10-17 22:35:20 +00:00
parent 5a9b98b776
commit b9b583fd22
148 changed files with 8619 additions and 20167 deletions

View file

@ -1,7 +1,6 @@
add_subdirectory(cdfs) add_subdirectory(cdfs)
add_subdirectory(ext2) add_subdirectory(ext2)
#add_subdirectory(ext2_new)
add_subdirectory(fastfat) add_subdirectory(fastfat)
#add_subdirectory(fastfat_new) #add_subdirectory(fastfat_new)
add_subdirectory(fs_rec) add_subdirectory(fs_rec)
@ -10,3 +9,4 @@ add_subdirectory(mup)
add_subdirectory(npfs) add_subdirectory(npfs)
add_subdirectory(ntfs) add_subdirectory(ntfs)
add_subdirectory(udfs) add_subdirectory(udfs)
add_subdirectory(registryfs)

View file

@ -1,35 +1,105 @@
include_directories(inc) include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers
inc)
list(APPEND SOURCE list(APPEND SOURCE
src/volinfo.c src/init.c
src/create.c src/ext3/generic.c
src/write.c src/ext3/htree.c
src/metadata.c src/ext3/indirect.c
src/fastio.c src/ext3/recover.c
src/dircntrl.c src/ext4/ext4_bh.c
src/DiskIO.c src/ext4/ext4_extents.c
src/fsctrl.c src/ext4/ext4_jbd2.c
src/devcntrl.c src/ext4/extents.c
src/flush.c src/jbd/recovery.c
src/ext2init.c src/jbd/replay.c
src/io.c src/jbd/revoke.c
src/close.c src/nls/nls_ascii.c
src/fileinfo.c src/nls/nls_base.c
src/read.c src/nls/nls_cp437.c
src/nls/nls_cp737.c
src/nls/nls_cp775.c
src/nls/nls_cp850.c
src/nls/nls_cp852.c
src/nls/nls_cp855.c
src/nls/nls_cp857.c
src/nls/nls_cp860.c
src/nls/nls_cp861.c
src/nls/nls_cp862.c
src/nls/nls_cp863.c
src/nls/nls_cp864.c
src/nls/nls_cp865.c
src/nls/nls_cp866.c
src/nls/nls_cp869.c
src/nls/nls_cp874.c
src/nls/nls_cp932.c
src/nls/nls_cp936.c
src/nls/nls_cp949.c
src/nls/nls_cp950.c
src/nls/nls_cp1250.c
src/nls/nls_cp1251.c
src/nls/nls_cp1255.c
src/nls/nls_euc-jp.c
src/nls/nls_iso8859-1.c
src/nls/nls_iso8859-2.c
src/nls/nls_iso8859-3.c
src/nls/nls_iso8859-4.c
src/nls/nls_iso8859-5.c
src/nls/nls_iso8859-6.c
src/nls/nls_iso8859-7.c
src/nls/nls_iso8859-9.c
src/nls/nls_iso8859-13.c
src/nls/nls_iso8859-14.c
src/nls/nls_iso8859-15.c
src/nls/nls_koi8-r.c
src/nls/nls_koi8-ru.c
src/nls/nls_koi8-u.c
src/nls/nls_utf8.c
src/block.c
src/cleanup.c src/cleanup.c
src/close.c
src/cmcb.c
src/create.c
src/debug.c
src/devctl.c
src/dirctl.c
src/dispatch.c
src/except.c
src/fastio.c
src/fileinfo.c
src/flush.c
src/fsctl.c
src/linux.c
src/lock.c
src/memory.c
src/misc.c src/misc.c
src/nls.c
src/pnp.c
src/rbtree.c
src/read.c
src/shutdown.c src/shutdown.c
inc/ext2fsd.h) src/volinfo.c
src/write.c
inc/ext2fs.h)
add_library(ext2fs SHARED ${SOURCE}) add_library(ext2fs SHARED ${SOURCE} ext2fs.rc)
if((NOT MSVC) AND (NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")) if(NOT MSVC)
add_target_compile_flags(ext2fs "-Wno-unused-but-set-variable") add_target_compile_flags(ext2fs "-Wno-pointer-sign -Wno-unused-function")
if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
replace_compile_flags("-Werror" " ")
add_target_compile_flags(ext2fs "-Wno-unused-but-set-variable -Wno-unused-variable -Wno-missing-braces")
endif()
else()
#disable warnings: "unreferenced local variable", "initialized, but not used variable", "benign include"
replace_compile_flags("/we\"4189\"" " ")
add_target_compile_flags(ext2fs "/wd\"4189\" /wd\"4142\" /wd\"4101\"")
endif() endif()
target_link_libraries(ext2fs ${PSEH_LIB}) target_link_libraries(ext2fs memcmp ${PSEH_LIB})
add_pch(ext2fs inc/ext2fsd.h SOURCE) add_definitions(-D__KERNEL__ -D_X86_)
set_module_type(ext2fs kernelmodedriver) set_module_type(ext2fs kernelmodedriver)
add_importlibs(ext2fs ntoskrnl hal) add_importlibs(ext2fs ntoskrnl hal)
add_pch(ext2fs inc/ext2fs.h SOURCE)
add_cd_file(TARGET ext2fs DESTINATION reactos/system32/drivers NO_CAB FOR all) add_cd_file(TARGET ext2fs DESTINATION reactos/system32/drivers NO_CAB FOR all)

View file

@ -1,14 +1,13 @@
//{{NO_DEPENDENCIES}} //{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file. // Microsoft Developer Studio generated include file.
// Used by D:\Work\VC\Drivers\ext2FSD\src\ext2.rc // Used by ext2fsd.rc
// //
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101

View file

@ -1,398 +1,389 @@
/************************************************************************* /*
* * COPYRIGHT: See COPYRIGHT.TXT
* File: cleanup.c * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* * FILE: cleanup.c
* Module: Ext2 File System Driver (Kernel mode execution only) * PROGRAMMER: Matt Wu <mattwu@163.com>
* * HOMEPAGE: http://www.ext2fsd.com
* Description: * UPDATE HISTORY:
* Should contain code to handle the "Cleanup" dispatch entry point. */
* This file serves as a placeholder. Please update this file as part
* of designing and implementing your FSD.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h" /* INCLUDES *****************************************************************/
// define the file specific bug-check id #include "ext2fs.h"
#define EXT2_BUG_CHECK_ID EXT2_FILE_CLEANUP
#define DEBUG_LEVEL (DEBUG_TRACE_CLEANUP)
/* GLOBALS ***************************************************************/
/************************************************************************* extern PEXT2_GLOBAL Ext2Global;
*
* Function: Ext2Cleanup() /* DEFINITIONS *************************************************************/
*
* Description: NTSTATUS
* The I/O Manager will invoke this routine to handle a cleanup Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
* request
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
* to be deferred to a worker thread context)
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS NTAPI Ext2Cleanup(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{ {
NTSTATUS RC = STATUS_SUCCESS; PDEVICE_OBJECT DeviceObject;
PtrExt2IrpContext PtrIrpContext = NULL; NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN AreWeTopLevel = FALSE; PEXT2_VCB Vcb;
PFILE_OBJECT FileObject;
PEXT2_FCB Fcb;
PEXT2_CCB Ccb;
PIRP Irp;
PEXT2_MCB Mcb;
DebugTrace( DEBUG_TRACE_IRP_ENTRY, "Cleanup IRP Received...", 0);
FsRtlEnterFileSystem(); BOOLEAN VcbResourceAcquired = FALSE;
ASSERT(DeviceObject); BOOLEAN FcbResourceAcquired = FALSE;
ASSERT(Irp); BOOLEAN FcbPagingIoResourceAcquired = FALSE;
// set the top level context _SEH2_TRY {
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
try ASSERT(IrpContext != NULL);
{ ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
// get an IRP context structure and issue the request DeviceObject = IrpContext->DeviceObject;
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject); if (IsExt2FsDevice(DeviceObject)) {
ASSERT(PtrIrpContext); Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
RC = Ext2CommonCleanup(PtrIrpContext, Irp, TRUE); Irp = IrpContext->Irp;
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
} if (!IsVcbInited(Vcb)) {
except( Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation() ) ) Status = STATUS_SUCCESS;
{ _SEH2_LEAVE;
}
RC = Ext2ExceptionHandler(PtrIrpContext, Irp); FileObject = IrpContext->FileObject;
Fcb = (PEXT2_FCB) FileObject->FsContext;
if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
Fcb->Identifier.Type != EXT2FCB)) {
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
Mcb = Fcb->Mcb;
Ccb = (PEXT2_CCB) FileObject->FsContext2;
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC); if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
} Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
if (AreWeTopLevel) VcbResourceAcquired =
{ ExAcquireResourceExclusiveLite(
IoSetTopLevelIrp(NULL); &Vcb->MainResource,
} IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
);
FsRtlExitFileSystem(); if (Fcb->Identifier.Type == EXT2VCB) {
return(RC); if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
} Vcb->LockFile == FileObject ){
/************************************************************************* ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
* Vcb->LockFile = NULL;
* Function: Ext2CommonCleanup() Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
* }
* Description:
* The actual work is performed here. This routine may be invoked in one' if (Ccb) {
* of the two possible contexts: Ext2DerefXcb(&Vcb->OpenHandleCount);
* (a) in the context of a system worker thread Ext2DerefXcb(&Vcb->OpenVolumeCount);
* (b) in the context of the original caller }
*
* Expected Interrupt Level (for execution) : IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
*
* IRQL_PASSIVE_LEVEL Status = STATUS_SUCCESS;
* _SEH2_LEAVE;
* Return Value: Does not matter! }
*
*************************************************************************/ ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
NTSTATUS NTAPI Ext2CommonCleanup( (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp, if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
BOOLEAN FirstAttempt ) if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
{ IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
!IsVcbReadOnly(Vcb) ) {
NTSTATUS RC = STATUS_SUCCESS; Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
PIO_STACK_LOCATION PtrIoStackLocation = NULL; }
PFILE_OBJECT PtrFileObject = NULL; _SEH2_LEAVE;
PtrExt2FCB PtrFCB = NULL; }
PtrExt2CCB PtrCCB = NULL;
PtrExt2VCB PtrVCB = NULL; if (Ccb == NULL) {
PtrExt2NTRequiredFCB PtrReqdFCB = NULL; Status = STATUS_SUCCESS;
PERESOURCE PtrResourceAcquired = NULL; _SEH2_LEAVE;
}
BOOLEAN CompleteIrp = TRUE;
BOOLEAN PostRequest = FALSE; if (IsDirectory(Fcb)) {
BOOLEAN AcquiredVCB = FALSE; if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
BOOLEAN BlockForResource; SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
int i = 1;
FsRtlNotifyFullChangeDirectory(
try Vcb->NotifySync,
{ &Vcb->NotifyList,
// First, get a pointer to the current I/O stack location Ccb,
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); NULL,
ASSERT(PtrIoStackLocation); FALSE,
FALSE,
PtrFileObject = PtrIoStackLocation->FileObject; 0,
ASSERT(PtrFileObject); NULL,
NULL,
if( !PtrFileObject->FsContext2 ) NULL );
{ }
// This must be a Cleanup request received
// as a result of IoCreateStreamFileObject FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
// Only such a File object would have a NULL CCB
}
DebugTrace( DEBUG_TRACE_MISC, " === Cleanup with NULL CCB", 0);
if( PtrFileObject ) ExReleaseResourceLite(&Vcb->MainResource);
{ VcbResourceAcquired = FALSE;
DebugTrace( DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
} FcbResourceAcquired =
try_return(); ExAcquireResourceExclusiveLite(
} &Fcb->MainResource,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
);
Ext2GetFCB_CCB_VCB_FromFileObject (
PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB ); ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer ) Ext2DerefXcb(&Vcb->OpenHandleCount);
{ Ext2DerefXcb(&Fcb->OpenHandleCount);
DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
} if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
else Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
{ }
DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup Volume", 0);
} if (IsDirectory(Fcb)) {
ext3_release_dir(Fcb->Inode, &Ccb->filp);
PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
ASSERT(PtrVCB); } else {
ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
// (a) Acquiring the VCBResource Exclusively... !IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
// This is done to synchronise with the close and cleanup routines...
BlockForResource = !FirstAttempt; LARGE_INTEGER SysTime;
if( !FirstAttempt ) KeQuerySystemTime(&SysTime);
{
Fcb->Inode->i_atime =
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire VCB Exclusively [Cleanup]", 0); Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
} Fcb->Mcb->LastAccessTime =
else Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire VCB Exclusively [Cleanup]", 0); Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
}
Ext2NotifyReportChange(
if( PtrFileObject ) IrpContext,
{ Vcb,
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject); Fcb->Mcb,
} FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_LAST_WRITE |
i = 1; FILE_NOTIFY_CHANGE_LAST_ACCESS,
while( !AcquiredVCB ) FILE_ACTION_MODIFIED );
{ }
DebugTraceState("VCB AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
if( ! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) ) FsRtlCheckOplock( &Fcb->Oplock,
{ Irp,
DebugTrace( DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquisition FAILED [Cleanup]", 0); IrpContext,
if( BlockForResource && i != 1000 ) NULL,
{ NULL );
LARGE_INTEGER Delay;
Delay.QuadPart = -500 * i; Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i); if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
} Fcb->NonCachedOpenCount--;
else }
{
if( i == 1000 ) if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 ); SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
PostRequest = TRUE; }
try_return( RC = STATUS_PENDING );
} //
} // Drop any byte range locks this process may have on the file.
else //
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquired in [Cleanup]", 0); FsRtlFastUnlockAll(
AcquiredVCB = TRUE; &Fcb->FileLockAnchor,
} FileObject,
i *= 10; IoGetRequestorProcess(Irp),
} NULL );
//
// (b) Acquire the file (FCB) exclusively // If there are no byte range locks owned by other processes on the
if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB ) // file the fast I/O read/write functions doesn't have to check for
{ // locks so we set IsFastIoPossible to FastIoIsPossible again.
// This FCB is an FCB indeed. ;) //
// So acquiring it exclusively... if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
// This is done to synchronise with read/write routines... if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
if( !FirstAttempt ) #if EXT2_DEBUG
{ DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire FCB Exclusively [Cleanup]", 0); Ext2GetCurrentProcessName(),
} "FastIoIsPossible",
else &Fcb->Mcb->FullName
{ ));
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire FCB Exclusively [Cleanup]", 0); #endif
}
if( PtrFileObject ) Fcb->Header.IsFastIoPossible = FastIoIsPossible;
{ }
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject); }
}
if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE |
i = 1; FCB_ALLOC_IN_SETINFO) ){
while( !PtrResourceAcquired )
{ if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) {
PtrReqdFCB = &(PtrFCB->NTRequiredFCB); if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) {
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters ); if (!INODE_HAS_EXTENT(Fcb->Inode)) {
if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) ) #if EXT2_PRE_ALLOCATION_SUPPORT
{ CcZeroData(FileObject, &Fcb->Header.ValidDataLength,
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB Acquisition FAILED [Cleanup]", 0); &Fcb->Header.AllocationSize, TRUE);
if( BlockForResource && i != 1000 ) #endif
{ }
LARGE_INTEGER Delay; }
Delay.QuadPart = -500 * i; }
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i); if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
}
else LARGE_INTEGER Size;
{
if( i == 1000 ) ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 ); FcbPagingIoResourceAcquired = TRUE;
PostRequest = TRUE;
try_return( RC = STATUS_PENDING ); Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
} (ULONGLONG)Fcb->Mcb->Inode.i_size,
} (ULONGLONG)BLOCK_SIZE);
else if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
{
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB acquired [Cleanup]", 0); Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
PtrResourceAcquired = & ( PtrFCB->NTRequiredFCB.MainResource ); Fcb->Header.AllocationSize = Size;
} Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
i *= 10; if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart)
} Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
if (CcIsFileCached(FileObject)) {
// (c) Flush file data to disk CcSetFileSizes(FileObject,
if ( PtrFileObject->PrivateCacheMap != NULL) (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
{ }
IO_STATUS_BLOCK Status; }
CcFlushCache( PtrFileObject->SectionObjectPointer, NULL, 0, &Status ); ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO);
} ExReleaseResourceLite(&Fcb->PagingIoResource);
FcbPagingIoResourceAcquired = FALSE;
// (d) Talk to the FSRTL package (if you use it) about pending oplocks. }
// (e) Notify the FSRTL package (if you use it) for use with pending }
// notification IRPs }
// (f) Unlock byte-range locks (if any were acquired by process)
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
// (g) Attempting to update time stamp values
// Errors are ignored... if (Fcb->OpenHandleCount == 0 || (Mcb = Ccb->SymLink)) {
// Not considered as critical errors...
//
/* // Ext2DeleteFile will acquire these lock inside
if( PtrFCB->OpenHandleCount == 1 ) //
{
ULONG CreationTime, AccessTime, ModificationTime; if (FcbResourceAcquired) {
EXT2_INODE Inode; ExReleaseResourceLite(&Fcb->MainResource);
FcbResourceAcquired = FALSE;
CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart }
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart //
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 ); // this file is to be deleted ...
ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart //
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 ); if (Ccb->SymLink) {
if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) Mcb = Ccb->SymLink;
{ FileObject->DeletePending = FALSE;
// Update time stamps in the inode... }
Inode.i_ctime = CreationTime;
Inode.i_atime = AccessTime; Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
Inode.i_mtime = ModificationTime;
if (NT_SUCCESS(Status)) {
// Updating the inode... if (IsMcbDirectory(Mcb)) {
Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ); Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
} FILE_NOTIFY_CHANGE_DIR_NAME,
} FILE_ACTION_REMOVED );
*/ } else {
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
// (h) Inform the Cache Manager to uninitialize Cache Maps ... FILE_NOTIFY_CHANGE_FILE_NAME,
CcUninitializeCacheMap( PtrFileObject, NULL, NULL ); FILE_ACTION_REMOVED );
}
// (i) Decrementing the Open Handle count... }
if( PtrFCB->OpenHandleCount )
{ //
InterlockedDecrement( &PtrFCB->OpenHandleCount ); // re-acquire the main resource lock
} //
else
{ FcbResourceAcquired =
Ext2BreakPoint(); ExAcquireResourceExclusiveLite(
} &Fcb->MainResource,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
PtrFCB->FCBFlags |= FO_CLEANUP_COMPLETE; );
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Cleanup]", PtrFCB->ReferenceCount ); SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Cleanup]", PtrFCB->OpenHandleCount ); if (CcIsFileCached(FileObject)) {
CcSetFileSizes(FileObject,
// (j) Remove share access... (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
// Will do that later ;) }
}
// (k) Is this a close on delete file? }
// If so, delete the file...
if( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE) && if (!IsDirectory(Fcb)) {
!PtrFCB->OpenHandleCount )
{ if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
// (Fcb->NonCachedOpenCount + 1 == Fcb->ReferenceCount) &&
// Have to delete this file... (Fcb->SectionObject.DataSectionObject != NULL)) {
//
Ext2DeleteFile( PtrFCB, PtrIrpContext ); if (!IsVcbReadOnly(Vcb)) {
PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart = 0; CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
PtrFCB->INodeNo = 0; ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
} }
}
else if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
{ ExReleaseResourceLite(&(Fcb->PagingIoResource));
// This must be a volume close... }
// Just go ahead and complete this IRP...
PtrVCB->VCBOpenCount--; CcPurgeCacheSection( &Fcb->SectionObject,
DebugTrace(DEBUG_TRACE_MISC, "VCB Cleanup Requested !!!", 0); NULL,
CompleteIrp = TRUE; 0,
} FALSE );
}
try_return();
CcUninitializeCacheMap(FileObject, NULL, NULL);
try_exit: NOTHING; }
} IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
finally
{ DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
if(PtrResourceAcquired) Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
{
Ext2ReleaseResource(PtrResourceAcquired); Status = STATUS_SUCCESS;
DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** Resource Released [Cleanup]", 0);
DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", if (FileObject) {
PtrResourceAcquired->ActiveCount, SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
PtrResourceAcquired->NumberOfExclusiveWaiters, }
PtrResourceAcquired->NumberOfSharedWaiters );
} _SEH2_FINALLY {
if( PtrFileObject )
{ if (FcbPagingIoResourceAcquired) {
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject); ExReleaseResourceLite(&Fcb->PagingIoResource);
} }
} if (FcbResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource);
if( AcquiredVCB ) }
{
ASSERT(PtrVCB); if (VcbResourceAcquired) {
Ext2ReleaseResource(&(PtrVCB->VCBResource)); ExReleaseResourceLite(&Vcb->MainResource);
DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** VCB Released [Cleanup]", 0); }
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
AcquiredVCB = FALSE; if (!IrpContext->ExceptionInProgress) {
if( PtrFileObject ) if (Status == STATUS_PENDING) {
{ Ext2QueueRequest(IrpContext);
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject); } else {
} IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteIrpContext(IrpContext, Status);
} }
}
if( PostRequest ) } _SEH2_END;
{
RC = Ext2PostRequest(PtrIrpContext, PtrIrp); return Status;
}
if( RC != STATUS_PENDING )
{
Ext2ReleaseIrpContext( PtrIrpContext );
// complete the IRP
IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
}
} // end of "finally" processing
return(RC);
} }

View file

@ -1,515 +1,282 @@
/************************************************************************* /*
* * COPYRIGHT: See COPYRIGHT.TXT
* File: close.c * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* * FILE: close.c
* Module: Ext2 File System Driver (Kernel mode execution only) * PROGRAMMER: Matt Wu <mattwu@163.com>
* * HOMEPAGE: http://www.ext2fsd.com
* Description: * UPDATE HISTORY:
* Should contain code to handle the "Close" dispatch entry point. */
* This file serves as a placeholder. Please update this file as part
* of designing and implementing your FSD.
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h" /* INCLUDES *****************************************************************/
// define the file specific bug-check id #include "ext2fs.h"
#define EXT2_BUG_CHECK_ID EXT2_FILE_CLOSE
#define DEBUG_LEVEL (DEBUG_TRACE_CLOSE) /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/************************************************************************* /* DEFINITIONS *************************************************************/
*
* Function: Ext2Close() #ifdef ALLOC_PRAGMA
* #pragma alloc_text(PAGE, Ext2QueueCloseRequest)
* Description: #pragma alloc_text(PAGE, Ext2DeQueueCloseRequest)
* The I/O Manager will invoke this routine to handle a close #endif
* request
* NTSTATUS
* Expected Interrupt Level (for execution) : Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
*
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
* to be deferred to a worker thread context)
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS NTAPI Ext2Close(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{ {
NTSTATUS RC = STATUS_SUCCESS; PDEVICE_OBJECT DeviceObject;
PtrExt2IrpContext PtrIrpContext = NULL; NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN AreWeTopLevel = FALSE; PEXT2_VCB Vcb = NULL;
BOOLEAN VcbResourceAcquired = FALSE;
PFILE_OBJECT FileObject;
PEXT2_FCB Fcb;
BOOLEAN FcbResourceAcquired = FALSE;
PEXT2_CCB Ccb;
BOOLEAN bDeleteVcb = FALSE;
BOOLEAN bBeingClosed = FALSE;
BOOLEAN bSkipLeave = FALSE;
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Close IRP Received...", 0); _SEH2_TRY {
FsRtlEnterFileSystem(); ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
ASSERT(DeviceObject); DeviceObject = IrpContext->DeviceObject;
ASSERT(Irp); if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_SUCCESS;
Vcb = NULL;
_SEH2_LEAVE;
}
// set the top level context Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
AreWeTopLevel = Ext2IsIrpTopLevel(Irp); ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
try if (!ExAcquireResourceExclusiveLite(
{ &Vcb->MainResource,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
Vcb->OpenHandleCount, Vcb->ReferenceCount));
// get an IRP context structure and issue the request Status = STATUS_PENDING;
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject); _SEH2_LEAVE;
ASSERT(PtrIrpContext); }
VcbResourceAcquired = TRUE;
RC = Ext2CommonClose(PtrIrpContext, Irp, 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)) {
except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
{
RC = Ext2ExceptionHandler(PtrIrpContext, Irp); FileObject = NULL;
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC); Fcb = IrpContext->Fcb;
} Ccb = IrpContext->Ccb;
if (AreWeTopLevel) } else {
{
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem(); FileObject = IrpContext->FileObject;
Fcb = (PEXT2_FCB) FileObject->FsContext;
if (!Fcb) {
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
ASSERT(Fcb != NULL);
Ccb = (PEXT2_CCB) FileObject->FsContext2;
}
return(RC); DEBUG(DL_INF, ( "Ext2Close: (VCB) bBeingClosed = %d Vcb = %p ReferCount = %d\n",
bBeingClosed, Vcb, Vcb->ReferenceCount));
if (Fcb->Identifier.Type == EXT2VCB) {
if (Ccb) {
Ext2DerefXcb(&Vcb->ReferenceCount);
Ext2FreeCcb(Vcb, Ccb);
if (FileObject) {
FileObject->FsContext2 = Ccb = NULL;
}
}
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
if ( Fcb->Identifier.Type != EXT2FCB ||
Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
_SEH2_LEAVE;
}
if (!ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
FcbResourceAcquired = TRUE;
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
if (!Ccb) {
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
if (IsFlagOn(Fcb->Flags, FCB_STATE_BUSY)) {
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY);
DEBUG(DL_WRN, ( "Ext2Close: busy bit set: %wZ\n", &Fcb->Mcb->FullName ));
Status = STATUS_PENDING;
_SEH2_LEAVE;
}
DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n",
Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));
if (Ccb) {
Ext2FreeCcb(Vcb, Ccb);
if (FileObject) {
FileObject->FsContext2 = Ccb = NULL;
}
}
if (0 == Ext2DerefXcb(&Fcb->ReferenceCount)) {
//
// Remove Fcb from Vcb->FcbList ...
//
if (FcbResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource);
FcbResourceAcquired = FALSE;
}
Ext2FreeFcb(Fcb);
if (FileObject) {
FileObject->FsContext = Fcb = NULL;
}
}
Ext2DerefXcb(&Vcb->ReferenceCount);
Status = STATUS_SUCCESS;
} _SEH2_FINALLY {
if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) {
/* for Ext2Fsd driver open/close, Vcb is NULL */
if ((!bBeingClosed) && (Vcb->ReferenceCount == 0)&&
(!IsMounted(Vcb) || IsDispending(Vcb))) {
bDeleteVcb = TRUE;
}
}
if (bSkipLeave && !bBeingClosed) {
ClearFlag(Vcb->Flags, VCB_BEING_CLOSED);
}
if (FcbResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource);
}
if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource);
}
if (!IrpContext->ExceptionInProgress) {
if (Status == STATUS_PENDING) {
Ext2QueueCloseRequest(IrpContext);
} else {
Ext2CompleteIrpContext(IrpContext, Status);
if (bDeleteVcb) {
PVPB Vpb = Vcb->Vpb;
DEBUG(DL_DBG, ( "Ext2Close: Try to free Vcb %p and Vpb %p\n",
Vcb, Vpb));
Ext2CheckDismount(IrpContext, Vcb, FALSE);
}
}
}
} _SEH2_END;
return Status;
} }
VOID
/************************************************************************* Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
*
* Function: Ext2CommonClose()
*
* Description:
* The actual work is performed here. This routine may be invoked in one'
* of the two possible contexts:
* (a) in the context of a system worker thread
* (b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: Does not matter!
*
*************************************************************************/
NTSTATUS NTAPI Ext2CommonClose(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
BOOLEAN FirstAttempt )
{ {
NTSTATUS RC = STATUS_SUCCESS; ASSERT(IrpContext);
PIO_STACK_LOCATION PtrIoStackLocation = NULL; ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
PFILE_OBJECT PtrFileObject = NULL; (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
PtrExt2FCB PtrFCB = NULL;
PtrExt2CCB PtrCCB = NULL;
PtrExt2VCB PtrVCB = NULL;
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
PERESOURCE PtrResourceAcquired = NULL;
PERESOURCE PtrPagingIoResourceAcquired = NULL;
BOOLEAN CompleteIrp = TRUE; if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
BOOLEAN PostRequest = FALSE;
BOOLEAN AcquiredVCB = FALSE;
BOOLEAN BlockForResource;
int i = 1;
try if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) {
{ Ext2Sleep(500); /* 0.5 sec*/
// First, get a pointer to the current I/O stack location } else {
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); Ext2Sleep(50); /* 0.05 sec*/
ASSERT(PtrIoStackLocation); }
PtrFileObject = PtrIoStackLocation->FileObject; } else {
ASSERT(PtrFileObject);
if( !PtrFileObject->FsContext2 ) SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
{ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
// This must be a Cleanup request received
// as a result of IoCreateStreamFileObject
// Only such a File object would have a NULL CCB
DebugTrace( DEBUG_TRACE_SPECIAL, " === Close with NULL CCB", 0); IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext;
if( PtrFileObject ) IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2;
{ }
DebugTrace( DEBUG_TRACE_SPECIAL, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
try_return();
}
// Get the FCB and CCB pointers ExInitializeWorkItem(
&IrpContext->WorkQueueItem,
Ext2DeQueueCloseRequest,
IrpContext);
Ext2GetFCB_CCB_VCB_FromFileObject ( ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue);
PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB ); }
PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension); VOID NTAPI
ASSERT( PtrVCB ); Ext2DeQueueCloseRequest (IN PVOID Context)
{
if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer ) PEXT2_IRP_CONTEXT IrpContext;
//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
{ IrpContext = (PEXT2_IRP_CONTEXT) Context;
DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer ); ASSERT(IrpContext);
} ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
else (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
{
DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -null-", 0); _SEH2_TRY {
}
_SEH2_TRY {
// (a) Acquiring the VCBResource Exclusively...
// This is done to synchronise with the close and cleanup routines... FsRtlEnterFileSystem();
// if( ExTryToAcquireResourceExclusiveLite(&(PtrVCB->VCBResource) ) ) Ext2Close(IrpContext);
BlockForResource = !FirstAttempt; } _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
if( !FirstAttempt )
{ Ext2ExceptionHandler(IrpContext);
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire VCB Exclusively [Close]", 0); } _SEH2_END;
}
else } _SEH2_FINALLY {
{
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Exclusively [Close]", 0); FsRtlExitFileSystem();
} } _SEH2_END;
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
i = 1;
while( !AcquiredVCB )
{
DebugTraceState( "VCB AC:0x%LX EX:0x%LX SW:0x%LX [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
if(! ExAcquireResourceExclusiveLite( &(PtrVCB->VCBResource), FALSE ) )
{
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquisition FAILED [Close]", 0);
if( BlockForResource && i != 1000 )
{
LARGE_INTEGER Delay;
//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY );
Delay.QuadPart = -500 * i;
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
}
else
{
if( i == 1000 )
DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
PostRequest = TRUE;
try_return( RC = STATUS_PENDING );
}
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired in [Close]", 0);
AcquiredVCB = TRUE;
}
i *= 10;
}
// (b) Acquire the file (FCB) exclusively
if( PtrFCB && PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB )
{
// This FCB is an FCB indeed. ;)
// So acquiring it exclusively...
// This is done to synchronise with read/write routines...
if( !FirstAttempt )
{
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire FCB Exclusively [Close]", 0);
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Exclusively [Close]", 0);
}
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
PtrReqdFCB = &PtrFCB->NTRequiredFCB;
i = 1;
while( !PtrResourceAcquired )
{
DebugTraceState( "FCBMain AC:0x%LX EX:0x%LX SW:0x%LX [Close]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
if(! ExAcquireResourceExclusiveLite( &(PtrReqdFCB->MainResource), FALSE ) )
{
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [Close]", 0);
if( BlockForResource && i != 1000 )
{
LARGE_INTEGER Delay;
//KeSetPriorityThread( PsGetCurrentThread(),LOW_REALTIME_PRIORITY );
Delay.QuadPart = -500 * i;
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
}
else
{
if( i == 1000 )
DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
PostRequest = TRUE;
try_return( RC = STATUS_PENDING );
}
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [Close]", 0);
PtrResourceAcquired = & ( PtrReqdFCB->MainResource );
}
i *= 10;
}
i = 1;
while( !PtrPagingIoResourceAcquired )
{
DebugTraceState( "FCBPaging AC:0x%LX EX:0x%LX SW:0x%LX [Close]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
if(! ExAcquireResourceExclusiveLite( &(PtrReqdFCB->PagingIoResource), FALSE ) )
{
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [Close]", 0);
if( BlockForResource && i != 1000 )
{
LARGE_INTEGER Delay;
// KeSetPriorityThread( PsGetCurrentThread(), LOW_REALTIME_PRIORITY );
Delay.QuadPart = -500 * i;
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
DebugTrace(DEBUG_TRACE_MISC, "*** Retrying... after 50 * %ld ms [Close]", i);
}
else
{
if( i == 1000 )
DebugTrace(DEBUG_TRACE_MISC, "*** Reposting... [Close]", 0 );
PostRequest = TRUE;
try_return( RC = STATUS_PENDING );
}
}
else
{
DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [Close]", 0);
PtrPagingIoResourceAcquired = & ( PtrReqdFCB->PagingIoResource );
}
i *= 10;
}
// (c) Delete the CCB structure (free memory)
RemoveEntryList( &PtrCCB->NextCCB );
Ext2ReleaseCCB( PtrCCB );
PtrFileObject->FsContext2 = NULL;
// (d) Decrementing the Reference Count...
if( PtrFCB->ReferenceCount )
{
InterlockedDecrement( &PtrFCB->ReferenceCount );
}
else
{
Ext2BreakPoint();
}
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Close]", PtrFCB->ReferenceCount );
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Close]", PtrFCB->OpenHandleCount );
if( PtrFCB->ReferenceCount == 0 )
{
// Attempting to update time stamp values
// Errors are ignored...
// Not considered as critical errors...
{
ULONG CreationTime, AccessTime, ModificationTime;
EXT2_INODE Inode;
CreationTime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
AccessTime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
ModificationTime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
- Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
{
// Update time stamps in the inode...
Inode.i_ctime = CreationTime;
Inode.i_atime = AccessTime;
Inode.i_mtime = ModificationTime;
// Updating the inode...
Ext2WriteInode( NULL, PtrVCB, PtrFCB->INodeNo, &Inode );
}
}
if( PtrFCB->INodeNo == EXT2_ROOT_INO )
{
//
// Root Directory FCB
// Preserve this
// FSD has a File Object for this FCB...
//
DebugTrace(DEBUG_TRACE_MISC, "^^^^^Root Directory FCB ; leaveing it alone[Close]", 0);
// Do nothing...
}
else if( PtrFCB->DcbFcb.Dcb.PtrDirFileObject )
{
//
// If this is a FCB created on the FSD's initiative
// Leave it alone
//
DebugTrace(DEBUG_TRACE_MISC, "^^^^^FCB Created on the FSD's initiative; leaveing it alone[Close]", 0);
if( !PtrFCB->ClosableFCBs.OnClosableFCBList )
{
InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
&PtrFCB->ClosableFCBs.ClosableFCBList );
PtrVCB->ClosableFCBs.Count++;
PtrFCB->ClosableFCBs.OnClosableFCBList = TRUE;
}
if( PtrVCB->ClosableFCBs.Count > EXT2_MAXCLOSABLE_FCBS_UL )
{
PtrExt2FCB PtrTempFCB = NULL;
// Checking if Closable FCBs are too many in number...
// Shouldn't block the
// Should do this asynchronously...
// Maybe later...
PLIST_ENTRY PtrEntry = NULL;
PtrEntry = RemoveHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead );
PtrTempFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, ClosableFCBs.ClosableFCBList );
if( Ext2CloseClosableFCB( PtrTempFCB ) )
{
DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Close]", PtrTempFCB );
ExFreePool( PtrTempFCB );
PtrVCB->ClosableFCBs.Count--;
}
else
{
// Put the FCB back in the list...
InsertHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
&PtrTempFCB->ClosableFCBs.ClosableFCBList );
}
DebugTrace( DEBUG_TRACE_SPECIAL, "ClosableFCBs Count = %ld [Close]", PtrVCB->ClosableFCBs.Count );
}
}
else
{
// Remove this FCB as well...
DebugTrace(DEBUG_TRACE_MISC, "^^^^^Deleting FCB [Close]", 0);
RemoveEntryList( &PtrFCB->NextFCB );
if ( PtrPagingIoResourceAcquired )
{
Ext2ReleaseResource(PtrPagingIoResourceAcquired);
DebugTraceState( "Resource AC:0x%LX EX:0x%LX SW:0x%LX [Close]",
PtrPagingIoResourceAcquired->ActiveCount,
PtrPagingIoResourceAcquired->NumberOfExclusiveWaiters,
PtrPagingIoResourceAcquired->NumberOfSharedWaiters );
PtrPagingIoResourceAcquired = NULL;
}
if ( PtrResourceAcquired )
{
Ext2ReleaseResource(PtrResourceAcquired);
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Close]", 0);
DebugTraceState( "Resource AC:0x%LX EX:0x%LX SW:0x%LX [Close]",
PtrResourceAcquired->ActiveCount,
PtrResourceAcquired->NumberOfExclusiveWaiters,
PtrResourceAcquired->NumberOfSharedWaiters );
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
PtrResourceAcquired = NULL;
}
Ext2ReleaseFCB( PtrFCB );
}
}
CompleteIrp = TRUE;
}
else
{
// This must be a volume close...
// What do I do now? ;)
DebugTrace(DEBUG_TRACE_MISC, "VCB Close Requested !!!", 0);
CompleteIrp = TRUE;
}
try_return();
try_exit: NOTHING;
}
finally
{
if ( PtrPagingIoResourceAcquired )
{
Ext2ReleaseResource(PtrPagingIoResourceAcquired);
DebugTraceState( "Resource AC:0x%LX EX:0x%LX SW:0x%LX [Close]",
PtrPagingIoResourceAcquired->ActiveCount,
PtrPagingIoResourceAcquired->NumberOfExclusiveWaiters,
PtrPagingIoResourceAcquired->NumberOfSharedWaiters );
PtrPagingIoResourceAcquired = NULL;
}
if ( PtrResourceAcquired )
{
Ext2ReleaseResource(PtrResourceAcquired);
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Close]", 0);
DebugTraceState( "Resource AC:0x%LX EX:0x%LX SW:0x%LX [Close]",
PtrResourceAcquired->ActiveCount,
PtrResourceAcquired->NumberOfExclusiveWaiters,
PtrResourceAcquired->NumberOfSharedWaiters );
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
PtrResourceAcquired = NULL;
}
if (AcquiredVCB)
{
ASSERT(PtrVCB);
Ext2ReleaseResource(&(PtrVCB->VCBResource));
DebugTraceState( "VCB AC:0x%LX EX:0x%LX SW:0x%LX [Close]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Close]", 0);
AcquiredVCB = FALSE;
if( PtrFileObject )
{
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Close]", PtrFileObject);
}
}
if( PostRequest )
{
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
}
else if( CompleteIrp && RC != STATUS_PENDING )
{
// complete the IRP
IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
Ext2ReleaseIrpContext( PtrIrpContext );
}
} // end of "finally" processing
return(RC);
} }

File diff suppressed because it is too large Load diff

View file

@ -62,8 +62,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,0,0,3 FILEVERSION 0,6,2,0
PRODUCTVERSION 0,0,0,3 PRODUCTVERSION 0,6,2,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x29L FILEFLAGS 0x29L
@ -81,14 +81,14 @@ BEGIN
VALUE "Comments", "Ext2 File System Driver\0" VALUE "Comments", "Ext2 File System Driver\0"
VALUE "CompanyName", "Purayidathil\0" VALUE "CompanyName", "Purayidathil\0"
VALUE "FileDescription", "Ext2 File System Driver\0" VALUE "FileDescription", "Ext2 File System Driver\0"
VALUE "FileVersion", "0, 0, 0, 3\0" VALUE "FileVersion", "0, 6, 2, 0\0"
VALUE "InternalName", "ext2.sys\0" VALUE "InternalName", "ext2fs.sys\0"
VALUE "LegalCopyright", "Copyright © 2002 Manoj Paul Joseph\0" VALUE "LegalCopyright", "Copyright © 2015 Matt Wu\0"
VALUE "LegalTrademarks", " - \0" VALUE "LegalTrademarks", " - \0"
VALUE "OriginalFilename", "ext2.sys\0" VALUE "OriginalFilename", "ext2fs.sys\0"
VALUE "PrivateBuild", " - \0" VALUE "PrivateBuild", " - \0"
VALUE "ProductName", "Ext2 File System Driver for Windows NT\0" VALUE "ProductName", "Ext2 File System Driver for Windows\0"
VALUE "ProductVersion", "0, 0, 0, 3\0" VALUE "ProductVersion", "0, 6, 2, 0\0"
VALUE "SpecialBuild", " - \0" VALUE "SpecialBuild", " - \0"
END END
END END

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,346 +1,268 @@
/************************************************************************* /*
* * COPYRIGHT: See COPYRIGHT.TXT
* File: flush.c * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* * FILE: flush.c
* Module: Ext2 File System Driver (Kernel mode execution only) * PROGRAMMER: Matt Wu <mattwu@163.com>
* * HOMEPAGE: http://www.ext2fsd.com
* Description: * UPDATE HISTORY:
* Contains code to handle the "Flush Buffers" dispatch entry point. */
*
* Author: Manoj Paul Joseph
*
*
*************************************************************************/
#include "ext2fsd.h" /* INCLUDES *****************************************************************/
// define the file specific bug-check id #include "ext2fs.h"
#define EXT2_BUG_CHECK_ID EXT2_FILE_FLUSH
#define DEBUG_LEVEL (DEBUG_TRACE_FLUSH) /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
/************************************************************************* NTSTATUS NTAPI
* Ext2FlushCompletionRoutine (
* Function: Ext2Flush() IN PDEVICE_OBJECT DeviceObject,
* IN PIRP Irp,
* Description: IN PVOID Context )
* The I/O Manager will invoke this routine to handle a flush buffers
* request
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
* to be deferred to a worker thread context)
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS NTAPI Ext2Flush(
PDEVICE_OBJECT DeviceObject, // the logical volume device object
PIRP Irp) // I/O Request Packet
{ {
NTSTATUS RC = STATUS_SUCCESS; if (Irp->PendingReturned)
PtrExt2IrpContext PtrIrpContext = NULL; IoMarkIrpPending( Irp );
BOOLEAN AreWeTopLevel = FALSE;
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Flush IRP Received...", 0);
// Ext2BreakPoint();
FsRtlEnterFileSystem(); if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
ASSERT(DeviceObject); Irp->IoStatus.Status = STATUS_SUCCESS;
ASSERT(Irp);
// set the top level context return STATUS_SUCCESS;
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
try
{
// get an IRP context structure and issue the request
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
ASSERT(PtrIrpContext);
RC = Ext2CommonFlush(PtrIrpContext, Irp);
} except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
}
if (AreWeTopLevel) {
IoSetTopLevelIrp(NULL);
}
FsRtlExitFileSystem();
return(RC);
} }
NTSTATUS
/************************************************************************* Ext2FlushFiles(
* IN PEXT2_IRP_CONTEXT IrpContext,
* Function: Ext2CommonFlush() IN PEXT2_VCB Vcb,
* IN BOOLEAN bShutDown
* Description: )
* The actual work is performed here. This routine may be invoked in one'
* of the two possible contexts:
* (a) in the context of a system worker thread
* (b) in the context of the original caller
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: STATUS_SUCCESS/Error
*
*************************************************************************/
NTSTATUS NTAPI Ext2CommonFlush(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp)
{ {
NTSTATUS RC = STATUS_SUCCESS; IO_STATUS_BLOCK IoStatus;
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
PFILE_OBJECT PtrFileObject = NULL;
PtrExt2FCB PtrFCB = NULL;
PtrExt2CCB PtrCCB = NULL;
PtrExt2VCB PtrVCB = NULL;
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
BOOLEAN AcquiredFCB = FALSE;
BOOLEAN PostRequest = FALSE;
BOOLEAN CanWait = TRUE;
try { PEXT2_FCB Fcb;
// First, get a pointer to the current I/O stack location PLIST_ENTRY ListEntry;
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
ASSERT(PtrIoStackLocation);
PtrFileObject = PtrIoStackLocation->FileObject; if (IsVcbReadOnly(Vcb)) {
ASSERT(PtrFileObject); return STATUS_SUCCESS;
}
// Get the FCB and CCB pointers IoStatus.Status = STATUS_SUCCESS;
PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
ASSERT(PtrCCB);
PtrFCB = PtrCCB->PtrFCB;
AssertFCB( PtrFCB );
/*ASSERT(PtrFCB); DEBUG(DL_INF, ( "Flushing Files ...\n"));
ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );*/
PtrReqdFCB = &(PtrFCB->NTRequiredFCB); // Flush all Fcbs in Vcb list queue.
for (ListEntry = Vcb->FcbList.Flink;
ListEntry != &Vcb->FcbList;
ListEntry = ListEntry->Flink ) {
// Get some of the parameters supplied to us Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); ExAcquireResourceExclusiveLite(
&Fcb->MainResource, TRUE);
IoStatus.Status = Ext2FlushFile(IrpContext, Fcb, NULL);
ExReleaseResourceLite(&Fcb->MainResource);
}
// If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous. return IoStatus.Status;
if (!CanWait) {
PostRequest = TRUE;
try_return();
}
// Check the type of object passed-in. That will determine the course of
// action we take.
if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || (PtrFCB->FCBFlags & EXT2_FCB_ROOT_DIRECTORY)) {
if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) {
PtrVCB = (PtrExt2VCB)(PtrFCB);
} else {
PtrVCB = PtrFCB->PtrVCB;
}
// The caller wishes to flush all files for the mounted
// logical volume. The flush volume routine below should simply
// walk through all of the open file streams, acquire the
// FCB resource, and request the flush operation from the Cache
// Manager. Basically, the sequence of operations listed below
// for a single file should be executed on all open files.
Ext2FlushLogicalVolume(PtrIrpContext, PtrIrp, PtrVCB);
try_return();
}
if (!(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY))
{
// This is a regular file.
ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE);
AcquiredFCB = TRUE;
// Request the Cache Manager to perform a flush operation.
// Further, instruct the Cache Manager that we wish to flush the
// entire file stream.
Ext2FlushAFile(PtrReqdFCB, &(PtrIrp->IoStatus));
RC = PtrIrp->IoStatus.Status;
// All done. You may want to also flush the directory entry for the
// file stream at this time.
// Some log-based FSD implementations may wish to flush their
// log files at this time. Finally, you should update the time-stamp
// values for the file stream appropriately. This would involve
// obtaining the current time and modifying the appropriate directory
// entry fields.
}
try_exit:
if (AcquiredFCB)
{
Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [Flush]", 0);
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Flush]",
PtrReqdFCB->MainResource.ActiveCount,
PtrReqdFCB->MainResource.NumberOfExclusiveWaiters,
PtrReqdFCB->MainResource.NumberOfSharedWaiters );
AcquiredFCB = FALSE;
}
if (!PostRequest)
{
PIO_STACK_LOCATION PtrNextIoStackLocation = NULL;
NTSTATUS RC1 = STATUS_SUCCESS;
// Send the request down at this point.
// To do this, you must set the next IRP stack location, and
// maybe set a completion routine.
// Be careful about marking the IRP pending if the lower level
// driver returned pending and you do have a completion routine!
PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp);
*PtrNextIoStackLocation = *PtrIoStackLocation;
// Set the completion routine to "eat-up" any
// STATUS_INVALID_DEVICE_REQUEST error code returned by the lower
// level driver.
IoSetCompletionRoutine(PtrIrp, Ext2FlushCompletion, NULL, TRUE, TRUE, TRUE);
/*
* The exception handlers propably masked out the
* fact that PtrVCB was never set.
* -- Filip Navara, 18/08/2004
*/
PtrVCB = PtrFCB->PtrVCB;
RC1 = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp);
RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1);
}
} finally {
if (PostRequest) {
// Nothing to lock now.
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
} else {
// Release the IRP context at this time.
Ext2ReleaseIrpContext(PtrIrpContext);
}
}
return(RC);
} }
/************************************************************************* NTSTATUS
* Ext2FlushVolume (
* Function: Ext2FlushAFile() IN PEXT2_IRP_CONTEXT IrpContext,
* IN PEXT2_VCB Vcb,
* Description: IN BOOLEAN bShutDown
* Tell the Cache Manager to perform a flush. )
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
void NTAPI Ext2FlushAFile(
PtrExt2NTRequiredFCB PtrReqdFCB,
PIO_STATUS_BLOCK PtrIoStatus)
{ {
CcFlushCache(&(PtrReqdFCB->SectionObject), NULL, 0, PtrIoStatus); IO_STATUS_BLOCK IoStatus;
return;
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Vcb->PagingIoResource);
CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
return IoStatus.Status;
} }
/************************************************************************* NTSTATUS
* Ext2FlushFile (
* Function: Ext2FlushLogicalVolume() IN PEXT2_IRP_CONTEXT IrpContext,
* IN PEXT2_FCB Fcb,
* Description: IN PEXT2_CCB Ccb
* Flush everything beginning at root directory. )
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
void NTAPI Ext2FlushLogicalVolume(
PtrExt2IrpContext PtrIrpContext,
PIRP PtrIrp,
PtrExt2VCB PtrVCB)
{ {
BOOLEAN AcquiredVCB = FALSE; IO_STATUS_BLOCK IoStatus;
try { ASSERT(Fcb != NULL);
ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE); ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
AcquiredVCB = TRUE; /* update timestamp and achieve attribute */
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired Ex [Flush] ", 0); if (Ccb != NULL) {
// Go through the list of FCB's. You would probably if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
// flush all of the files. Then, you could flush the
// directories that you may have have pinned into memory.
// NOTE: This function may also be invoked internally as part of LARGE_INTEGER SysTime;
// processing a shutdown request. KeQuerySystemTime(&SysTime);
} Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
finally Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
{ Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
if (AcquiredVCB) }
{ }
Ext2ReleaseResource(&(PtrVCB->VCBResource));
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Released [Flush]", 0);
DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Flush]",
PtrVCB->VCBResource.ActiveCount,
PtrVCB->VCBResource.NumberOfExclusiveWaiters,
PtrVCB->VCBResource.NumberOfSharedWaiters );
}
}
return; if (IsDirectory(Fcb)) {
return STATUS_SUCCESS;
}
DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
return IoStatus.Status;
} }
NTSTATUS
/************************************************************************* Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
*
* Function: Ext2FlushCompletion()
*
* Description:
* Eat up any bad errors.
*
* Expected Interrupt Level (for execution) :
*
* IRQL_PASSIVE_LEVEL
*
* Return Value: None
*
*************************************************************************/
NTSTATUS NTAPI Ext2FlushCompletion(
PDEVICE_OBJECT PtrDeviceObject,
PIRP PtrIrp,
PVOID Context)
{ {
if (PtrIrp->PendingReturned) { NTSTATUS Status = STATUS_SUCCESS;
IoMarkIrpPending(PtrIrp);
}
if (PtrIrp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) { PIRP Irp = NULL;
// cannot do much here, can we? PIO_STACK_LOCATION IrpSp = NULL;
PtrIrp->IoStatus.Status = STATUS_SUCCESS;
}
return(STATUS_SUCCESS); PEXT2_VCB Vcb = NULL;
} PEXT2_FCB Fcb = NULL;
PEXT2_FCBVCB FcbOrVcb = NULL;
PEXT2_CCB Ccb = NULL;
PFILE_OBJECT FileObject = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
BOOLEAN MainResourceAcquired = FALSE;
_SEH2_TRY {
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_INVALID_DEVICE_REQUEST;
_SEH2_LEAVE;
}
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb));
if (IsVcbReadOnly(Vcb)) {
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpContext->FileObject;
FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
ASSERT(FcbOrVcb != NULL);
Ccb = (PEXT2_CCB) FileObject->FsContext2;
if (Ccb == NULL) {
Status = STATUS_SUCCESS;
_SEH2_LEAVE;
}
MainResourceAcquired =
ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
ASSERT(MainResourceAcquired);
DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
if (FcbOrVcb->Identifier.Type == EXT2VCB) {
Ext2VerifyVcb(IrpContext, Vcb);
Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status)) {
_SEH2_LEAVE;
}
Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
}
} else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
Fcb = (PEXT2_FCB)(FcbOrVcb);
Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
if (NT_SUCCESS(Status)) {
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
}
}
}
DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
} _SEH2_FINALLY {
if (MainResourceAcquired) {
ExReleaseResourceLite(&FcbOrVcb->MainResource);
}
if (!IrpContext->ExceptionInProgress) {
if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {
// Call the disk driver to flush the physial media.
NTSTATUS DriverStatus;
PIO_STACK_LOCATION NextIrpSp;
NextIrpSp = IoGetNextIrpStackLocation(Irp);
*NextIrpSp = *IrpSp;
IoSetCompletionRoutine( Irp,
Ext2FlushCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE );
DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
Status : DriverStatus;
IrpContext->Irp = Irp = NULL;
}
Ext2CompleteIrpContext(IrpContext, Status);
}
} _SEH2_END;
return Status;
}

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more