mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +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(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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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
|
@ -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
Loading…
Reference in a new issue