Author: fireball
Date: Sat Aug 31 16:36:34 2013
New Revision: 59926
URL:
http://svn.reactos.org/svn/reactos?rev=59926&view=rev
Log:
[NTOS/FSRTL]
- FsRtlCopyWrite: Fix typos in local var names and comments.
- FsRtlCopyWrite: Fix copypasta in a call to FastIoCheckIfPossible: wait flag
shouldn't be always TRUE in this case (it's determined by Wait parameter).
- FsRtlCopyRead: Fix updating of CurrentByteOffset.
- FsRtlAcquireFileForCcFlushEx / FsRtlReleaseFileForCcFlush: Handle the case when FastIO
callback may fail and FsRtl still needs to act as if FastIO callback would be missing at
all.
- Implement FsRtlAcquireFileForModWriteEx / FsRtlReleaseFileForModWrite thanks to Rajeev
Nagar's book.
- Now all necessary FsRtl locking/unlocking mechanisms exist.
Modified:
trunk/reactos/ntoskrnl/fsrtl/fastio.c
Modified: trunk/reactos/ntoskrnl/fsrtl/fastio.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/fastio.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/fastio.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/fastio.c [iso-8859-1] Sat Aug 31 16:36:34 2013
@@ -229,7 +229,7 @@
/* Update the current file offset */
if (Result == TRUE)
{
- FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
+ FileObject->CurrentByteOffset.QuadPart = FileOffset->QuadPart +
IoStatus->Information;
}
}
_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
@@ -282,7 +282,7 @@
BOOLEAN FileOffsetAppend = (FileOffset->HighPart == (LONG)0xffffffff) &&
(FileOffset->LowPart == 0xffffffff);
- BOOLEAN ResourceAquiredShared = FALSE;
+ BOOLEAN ResourceAcquiredShared = FALSE;
BOOLEAN b_4GB = FALSE;
BOOLEAN FileSizeModified = FALSE;
LARGE_INTEGER OldFileSize;
@@ -337,7 +337,7 @@
(Offset.LowPart <= FcbHeader->ValidDataLength.LowPart))
{
ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- ResourceAquiredShared = TRUE;
+ ResourceAcquiredShared = TRUE;
}
else
{
@@ -380,7 +380,7 @@
* release the lock and acquire it exclusively, because
* we are going to need to update the FcbHeader.
*/
- if (ResourceAquiredShared &&
+ if (ResourceAcquiredShared &&
(NewSize.LowPart > FcbHeader->ValidDataLength.LowPart + 0x2000))
{
/* Then we need to acquire the resource exclusive */
@@ -566,7 +566,7 @@
{
goto LeaveCriticalAndFail;
}
- ResourceAquiredShared = TRUE;
+ ResourceAcquiredShared = TRUE;
}
else
{
@@ -602,7 +602,7 @@
(FcbHeader->AllocationSize.QuadPart >= NewSize.QuadPart))
{
/* Check if we can keep the lock shared */
- if (ResourceAquiredShared &&
+ if (ResourceAcquiredShared &&
(NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart))
{
ExReleaseResourceLite(FcbHeader->Resource);
@@ -653,7 +653,7 @@
&FcbHeader->FileSize
:
FileOffset,
Length,
- TRUE,
+ Wait,
LockKey,
FALSE,
&FastIoCheckIfPossibleStatus,
@@ -708,8 +708,8 @@
&Offset,
Wait)))
{
- /* If this operation fails, then we have to exit. We can jump
- * outside the SEH, so I a using a variable to exit normally.
+ /* If this operation fails, then we have to exit. We can't
jump
+ * outside the SEH, so I am using a variable to exit normally.
*/
CallCc = FALSE;
}
@@ -1303,7 +1303,7 @@
(FileOffset->LowPart == 0xffffffff);
BOOLEAN FileSizeModified = FALSE;
- BOOLEAN ResourceAquiredShared = FALSE;
+ BOOLEAN ResourceAcquiredShared = FALSE;
/* Initialize some of the vars and pointers */
OldFileSize.QuadPart = 0;
@@ -1339,7 +1339,7 @@
{
/* Acquire the resource shared */
ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- ResourceAquiredShared = TRUE;
+ ResourceAcquiredShared = TRUE;
}
else
{
@@ -1365,7 +1365,7 @@
(NewSize.QuadPart <= FcbHeader->AllocationSize.QuadPart))
{
/* Check if we can keep the lock shared */
- if (ResourceAquiredShared &&
+ if (ResourceAcquiredShared &&
(NewSize.QuadPart > FcbHeader->ValidDataLength.QuadPart))
{
ExReleaseResourceLite(FcbHeader->Resource);
@@ -1650,6 +1650,7 @@
PFSRTL_COMMON_FCB_HEADER FcbHeader;
PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
PFAST_IO_DISPATCH FastDispatch;
+ NTSTATUS Status;
/* Get the Base File System (Volume) and Fast Calls */
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
@@ -1665,25 +1666,31 @@
FastDispatch->AcquireForCcFlush)
{
/* Call the AcquireForCcFlush FastIo handler */
- FastDispatch->AcquireForCcFlush(FileObject, BaseDeviceObject);
- }
- else
- {
- /* No FastIo handler, acquire file's resource */
- if (FcbHeader->Resource)
- {
- /* Acquire it - either shared if it's already acquired
- or exclusively if we are the first */
- if (ExIsResourceAcquiredSharedLite(FcbHeader->Resource))
- ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
- else
- ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE);
- }
-
- /* Also acquire its Paging I/O resource */
- if (FcbHeader->PagingIoResource)
- ExAcquireResourceSharedLite(FcbHeader->PagingIoResource, TRUE);
- }
+ Status = FastDispatch->AcquireForCcFlush(FileObject, BaseDeviceObject);
+
+ /* Return either success or inability to wait.
+ In case of other failure - fall through */
+ if (Status == STATUS_SUCCESS ||
+ Status == STATUS_CANT_WAIT)
+ {
+ return Status;
+ }
+ }
+
+ /* No FastIo handler (or it failed). Acquire Main resource */
+ if (FcbHeader->Resource)
+ {
+ /* Acquire it - either shared if it's already acquired
+ or exclusively if we are the first */
+ if (ExIsResourceAcquiredSharedLite(FcbHeader->Resource))
+ ExAcquireResourceSharedLite(FcbHeader->Resource, TRUE);
+ else
+ ExAcquireResourceExclusiveLite(FcbHeader->Resource, TRUE);
+ }
+
+ /* Also acquire its PagingIO resource */
+ if (FcbHeader->PagingIoResource)
+ ExAcquireResourceSharedLite(FcbHeader->PagingIoResource, TRUE);
return STATUS_SUCCESS;
}
@@ -1712,6 +1719,7 @@
PFSRTL_COMMON_FCB_HEADER FcbHeader;
PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
PFAST_IO_DISPATCH FastDispatch;
+ NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
/* Get Device Object and Fast Calls */
FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
@@ -1724,11 +1732,13 @@
FastDispatch->ReleaseForCcFlush)
{
/* Call the ReleaseForCcFlush FastIo handler */
- FastDispatch->ReleaseForCcFlush(FileObject, BaseDeviceObject);
- }
- else
- {
- /* No FastIo handler, release PagingIO and then file's resource */
+ Status = FastDispatch->ReleaseForCcFlush(FileObject, BaseDeviceObject);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* No FastIo handler (or it failed). Release PagingIO resource and
+ then Main resource */
if (FcbHeader->PagingIoResource)
ExReleaseResourceLite(FcbHeader->PagingIoResource);
if (FcbHeader->Resource) ExReleaseResourceLite(FcbHeader->Resource);
}
@@ -1736,6 +1746,192 @@
/* Release master FsRtl lock */
FsRtlExitFileSystem();
}
+
+/*
+* @implemented
+*/
+NTSTATUS
+NTAPI
+FsRtlAcquireFileForModWriteEx(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER EndingOffset,
+ IN PERESOURCE *ResourceToRelease)
+{
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+ PERESOURCE ResourceToAcquire = NULL;
+ BOOLEAN Exclusive = FALSE;
+ BOOLEAN Result;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* Get Device Object and Fast Calls */
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if Fast Calls are supported, and check AcquireForModWrite */
+ if (FastDispatch &&
+ FastDispatch->AcquireForModWrite)
+ {
+ /* Call the AcquireForModWrite FastIo handler */
+ Status = FastDispatch->AcquireForModWrite(FileObject,
+ EndingOffset,
+ ResourceToRelease,
+ BaseDeviceObject);
+
+ /* Return either success or inability to wait.
+ In case of other failure - fall through */
+ if (Status == STATUS_SUCCESS ||
+ Status == STATUS_CANT_WAIT)
+ {
+ return Status;
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+
+ /* No FastIo handler, use algorithm from Nagar p.550. */
+ if (!FcbHeader->Resource)
+ {
+ *ResourceToRelease = NULL;
+ return STATUS_SUCCESS;
+ }
+
+ /* Default condition - shared acquiring of Paging IO Resource */
+ ResourceToAcquire = FcbHeader->PagingIoResource;
+
+ /* Decide on type of locking and type of resource based on historical magic
+ well explain by Nagar in p. 550-551 */
+ if ((EndingOffset->QuadPart > FcbHeader->ValidDataLength.QuadPart
&&
+ FcbHeader->FileSize.QuadPart != FcbHeader->ValidDataLength.QuadPart) ||
+ (FcbHeader->Flags & FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX))
+ {
+ /* Either exclusive flag is set or write operation is extending
+ the valid data length. Prefer exclusive acquire then */
+ Exclusive = TRUE;
+ ResourceToAcquire = FcbHeader->Resource;
+ }
+ else if (!FcbHeader->PagingIoResource ||
+ (FcbHeader->Flags & FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH))
+ {
+ /* Acquire main resource shared if flag is specified or
+ if PagingIo resource is missing */
+ Exclusive = FALSE;
+ ResourceToAcquire = FcbHeader->Resource;
+ }
+
+ /* Acquire the resource in the loop, since the above code is unsafe */
+ while (TRUE)
+ {
+ Result = FALSE;
+
+ if (Exclusive)
+ Result = ExAcquireResourceExclusiveLite(ResourceToAcquire, FALSE);
+ else
+ Result = ExAcquireSharedWaitForExclusive(ResourceToAcquire, FALSE);
+
+ if (!Result) {
+ Status = STATUS_CANT_WAIT;
+ break;
+ }
+
+ /* Do the magic ifs again */
+ if ((EndingOffset->QuadPart > FcbHeader->ValidDataLength.QuadPart) ||
+ (FcbHeader->Flags & FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX))
+ {
+ /* Check what we have */
+ if (Exclusive)
+ {
+ /* Asked for exclusive, got exclusive! */
+ break;
+ }
+ else
+ {
+ /* Asked for exclusive, got shared. Release it and retry. */
+ ExReleaseResourceLite(ResourceToAcquire);
+ Exclusive = TRUE;
+ ResourceToAcquire = FcbHeader->Resource;
+ }
+ }
+ else if (FcbHeader->Flags & FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH)
+ {
+ if (Exclusive)
+ {
+ /* Asked for shared, got exclusive - convert */
+ ExConvertExclusiveToSharedLite(ResourceToAcquire);
+ break;
+ }
+ else if (ResourceToAcquire != FcbHeader->Resource)
+ {
+ /* Asked for main resource, got something else */
+ ExReleaseResourceLite(ResourceToAcquire);
+ ResourceToAcquire = FcbHeader->Resource;
+ Exclusive = TRUE;
+ }
+ }
+ else if (FcbHeader->PagingIoResource &&
+ ResourceToAcquire != FcbHeader->PagingIoResource)
+ {
+ /* There is PagingIo resource, but other resource was acquired */
+ ResourceToAcquire = FcbHeader->PagingIoResource;
+ if (!ExAcquireSharedWaitForExclusive(ResourceToAcquire, FALSE))
+ {
+ Status = STATUS_CANT_WAIT;
+ ExReleaseResourceLite(FcbHeader->Resource);
+ }
+
+ break;
+ }
+ else if (Exclusive)
+ {
+ /* Asked for shared got exclusive - convert */
+ ExConvertExclusiveToSharedLite(ResourceToAcquire);
+ break;
+ }
+ }
+
+ /* If the resource was acquired successfully - pass it to the caller */
+ if (NT_SUCCESS(Status))
+ *ResourceToRelease = ResourceToAcquire;
+
+ return Status;
+}
+
+/*
+* @implemented
+*/
+VOID
+NTAPI
+FsRtlReleaseFileForModWrite(IN PFILE_OBJECT FileObject,
+ IN PERESOURCE ResourceToRelease)
+{
+ PDEVICE_OBJECT DeviceObject, BaseDeviceObject;
+ PFAST_IO_DISPATCH FastDispatch;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* Get Device Object and Fast Calls */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ BaseDeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
+ if (FastDispatch &&
+ FastDispatch->ReleaseForModWrite)
+ {
+ /* Call the ReleaseForModWrite FastIo handler */
+ Status = FastDispatch->ReleaseForModWrite(FileObject,
+ ResourceToRelease,
+ BaseDeviceObject);
+ }
+
+ /* Just release the resource if previous op failed */
+ if (!NT_SUCCESS(Status))
+ {
+ ExReleaseResourceLite(ResourceToRelease);
+ }
+}
+
/*++
* @name FsRtlRegisterFileSystemFilterCallbacks