FsRtlPrepareMdlWriteDev()
FsRtlMdlWriteCompleteDev()
FsRtlPrepareMdlWrite()
FsRtlMdlWriteComplete()

svn path=/trunk/; revision=25910
This commit is contained in:
Dominique Cote 2007-02-26 20:22:55 +00:00
parent 35f897c768
commit 982855b6e3
3 changed files with 368 additions and 46 deletions

View file

@ -133,14 +133,16 @@ CcMdlWriteComplete(IN PFILE_OBJECT FileObject,
} }
/* Use slow path */ /* Use slow path */
CcMdlWriteCompleteDev(FileOffset, MdlChain, FileObject); CcMdlWriteComplete2(FileObject,FileOffset, MdlChain);
} }
VOID VOID
STDCALL NTAPI
CcMdlWriteCompleteDev(IN PLARGE_INTEGER FileOffset, CcMdlWriteComplete2(
IN PMDL MdlChain, IN PFILE_OBJECT FileObject,
IN PFILE_OBJECT FileObject) IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain
)
{ {
UNIMPLEMENTED; UNIMPLEMENTED;
} }

View file

@ -3,7 +3,7 @@
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/fsrtl/fastio.c * FILE: ntoskrnl/fsrtl/fastio.c
* PURPOSE: Provides Fast I/O entrypoints to the Cache Manager * PURPOSE: Provides Fast I/O entrypoints to the Cache Manager
* PROGRAMMERS: None. * PROGRAMMERS: buzdelabuz2@gmail.com,alex.ionescu@reactos.org
*/ */
/* INCLUDES ******************************************************************/ /* INCLUDES ******************************************************************/
@ -196,7 +196,8 @@ FsRtlCopyRead(IN PFILE_OBJECT FileObject,
/* Set this as top-level IRP */ /* Set this as top-level IRP */
PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
_SEH_TRY { _SEH_TRY
{
/* Make sure the IO and file size is below 4GB */ /* Make sure the IO and file size is below 4GB */
if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart )) { if (Wait && !(Offset.HighPart | FcbHeader->FileSize.HighPart )) {
@ -226,7 +227,8 @@ FsRtlCopyRead(IN PFILE_OBJECT FileObject,
FileObject->CurrentByteOffset.QuadPart += IoStatus->Information; FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
} }
} }
_SEH_EXCEPT(FsRtlCcCopyFilter) { _SEH_EXCEPT(FsRtlCcCopyFilter)
{
Result = FALSE; Result = FALSE;
} _SEH_END; } _SEH_END;
@ -365,13 +367,16 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
(FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) && (FcbHeader->AllocationSize.LowPart >= NewSize.LowPart) &&
(FcbHeader->AllocationSize.HighPart == 0) && (FcbHeader->AllocationSize.HighPart == 0) &&
!b_4GB !b_4GB
) { )
} else { {
} else
{
goto FailAndCleanup; goto FailAndCleanup;
} }
} }
}else { }else
{
goto FailAndCleanup; goto FailAndCleanup;
} }
@ -419,7 +424,8 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
/* Set this as top-level IRP */ /* Set this as top-level IRP */
PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
_SEH_TRY { _SEH_TRY
{
if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart) { if (Offset.LowPart > FcbHeader->ValidDataLength.LowPart) {
LARGE_INTEGER OffsetVar; LARGE_INTEGER OffsetVar;
OffsetVar.LowPart = Offset.LowPart; OffsetVar.LowPart = Offset.LowPart;
@ -430,7 +436,8 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
/* Call the cache manager */ /* Call the cache manager */
CcFastCopyWrite(FileObject,Offset.LowPart,Length,Buffer); CcFastCopyWrite(FileObject,Offset.LowPart,Length,Buffer);
} }
_SEH_EXCEPT(FsRtlCcCopyFilter) { _SEH_EXCEPT(FsRtlCcCopyFilter)
{
Result = FALSE; Result = FALSE;
} _SEH_END; } _SEH_END;
@ -493,13 +500,13 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
{ {
/* Acquire the resource shared */ /* Acquire the resource shared */
if (!ExAcquireResourceSharedLite(FcbHeader->Resource,Wait)) { if (!ExAcquireResourceSharedLite(FcbHeader->Resource,Wait)) {
goto FailAndCleanup; goto LeaveCriticalAndFail;
} }
ResourceAquiredShared =TRUE; ResourceAquiredShared =TRUE;
} else { } else {
/* Acquire the resource exclusive */ /* Acquire the resource exclusive */
if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait)) { if (!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait)) {
goto FailAndCleanup; goto LeaveCriticalAndFail;
} }
} }
@ -528,7 +535,8 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
/* Check if we can keep the lock shared */ /* Check if we can keep the lock shared */
if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) { if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) {
ExReleaseResourceLite(FcbHeader->Resource); ExReleaseResourceLite(FcbHeader->Resource);
if(!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait)) { if(!ExAcquireResourceExclusiveLite(FcbHeader->Resource,Wait))
{
goto LeaveCriticalAndFail; goto LeaveCriticalAndFail;
} }
@ -542,7 +550,8 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
if ( (FileObject->PrivateCacheMap != NULL) && if ( (FileObject->PrivateCacheMap != NULL) &&
(FcbHeader->IsFastIoPossible != FastIoIsNotPossible) && (FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
(FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart) (FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
) { )
{
/* Do nothing */ /* Do nothing */
} else { } else {
goto FailAndCleanup; goto FailAndCleanup;
@ -600,7 +609,8 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
/* Nagar p.544 */ /* Nagar p.544 */
/* Set ourselves as top component */ /* Set ourselves as top component */
PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP; PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
_SEH_TRY { _SEH_TRY
{
BOOLEAN CallCc = TRUE; BOOLEAN CallCc = TRUE;
/* Check if there is a gap between the end of the file and the offset /* Check if there is a gap between the end of the file and the offset
If yes, then we have to zero the data If yes, then we have to zero the data
@ -619,7 +629,8 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
if (CallCc) { if (CallCc) {
Result = CcCopyWrite(FileObject,&Offset,Length, Wait, Buffer); Result = CcCopyWrite(FileObject,&Offset,Length, Wait, Buffer);
} }
}_SEH_EXCEPT(FsRtlCcCopyFilter) { }_SEH_EXCEPT(FsRtlCcCopyFilter)
{
Result = FALSE; Result = FALSE;
} _SEH_END; } _SEH_END;
@ -637,6 +648,7 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
} else { } else {
FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart; FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
} }
}
/* Flag the file as modified */ /* Flag the file as modified */
FileObject->Flags |= FO_FILE_MODIFIED; FileObject->Flags |= FO_FILE_MODIFIED;
@ -649,7 +661,6 @@ FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
/* Update the current FO byte offset */ /* Update the current FO byte offset */
FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart; FileObject->CurrentByteOffset.QuadPart = NewSize.QuadPart;
} }
}
else else
{ {
/* The operation did not succeed /* The operation did not succeed
@ -743,7 +754,7 @@ FsRtlGetFileSize(IN PFILE_OBJECT FileObject,
Irp->UserIosb = &IoStatus; Irp->UserIosb = &IoStatus;
Irp->UserEvent = &Event; Irp->UserEvent = &Event;
Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->Flags = IRP_INPUT_OPERATION | IRP_PAGING_IO; Irp->Flags = IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO;
Irp->RequestorMode = KernelMode; Irp->RequestorMode = KernelMode;
Irp->Tail.Overlay.OriginalFileObject = FileObject; Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->AssociatedIrp.SystemBuffer = &Info; Irp->AssociatedIrp.SystemBuffer = &Info;
@ -761,12 +772,14 @@ FsRtlGetFileSize(IN PFILE_OBJECT FileObject,
Status = IofCallDriver(DeviceObject,Irp); Status = IofCallDriver(DeviceObject,Irp);
/* Standard DDK IRP result processing */ /* Standard DDK IRP result processing */
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL); KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
} }
/* If there was a synchronous error, signal it */ /* If there was a synchronous error, signal it */
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status))
{
IoStatus.Status = Status; IoStatus.Status = Status;
} }
@ -1030,10 +1043,41 @@ FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain) IN PMDL MdlChain)
{ {
KEBUGCHECK(0); PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
PFAST_IO_DISPATCH FastDispatch;
/* Get Device Object and Fast Calls */
DeviceObject = IoGetRelatedDeviceObject(FileObject);
FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
/* Check if we support Fast Calls, and check this one */
if (FastDispatch && FastDispatch->MdlWriteComplete)
{
/* Use the fast path */
return FastDispatch->MdlWriteComplete(FileObject,
FileOffset,
MdlChain,
DeviceObject);
}
/* Get the Base File System (Volume) and Fast Calls */
BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
/* If the Base Device Object has its own FastDispatch Routine, fail */
if (FastDispatch && FastDispatch->MdlWriteComplete &&
BaseDeviceObject != DeviceObject)
{
return FALSE; return FALSE;
} }
/* No fast path, use slow path */
return FsRtlMdlWriteCompleteDev(FileObject,
FileOffset,
MdlChain,
DeviceObject);
}
/* /*
* @implemented * @implemented
*/ */
@ -1044,10 +1088,17 @@ FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject,
IN PMDL MdlChain, IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject) IN PDEVICE_OBJECT DeviceObject)
{ {
KEBUGCHECK(0); if (FileObject->Flags & FO_WRITE_THROUGH)
{
return FALSE; return FALSE;
} }
/* Call the Cache Manager */
CcMdlWriteComplete2(FileObject,FileOffset,MdlChain);
return TRUE;
}
/* /*
* @implemented * @implemented
*/ */
@ -1060,12 +1111,49 @@ FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject,
OUT PMDL *MdlChain, OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus) OUT PIO_STATUS_BLOCK IoStatus)
{ {
KEBUGCHECK(0); PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
PFAST_IO_DISPATCH FastDispatch;
/* Get Device Object and Fast Calls */
DeviceObject = IoGetRelatedDeviceObject(FileObject);
FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
/* Check if we support Fast Calls, and check this one */
if (FastDispatch && FastDispatch->PrepareMdlWrite)
{
/* Use the fast path */
return FastDispatch->PrepareMdlWrite(FileObject,
FileOffset,
Length,
LockKey,
MdlChain,
IoStatus,
DeviceObject);
}
/* Get the Base File System (Volume) and Fast Calls */
BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
FastDispatch = BaseDeviceObject->DriverObject->FastIoDispatch;
/* If the Base Device Object has its own FastDispatch Routine, fail */
if (FastDispatch && FastDispatch->PrepareMdlWrite &&
BaseDeviceObject != DeviceObject)
{
return FALSE; return FALSE;
} }
/* No fast path, use slow path */
return FsRtlPrepareMdlWriteDev(FileObject,
FileOffset,
Length,
LockKey,
MdlChain,
IoStatus,
DeviceObject);
}
/* /*
* @unimplemented * @implemented
*/ */
BOOLEAN BOOLEAN
NTAPI NTAPI
@ -1077,10 +1165,237 @@ FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject) IN PDEVICE_OBJECT DeviceObject)
{ {
KEBUGCHECK(0); BOOLEAN Result = TRUE;
PFAST_IO_DISPATCH FastIoDispatch;
PDEVICE_OBJECT Device;
PFSRTL_COMMON_FCB_HEADER FcbHeader;
LARGE_INTEGER OldFileSize;
LARGE_INTEGER OldValidDataLength;
LARGE_INTEGER NewSize;
LARGE_INTEGER Offset;
/* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
BOOLEAN FileOffsetAppend = ((FileOffset->HighPart == 0xffffffff) && (FileOffset->LowPart == 0xffffffff));
BOOLEAN FileSizeModified = FALSE;
BOOLEAN ResourceAquiredShared = FALSE;
/* Initialize some of the vars and pointers */
OldFileSize.QuadPart = 0;
OldValidDataLength.QuadPart = 0;
PAGED_CODE();
Offset.QuadPart = FileOffset->QuadPart + Length;
/* Nagar p.544 -- Check with Cc if we can write */
if ( (!CcCanIWrite(FileObject, Length,TRUE,FALSE))||
(FileObject->Flags & FO_WRITE_THROUGH))
{
return FALSE; return FALSE;
} }
IoStatus->Status = STATUS_SUCCESS;
/* No actual read */
if (!Length)
{
return TRUE;
}
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
FsRtlEnterFileSystem();
/* Check we are going to extend the file */
if ( (FileOffsetAppend == FALSE) &&
( (FileOffset->QuadPart + Length) <= FcbHeader->ValidDataLength.QuadPart )
)
{
/* Acquire the resource shared */
ExAcquireResourceSharedLite(FcbHeader->Resource,TRUE);
ResourceAquiredShared =TRUE;
} else
{
/* Acquire the resource exclusive */
ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
}
/* Check if we are appending */
if (FileOffsetAppend == TRUE) {
Offset.QuadPart = FcbHeader->FileSize.QuadPart;
NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
} else
{
Offset.QuadPart = FileOffset->QuadPart;
NewSize.QuadPart = FileOffset->QuadPart + Length;
}
if ( (FileObject->PrivateCacheMap) &&
(FcbHeader->IsFastIoPossible) &&
(MAXLONGLONG >= (LONGLONG) FileOffset->QuadPart + Length) &&
(NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart) )
{
/* Check if we can keep the lock shared */
if (ResourceAquiredShared && (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) ) {
ExReleaseResourceLite(FcbHeader->Resource);
ExAcquireResourceExclusiveLite(FcbHeader->Resource,TRUE);
/* Compute the offset and the new filesize */
if (FileOffsetAppend) {
Offset.QuadPart = FcbHeader->FileSize.QuadPart;
NewSize.QuadPart = FcbHeader->FileSize.QuadPart + Length;
}
/* Recheck the above points since we released and reacquire the lock */
if ( (FileObject->PrivateCacheMap != NULL) &&
(FcbHeader->IsFastIoPossible != FastIoIsNotPossible) &&
(FcbHeader->AllocationSize.QuadPart > NewSize.QuadPart)
)
{
/* Do nothing */
} else {
goto FailAndCleanup;
}
}
/* Check if we need to find out if fast I/O is available */
if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
{
/* Sanity check */
/* ASSERT(!KeIsExecutingDpc()); */
/* Get the Fast I/O table */
Device = IoGetRelatedDeviceObject(FileObject);
FastIoDispatch = Device->DriverObject->FastIoDispatch;
/* Sanity check */
ASSERT(FastIoDispatch != NULL);
ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
/* Ask the driver if we can do it */
if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
FileOffset,
Length,
TRUE,
LockKey,
FALSE,
IoStatus,
Device))
{
/* It's not, fail */
goto FailAndCleanup;
}
}
/* If we are going to modify the filesize, save the old fs in case the operation fails */
if (NewSize.QuadPart > FcbHeader->FileSize.QuadPart)
{
FileSizeModified = TRUE;
OldFileSize.QuadPart = FcbHeader->FileSize.QuadPart;
OldValidDataLength.QuadPart = FcbHeader->ValidDataLength.QuadPart;
/* If the high part of the filesize is going to change, grab the Paging IoResouce */
if (NewSize.HighPart != FcbHeader->FileSize.HighPart && FcbHeader->PagingIoResource)
{
ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
ExReleaseResourceLite(FcbHeader->PagingIoResource);
} else {
FcbHeader->FileSize.QuadPart = NewSize.QuadPart;
}
}
/* Nagar p.544 */
/* Set ourselves as top component */
PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
_SEH_TRY
{
/* Check if there is a gap between the end of the file and the offset
If yes, then we have to zero the data
*/
if (Offset.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
Result = CcZeroData(FileObject,&FcbHeader->ValidDataLength,&Offset,TRUE);
if (Result)
{
CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
}
} else {
CcPrepareMdlWrite(FileObject,&Offset,Length,MdlChain,IoStatus);
}
}_SEH_EXCEPT(FsRtlCcCopyFilter)
{
Result = FALSE;
} _SEH_END;
/* Reset the top component */
PsGetCurrentThread()->TopLevelIrp = 0;
/* Did the operation suceeded */
if (Result) {
/* Check if we need to update the filesize */
if (NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart) {
if (NewSize.HighPart != FcbHeader->ValidDataLength.HighPart && FcbHeader->PagingIoResource) {
ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
ExReleaseResourceLite(FcbHeader->PagingIoResource);
} else {
FcbHeader->ValidDataLength.QuadPart = NewSize.QuadPart;
}
}
/* Flag the file as modified */
FileObject->Flags |= FO_FILE_MODIFIED;
/* Check if the filesize has changed */
if (FileSizeModified) {
/* Update the file sizes */
((SHARED_CACHE_MAP*) FileObject->SectionObjectPointer->SharedCacheMap)->FileSize.QuadPart = NewSize.QuadPart;
FileObject->Flags |= FO_FILE_SIZE_CHANGED;
}
}
else
{
/* The operation did not succeed
Reset the file size to what it should be
*/
if (FileSizeModified) {
if (FcbHeader->PagingIoResource) {
ExAcquireResourceExclusiveLite(FcbHeader->PagingIoResource, TRUE);
FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
ExReleaseResourceLite(FcbHeader->PagingIoResource);
}else{
FcbHeader->FileSize.QuadPart = OldFileSize.QuadPart;
FcbHeader->ValidDataLength.QuadPart = OldValidDataLength.QuadPart;
}
}
}
goto Cleanup;
}
else
{
goto FailAndCleanup;
}
FailAndCleanup:
ExReleaseResourceLite(FcbHeader->Resource);
FsRtlExitFileSystem();
return FALSE;
Cleanup:
ExReleaseResourceLite(FcbHeader->Resource);
FsRtlExitFileSystem();
return Result;
}
/* /*
* @implemented * @implemented
*/ */
@ -1088,6 +1403,10 @@ VOID
NTAPI NTAPI
FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject) FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
{ {
/*
PAGED_CODE();
FsRtlAcquireFileExclusiveCommon(FileObject,0,0);
*/
KEBUGCHECK(0); KEBUGCHECK(0);
} }
@ -1098,6 +1417,7 @@ VOID
NTAPI NTAPI
FsRtlReleaseFile(IN PFILE_OBJECT FileObject) FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
{ {
KEBUGCHECK(0); KEBUGCHECK(0);
} }

View file

@ -70,10 +70,10 @@ CcMdlReadComplete2(
VOID VOID
NTAPI NTAPI
CcMdlWriteCompleteDev( CcMdlWriteComplete2(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain, IN PMDL MdlChain
IN PFILE_OBJECT FileObject
); );
NTSTATUS NTSTATUS