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

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

View file

@ -1,7 +1,6 @@
add_subdirectory(cdfs)
add_subdirectory(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)

View file

@ -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)

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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