mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[EXT2]
[EXT2_NEW] Get rid of old ext2 driver and use new one svn path=/trunk/; revision=69576
This commit is contained in:
parent
5a9b98b776
commit
b9b583fd22
148 changed files with 8619 additions and 20167 deletions
|
@ -1,7 +1,6 @@
|
|||
|
||||
add_subdirectory(cdfs)
|
||||
add_subdirectory(ext2)
|
||||
#add_subdirectory(ext2_new)
|
||||
add_subdirectory(fastfat)
|
||||
#add_subdirectory(fastfat_new)
|
||||
add_subdirectory(fs_rec)
|
||||
|
@ -10,3 +9,4 @@ add_subdirectory(mup)
|
|||
add_subdirectory(npfs)
|
||||
add_subdirectory(ntfs)
|
||||
add_subdirectory(udfs)
|
||||
add_subdirectory(registryfs)
|
||||
|
|
|
@ -1,35 +1,105 @@
|
|||
|
||||
include_directories(inc)
|
||||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers
|
||||
inc)
|
||||
|
||||
list(APPEND SOURCE
|
||||
src/volinfo.c
|
||||
src/create.c
|
||||
src/write.c
|
||||
src/metadata.c
|
||||
src/fastio.c
|
||||
src/dircntrl.c
|
||||
src/DiskIO.c
|
||||
src/fsctrl.c
|
||||
src/devcntrl.c
|
||||
src/flush.c
|
||||
src/ext2init.c
|
||||
src/io.c
|
||||
src/close.c
|
||||
src/fileinfo.c
|
||||
src/read.c
|
||||
src/init.c
|
||||
src/ext3/generic.c
|
||||
src/ext3/htree.c
|
||||
src/ext3/indirect.c
|
||||
src/ext3/recover.c
|
||||
src/ext4/ext4_bh.c
|
||||
src/ext4/ext4_extents.c
|
||||
src/ext4/ext4_jbd2.c
|
||||
src/ext4/extents.c
|
||||
src/jbd/recovery.c
|
||||
src/jbd/replay.c
|
||||
src/jbd/revoke.c
|
||||
src/nls/nls_ascii.c
|
||||
src/nls/nls_base.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/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/nls.c
|
||||
src/pnp.c
|
||||
src/rbtree.c
|
||||
src/read.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"))
|
||||
add_target_compile_flags(ext2fs "-Wno-unused-but-set-variable")
|
||||
if(NOT MSVC)
|
||||
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()
|
||||
|
||||
target_link_libraries(ext2fs ${PSEH_LIB})
|
||||
add_pch(ext2fs inc/ext2fsd.h SOURCE)
|
||||
target_link_libraries(ext2fs memcmp ${PSEH_LIB})
|
||||
add_definitions(-D__KERNEL__ -D_X86_)
|
||||
set_module_type(ext2fs kernelmodedriver)
|
||||
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)
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// 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
|
||||
//
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_RESOURCE_VALUE 104
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
|
|
|
@ -1,398 +1,389 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: cleanup.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* 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
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
/*
|
||||
* COPYRIGHT: See COPYRIGHT.TXT
|
||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||
* FILE: cleanup.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://www.ext2fsd.com
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_CLEANUP
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_CLEANUP)
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* GLOBALS ***************************************************************/
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2Cleanup()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a cleanup
|
||||
* 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
|
||||
extern PEXT2_GLOBAL Ext2Global;
|
||||
|
||||
/* DEFINITIONS *************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
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();
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
BOOLEAN VcbResourceAcquired = FALSE;
|
||||
BOOLEAN FcbResourceAcquired = FALSE;
|
||||
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
|
||||
_SEH2_TRY {
|
||||
|
||||
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
|
||||
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
|
||||
ASSERT(PtrIrpContext);
|
||||
DeviceObject = IrpContext->DeviceObject;
|
||||
if (IsExt2FsDevice(DeviceObject)) {
|
||||
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)));
|
||||
|
||||
}
|
||||
except( Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation() ) )
|
||||
{
|
||||
if (!IsVcbInited(Vcb)) {
|
||||
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)
|
||||
{
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
VcbResourceAcquired =
|
||||
ExAcquireResourceExclusiveLite(
|
||||
&Vcb->MainResource,
|
||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
|
||||
);
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
if (Fcb->Identifier.Type == EXT2VCB) {
|
||||
|
||||
return(RC);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2CommonCleanup()
|
||||
*
|
||||
* 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 Ext2CommonCleanup(
|
||||
PtrExt2IrpContext PtrIrpContext,
|
||||
PIRP PtrIrp,
|
||||
BOOLEAN FirstAttempt )
|
||||
{
|
||||
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
|
||||
PFILE_OBJECT PtrFileObject = NULL;
|
||||
PtrExt2FCB PtrFCB = NULL;
|
||||
PtrExt2CCB PtrCCB = NULL;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
|
||||
PERESOURCE PtrResourceAcquired = NULL;
|
||||
|
||||
BOOLEAN CompleteIrp = TRUE;
|
||||
BOOLEAN PostRequest = FALSE;
|
||||
BOOLEAN AcquiredVCB = FALSE;
|
||||
BOOLEAN BlockForResource;
|
||||
int i = 1;
|
||||
|
||||
try
|
||||
{
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
|
||||
PtrFileObject = PtrIoStackLocation->FileObject;
|
||||
ASSERT(PtrFileObject);
|
||||
|
||||
if( !PtrFileObject->FsContext2 )
|
||||
{
|
||||
// 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_MISC, " === Cleanup with NULL CCB", 0);
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
try_return();
|
||||
}
|
||||
|
||||
|
||||
Ext2GetFCB_CCB_VCB_FromFileObject (
|
||||
PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
|
||||
|
||||
if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
|
||||
//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_FILE_NAME, " === Cleanup Volume", 0);
|
||||
}
|
||||
|
||||
|
||||
PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
|
||||
ASSERT(PtrVCB);
|
||||
ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
|
||||
|
||||
// (a) Acquiring the VCBResource Exclusively...
|
||||
// This is done to synchronise with the close and cleanup routines...
|
||||
BlockForResource = !FirstAttempt;
|
||||
if( !FirstAttempt )
|
||||
{
|
||||
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Going into a block to acquire VCB Exclusively [Cleanup]", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire VCB Exclusively [Cleanup]", 0);
|
||||
}
|
||||
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
|
||||
i = 1;
|
||||
while( !AcquiredVCB )
|
||||
{
|
||||
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 ) )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquisition FAILED [Cleanup]", 0);
|
||||
if( BlockForResource && i != 1000 )
|
||||
{
|
||||
LARGE_INTEGER Delay;
|
||||
Delay.QuadPart = -500 * i;
|
||||
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i == 1000 )
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 );
|
||||
PostRequest = TRUE;
|
||||
try_return( RC = STATUS_PENDING );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** VCB Acquired in [Cleanup]", 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_RESOURCE_ACQUIRE, "*** Going into a block to acquire FCB Exclusively [Cleanup]", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** Attempting to acquire FCB Exclusively [Cleanup]", 0);
|
||||
}
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
|
||||
i = 1;
|
||||
while( !PtrResourceAcquired )
|
||||
{
|
||||
PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
|
||||
DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
|
||||
if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB Acquisition FAILED [Cleanup]", 0);
|
||||
if( BlockForResource && i != 1000 )
|
||||
{
|
||||
LARGE_INTEGER Delay;
|
||||
Delay.QuadPart = -500 * i;
|
||||
KeDelayExecutionThread( KernelMode, FALSE, &Delay );
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Retrying... after 50 * %ld ms [Cleanup]", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i == 1000 )
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RETRY, "*** Reposting... [Cleanup]", 0 );
|
||||
PostRequest = TRUE;
|
||||
try_return( RC = STATUS_PENDING );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_ACQUIRE, "*** FCB acquired [Cleanup]", 0);
|
||||
PtrResourceAcquired = & ( PtrFCB->NTRequiredFCB.MainResource );
|
||||
}
|
||||
i *= 10;
|
||||
}
|
||||
|
||||
// (c) Flush file data to disk
|
||||
if ( PtrFileObject->PrivateCacheMap != NULL)
|
||||
{
|
||||
IO_STATUS_BLOCK Status;
|
||||
CcFlushCache( PtrFileObject->SectionObjectPointer, NULL, 0, &Status );
|
||||
}
|
||||
|
||||
// (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)
|
||||
|
||||
// (g) Attempting to update time stamp values
|
||||
// Errors are ignored...
|
||||
// Not considered as critical errors...
|
||||
|
||||
/*
|
||||
if( PtrFCB->OpenHandleCount == 1 )
|
||||
{
|
||||
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( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// (h) Inform the Cache Manager to uninitialize Cache Maps ...
|
||||
CcUninitializeCacheMap( PtrFileObject, NULL, NULL );
|
||||
|
||||
// (i) Decrementing the Open Handle count...
|
||||
if( PtrFCB->OpenHandleCount )
|
||||
{
|
||||
InterlockedDecrement( &PtrFCB->OpenHandleCount );
|
||||
}
|
||||
else
|
||||
{
|
||||
Ext2BreakPoint();
|
||||
}
|
||||
|
||||
PtrFCB->FCBFlags |= FO_CLEANUP_COMPLETE;
|
||||
|
||||
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^ReferenceCount = 0x%lX [Cleanup]", PtrFCB->ReferenceCount );
|
||||
DebugTrace(DEBUG_TRACE_REFERENCE, "^^^^^OpenHandleCount = 0x%lX [Cleanup]", PtrFCB->OpenHandleCount );
|
||||
|
||||
// (j) Remove share access...
|
||||
// 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) &&
|
||||
!PtrFCB->OpenHandleCount )
|
||||
{
|
||||
//
|
||||
// Have to delete this file...
|
||||
//
|
||||
Ext2DeleteFile( PtrFCB, PtrIrpContext );
|
||||
PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart = 0;
|
||||
PtrFCB->INodeNo = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This must be a volume close...
|
||||
// Just go ahead and complete this IRP...
|
||||
PtrVCB->VCBOpenCount--;
|
||||
DebugTrace(DEBUG_TRACE_MISC, "VCB Cleanup Requested !!!", 0);
|
||||
CompleteIrp = TRUE;
|
||||
}
|
||||
|
||||
try_return();
|
||||
|
||||
try_exit: NOTHING;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(PtrResourceAcquired)
|
||||
{
|
||||
Ext2ReleaseResource(PtrResourceAcquired);
|
||||
DebugTrace(DEBUG_TRACE_RESOURCE_RELEASE, "*** Resource Released [Cleanup]", 0);
|
||||
DebugTraceState( "Resource AC:0x%LX SW:0x%LX EX:0x%LX [Cleanup]",
|
||||
PtrResourceAcquired->ActiveCount,
|
||||
PtrResourceAcquired->NumberOfExclusiveWaiters,
|
||||
PtrResourceAcquired->NumberOfSharedWaiters );
|
||||
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( AcquiredVCB )
|
||||
{
|
||||
ASSERT(PtrVCB);
|
||||
Ext2ReleaseResource(&(PtrVCB->VCBResource));
|
||||
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( PtrFileObject )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_OBJ, "###### File Pointer 0x%LX [Cleanup]", PtrFileObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( PostRequest )
|
||||
{
|
||||
RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
|
||||
}
|
||||
if( RC != STATUS_PENDING )
|
||||
{
|
||||
Ext2ReleaseIrpContext( PtrIrpContext );
|
||||
// complete the IRP
|
||||
IoCompleteRequest( PtrIrp, IO_DISK_INCREMENT );
|
||||
}
|
||||
} // end of "finally" processing
|
||||
|
||||
return(RC);
|
||||
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
||||
Vcb->LockFile == FileObject ){
|
||||
|
||||
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
|
||||
Vcb->LockFile = NULL;
|
||||
Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
|
||||
}
|
||||
|
||||
if (Ccb) {
|
||||
Ext2DerefXcb(&Vcb->OpenHandleCount);
|
||||
Ext2DerefXcb(&Vcb->OpenVolumeCount);
|
||||
}
|
||||
|
||||
IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||
|
||||
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
|
||||
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
|
||||
IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
|
||||
!IsVcbReadOnly(Vcb) ) {
|
||||
Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
|
||||
}
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
if (Ccb == NULL) {
|
||||
Status = STATUS_SUCCESS;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
if (IsDirectory(Fcb)) {
|
||||
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
|
||||
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
||||
|
||||
FsRtlNotifyFullChangeDirectory(
|
||||
Vcb->NotifySync,
|
||||
&Vcb->NotifyList,
|
||||
Ccb,
|
||||
NULL,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL );
|
||||
}
|
||||
|
||||
FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
|
||||
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&Vcb->MainResource);
|
||||
VcbResourceAcquired = FALSE;
|
||||
|
||||
FcbResourceAcquired =
|
||||
ExAcquireResourceExclusiveLite(
|
||||
&Fcb->MainResource,
|
||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
|
||||
);
|
||||
|
||||
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
|
||||
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
|
||||
|
||||
Ext2DerefXcb(&Vcb->OpenHandleCount);
|
||||
Ext2DerefXcb(&Fcb->OpenHandleCount);
|
||||
|
||||
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
|
||||
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
|
||||
if (IsDirectory(Fcb)) {
|
||||
|
||||
ext3_release_dir(Fcb->Inode, &Ccb->filp);
|
||||
|
||||
} else {
|
||||
|
||||
if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
|
||||
!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
|
||||
|
||||
LARGE_INTEGER SysTime;
|
||||
KeQuerySystemTime(&SysTime);
|
||||
|
||||
Fcb->Inode->i_atime =
|
||||
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
|
||||
Fcb->Mcb->LastAccessTime =
|
||||
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);
|
||||
|
||||
Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
|
||||
|
||||
Ext2NotifyReportChange(
|
||||
IrpContext,
|
||||
Vcb,
|
||||
Fcb->Mcb,
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||
FILE_NOTIFY_CHANGE_LAST_ACCESS,
|
||||
FILE_ACTION_MODIFIED );
|
||||
}
|
||||
|
||||
FsRtlCheckOplock( &Fcb->Oplock,
|
||||
Irp,
|
||||
IrpContext,
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
|
||||
|
||||
if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
|
||||
Fcb->NonCachedOpenCount--;
|
||||
}
|
||||
|
||||
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
|
||||
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
||||
}
|
||||
|
||||
//
|
||||
// Drop any byte range locks this process may have on the file.
|
||||
//
|
||||
|
||||
FsRtlFastUnlockAll(
|
||||
&Fcb->FileLockAnchor,
|
||||
FileObject,
|
||||
IoGetRequestorProcess(Irp),
|
||||
NULL );
|
||||
|
||||
//
|
||||
// If there are no byte range locks owned by other processes on the
|
||||
// file the fast I/O read/write functions doesn't have to check for
|
||||
// locks so we set IsFastIoPossible to FastIoIsPossible again.
|
||||
//
|
||||
if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
|
||||
if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
|
||||
#if EXT2_DEBUG
|
||||
DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
|
||||
Ext2GetCurrentProcessName(),
|
||||
"FastIoIsPossible",
|
||||
&Fcb->Mcb->FullName
|
||||
));
|
||||
#endif
|
||||
|
||||
Fcb->Header.IsFastIoPossible = FastIoIsPossible;
|
||||
}
|
||||
}
|
||||
|
||||
if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE |
|
||||
FCB_ALLOC_IN_SETINFO) ){
|
||||
|
||||
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) {
|
||||
if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) {
|
||||
if (!INODE_HAS_EXTENT(Fcb->Inode)) {
|
||||
#if EXT2_PRE_ALLOCATION_SUPPORT
|
||||
CcZeroData(FileObject, &Fcb->Header.ValidDataLength,
|
||||
&Fcb->Header.AllocationSize, TRUE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
|
||||
|
||||
LARGE_INTEGER Size;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
|
||||
FcbPagingIoResourceAcquired = TRUE;
|
||||
|
||||
Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
|
||||
(ULONGLONG)Fcb->Mcb->Inode.i_size,
|
||||
(ULONGLONG)BLOCK_SIZE);
|
||||
if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
||||
|
||||
Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
|
||||
Fcb->Header.AllocationSize = Size;
|
||||
Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
|
||||
if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart)
|
||||
Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
|
||||
if (CcIsFileCached(FileObject)) {
|
||||
CcSetFileSizes(FileObject,
|
||||
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
||||
}
|
||||
}
|
||||
ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO);
|
||||
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
||||
FcbPagingIoResourceAcquired = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
||||
|
||||
if (Fcb->OpenHandleCount == 0 || (Mcb = Ccb->SymLink)) {
|
||||
|
||||
//
|
||||
// Ext2DeleteFile will acquire these lock inside
|
||||
//
|
||||
|
||||
if (FcbResourceAcquired) {
|
||||
ExReleaseResourceLite(&Fcb->MainResource);
|
||||
FcbResourceAcquired = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// this file is to be deleted ...
|
||||
//
|
||||
if (Ccb->SymLink) {
|
||||
Mcb = Ccb->SymLink;
|
||||
FileObject->DeletePending = FALSE;
|
||||
}
|
||||
|
||||
Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
if (IsMcbDirectory(Mcb)) {
|
||||
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME,
|
||||
FILE_ACTION_REMOVED );
|
||||
} else {
|
||||
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME,
|
||||
FILE_ACTION_REMOVED );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// re-acquire the main resource lock
|
||||
//
|
||||
|
||||
FcbResourceAcquired =
|
||||
ExAcquireResourceExclusiveLite(
|
||||
&Fcb->MainResource,
|
||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
|
||||
);
|
||||
|
||||
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
||||
if (CcIsFileCached(FileObject)) {
|
||||
CcSetFileSizes(FileObject,
|
||||
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsDirectory(Fcb)) {
|
||||
|
||||
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
|
||||
(Fcb->NonCachedOpenCount + 1 == Fcb->ReferenceCount) &&
|
||||
(Fcb->SectionObject.DataSectionObject != NULL)) {
|
||||
|
||||
if (!IsVcbReadOnly(Vcb)) {
|
||||
CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
|
||||
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
||||
}
|
||||
|
||||
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
|
||||
ExReleaseResourceLite(&(Fcb->PagingIoResource));
|
||||
}
|
||||
|
||||
CcPurgeCacheSection( &Fcb->SectionObject,
|
||||
NULL,
|
||||
0,
|
||||
FALSE );
|
||||
}
|
||||
|
||||
CcUninitializeCacheMap(FileObject, NULL, NULL);
|
||||
}
|
||||
|
||||
IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
|
||||
|
||||
DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
|
||||
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
if (FileObject) {
|
||||
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
|
||||
}
|
||||
|
||||
} _SEH2_FINALLY {
|
||||
|
||||
if (FcbPagingIoResourceAcquired) {
|
||||
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
||||
}
|
||||
|
||||
if (FcbResourceAcquired) {
|
||||
ExReleaseResourceLite(&Fcb->MainResource);
|
||||
}
|
||||
|
||||
if (VcbResourceAcquired) {
|
||||
ExReleaseResourceLite(&Vcb->MainResource);
|
||||
}
|
||||
|
||||
if (!IrpContext->ExceptionInProgress) {
|
||||
if (Status == STATUS_PENDING) {
|
||||
Ext2QueueRequest(IrpContext);
|
||||
} else {
|
||||
IrpContext->Irp->IoStatus.Status = Status;
|
||||
Ext2CompleteIrpContext(IrpContext, Status);
|
||||
}
|
||||
}
|
||||
} _SEH2_END;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -1,515 +1,282 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: close.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* 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
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
/*
|
||||
* COPYRIGHT: See COPYRIGHT.TXT
|
||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||
* FILE: close.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://www.ext2fsd.com
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_CLOSE
|
||||
#include "ext2fs.h"
|
||||
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_CLOSE)
|
||||
/* GLOBALS ***************************************************************/
|
||||
|
||||
extern PEXT2_GLOBAL Ext2Global;
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2Close()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a close
|
||||
* 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 Ext2Close(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp) // I/O Request Packet
|
||||
/* DEFINITIONS *************************************************************/
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, Ext2QueueCloseRequest)
|
||||
#pragma alloc_text(PAGE, Ext2DeQueueCloseRequest)
|
||||
#endif
|
||||
|
||||
NTSTATUS
|
||||
Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
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);
|
||||
ASSERT(Irp);
|
||||
DeviceObject = IrpContext->DeviceObject;
|
||||
if (IsExt2FsDevice(DeviceObject)) {
|
||||
Status = STATUS_SUCCESS;
|
||||
Vcb = NULL;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
|
||||
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
||||
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
|
||||
PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
|
||||
ASSERT(PtrIrpContext);
|
||||
Status = STATUS_PENDING;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation()))
|
||||
{
|
||||
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
|
||||
|
||||
RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
|
||||
Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
|
||||
}
|
||||
FileObject = NULL;
|
||||
Fcb = IrpContext->Fcb;
|
||||
Ccb = IrpContext->Ccb;
|
||||
|
||||
if (AreWeTopLevel)
|
||||
{
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
} else {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* 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 )
|
||||
VOID
|
||||
Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION PtrIoStackLocation = NULL;
|
||||
PFILE_OBJECT PtrFileObject = NULL;
|
||||
PtrExt2FCB PtrFCB = NULL;
|
||||
PtrExt2CCB PtrCCB = NULL;
|
||||
PtrExt2VCB PtrVCB = NULL;
|
||||
PtrExt2NTRequiredFCB PtrReqdFCB = NULL;
|
||||
PERESOURCE PtrResourceAcquired = NULL;
|
||||
PERESOURCE PtrPagingIoResourceAcquired = NULL;
|
||||
ASSERT(IrpContext);
|
||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||
|
||||
BOOLEAN CompleteIrp = TRUE;
|
||||
BOOLEAN PostRequest = FALSE;
|
||||
BOOLEAN AcquiredVCB = FALSE;
|
||||
BOOLEAN BlockForResource;
|
||||
int i = 1;
|
||||
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
|
||||
|
||||
try
|
||||
{
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) {
|
||||
Ext2Sleep(500); /* 0.5 sec*/
|
||||
} else {
|
||||
Ext2Sleep(50); /* 0.05 sec*/
|
||||
}
|
||||
|
||||
PtrFileObject = PtrIoStackLocation->FileObject;
|
||||
ASSERT(PtrFileObject);
|
||||
} else {
|
||||
|
||||
if( !PtrFileObject->FsContext2 )
|
||||
{
|
||||
// This must be a Cleanup request received
|
||||
// as a result of IoCreateStreamFileObject
|
||||
// Only such a File object would have a NULL CCB
|
||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
|
||||
|
||||
DebugTrace( DEBUG_TRACE_SPECIAL, " === Close with NULL CCB", 0);
|
||||
if( PtrFileObject )
|
||||
{
|
||||
DebugTrace( DEBUG_TRACE_SPECIAL, "###### File Pointer 0x%LX [Close]", PtrFileObject);
|
||||
}
|
||||
try_return();
|
||||
}
|
||||
IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext;
|
||||
IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2;
|
||||
}
|
||||
|
||||
// Get the FCB and CCB pointers
|
||||
ExInitializeWorkItem(
|
||||
&IrpContext->WorkQueueItem,
|
||||
Ext2DeQueueCloseRequest,
|
||||
IrpContext);
|
||||
|
||||
Ext2GetFCB_CCB_VCB_FromFileObject (
|
||||
PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
|
||||
|
||||
PtrVCB = (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
|
||||
ASSERT( PtrVCB );
|
||||
|
||||
if( PtrFCB && PtrFCB->FCBName && PtrFCB->FCBName->ObjectName.Length && PtrFCB->FCBName->ObjectName.Buffer )
|
||||
//if( PtrFileObject->FileName.Length && PtrFileObject->FileName.Buffer )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -%S-", PtrFCB->FCBName->ObjectName.Buffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_FILE_NAME, " === Close File Name : -null-", 0);
|
||||
}
|
||||
|
||||
// (a) Acquiring the VCBResource Exclusively...
|
||||
// This is done to synchronise with the close and cleanup routines...
|
||||
// if( ExTryToAcquireResourceExclusiveLite(&(PtrVCB->VCBResource) ) )
|
||||
|
||||
BlockForResource = !FirstAttempt;
|
||||
if( !FirstAttempt )
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire VCB Exclusively [Close]", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire VCB Exclusively [Close]", 0);
|
||||
}
|
||||
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);
|
||||
ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue);
|
||||
}
|
||||
|
||||
VOID NTAPI
|
||||
Ext2DeQueueCloseRequest (IN PVOID Context)
|
||||
{
|
||||
PEXT2_IRP_CONTEXT IrpContext;
|
||||
|
||||
IrpContext = (PEXT2_IRP_CONTEXT) Context;
|
||||
ASSERT(IrpContext);
|
||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||
|
||||
_SEH2_TRY {
|
||||
|
||||
_SEH2_TRY {
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
Ext2Close(IrpContext);
|
||||
|
||||
} _SEH2_EXCEPT (Ext2ExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
|
||||
|
||||
Ext2ExceptionHandler(IrpContext);
|
||||
} _SEH2_END;
|
||||
|
||||
} _SEH2_FINALLY {
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
} _SEH2_END;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -62,8 +62,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,0,0,3
|
||||
PRODUCTVERSION 0,0,0,3
|
||||
FILEVERSION 0,6,2,0
|
||||
PRODUCTVERSION 0,6,2,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x29L
|
||||
|
@ -81,14 +81,14 @@ BEGIN
|
|||
VALUE "Comments", "Ext2 File System Driver\0"
|
||||
VALUE "CompanyName", "Purayidathil\0"
|
||||
VALUE "FileDescription", "Ext2 File System Driver\0"
|
||||
VALUE "FileVersion", "0, 0, 0, 3\0"
|
||||
VALUE "InternalName", "ext2.sys\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2002 Manoj Paul Joseph\0"
|
||||
VALUE "FileVersion", "0, 6, 2, 0\0"
|
||||
VALUE "InternalName", "ext2fs.sys\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2015 Matt Wu\0"
|
||||
VALUE "LegalTrademarks", " - \0"
|
||||
VALUE "OriginalFilename", "ext2.sys\0"
|
||||
VALUE "OriginalFilename", "ext2fs.sys\0"
|
||||
VALUE "PrivateBuild", " - \0"
|
||||
VALUE "ProductName", "Ext2 File System Driver for Windows NT\0"
|
||||
VALUE "ProductVersion", "0, 0, 0, 3\0"
|
||||
VALUE "ProductName", "Ext2 File System Driver for Windows\0"
|
||||
VALUE "ProductVersion", "0, 6, 2, 0\0"
|
||||
VALUE "SpecialBuild", " - \0"
|
||||
END
|
||||
END
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,346 +1,268 @@
|
|||
/*************************************************************************
|
||||
*
|
||||
* File: flush.c
|
||||
*
|
||||
* Module: Ext2 File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains code to handle the "Flush Buffers" dispatch entry point.
|
||||
*
|
||||
* Author: Manoj Paul Joseph
|
||||
*
|
||||
*
|
||||
*************************************************************************/
|
||||
/*
|
||||
* COPYRIGHT: See COPYRIGHT.TXT
|
||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||
* FILE: flush.c
|
||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||
* HOMEPAGE: http://www.ext2fsd.com
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
#include "ext2fsd.h"
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define EXT2_BUG_CHECK_ID EXT2_FILE_FLUSH
|
||||
#include "ext2fs.h"
|
||||
|
||||
#define DEBUG_LEVEL (DEBUG_TRACE_FLUSH)
|
||||
/* GLOBALS ***************************************************************/
|
||||
|
||||
extern PEXT2_GLOBAL Ext2Global;
|
||||
|
||||
/* DEFINITIONS *************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2Flush()
|
||||
*
|
||||
* Description:
|
||||
* 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 NTAPI
|
||||
Ext2FlushCompletionRoutine (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context )
|
||||
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrExt2IrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
if (Irp->PendingReturned)
|
||||
IoMarkIrpPending( Irp );
|
||||
|
||||
DebugTrace(DEBUG_TRACE_IRP_ENTRY, "Flush IRP Received...", 0);
|
||||
|
||||
// Ext2BreakPoint();
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
// set the top level context
|
||||
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);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2CommonFlush()
|
||||
*
|
||||
* 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
|
||||
Ext2FlushFiles(
|
||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||
IN PEXT2_VCB Vcb,
|
||||
IN BOOLEAN bShutDown
|
||||
)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
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;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
try {
|
||||
// First, get a pointer to the current I/O stack location
|
||||
PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
|
||||
ASSERT(PtrIoStackLocation);
|
||||
PEXT2_FCB Fcb;
|
||||
PLIST_ENTRY ListEntry;
|
||||
|
||||
PtrFileObject = PtrIoStackLocation->FileObject;
|
||||
ASSERT(PtrFileObject);
|
||||
if (IsVcbReadOnly(Vcb)) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Get the FCB and CCB pointers
|
||||
PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2);
|
||||
ASSERT(PtrCCB);
|
||||
PtrFCB = PtrCCB->PtrFCB;
|
||||
AssertFCB( PtrFCB );
|
||||
IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/*ASSERT(PtrFCB);
|
||||
ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB );*/
|
||||
DEBUG(DL_INF, ( "Flushing Files ...\n"));
|
||||
|
||||
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
|
||||
CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
|
||||
Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
|
||||
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.
|
||||
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);
|
||||
return IoStatus.Status;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2FlushAFile()
|
||||
*
|
||||
* Description:
|
||||
* 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)
|
||||
NTSTATUS
|
||||
Ext2FlushVolume (
|
||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||
IN PEXT2_VCB Vcb,
|
||||
IN BOOLEAN bShutDown
|
||||
)
|
||||
{
|
||||
CcFlushCache(&(PtrReqdFCB->SectionObject), NULL, 0, PtrIoStatus);
|
||||
return;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
|
||||
|
||||
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
||||
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
||||
|
||||
CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
|
||||
|
||||
return IoStatus.Status;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: Ext2FlushLogicalVolume()
|
||||
*
|
||||
* Description:
|
||||
* 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)
|
||||
NTSTATUS
|
||||
Ext2FlushFile (
|
||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||
IN PEXT2_FCB Fcb,
|
||||
IN PEXT2_CCB Ccb
|
||||
)
|
||||
{
|
||||
BOOLEAN AcquiredVCB = FALSE;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
try {
|
||||
ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE);
|
||||
ASSERT(Fcb != NULL);
|
||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||
|
||||
AcquiredVCB = TRUE;
|
||||
DebugTrace(DEBUG_TRACE_MISC, "*** VCB Acquired Ex [Flush] ", 0);
|
||||
/* update timestamp and achieve attribute */
|
||||
if (Ccb != NULL) {
|
||||
|
||||
// Go through the list of FCB's. You would probably
|
||||
// flush all of the files. Then, you could flush the
|
||||
// directories that you may have have pinned into memory.
|
||||
if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
|
||||
|
||||
// NOTE: This function may also be invoked internally as part of
|
||||
// processing a shutdown request.
|
||||
LARGE_INTEGER SysTime;
|
||||
KeQuerySystemTime(&SysTime);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
|
||||
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
|
||||
Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* 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)
|
||||
NTSTATUS
|
||||
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||
{
|
||||
if (PtrIrp->PendingReturned) {
|
||||
IoMarkIrpPending(PtrIrp);
|
||||
}
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if (PtrIrp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) {
|
||||
// cannot do much here, can we?
|
||||
PtrIrp->IoStatus.Status = STATUS_SUCCESS;
|
||||
}
|
||||
PIRP Irp = NULL;
|
||||
PIO_STACK_LOCATION IrpSp = NULL;
|
||||
|
||||
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
Loading…
Reference in a new issue