mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
sys: FastIo: read/write implementation
This commit is contained in:
parent
00d4aba946
commit
20680fa5b5
@ -66,11 +66,17 @@ BOOLEAN FspFastIoCheckIfPossible(
|
|||||||
PIO_STATUS_BLOCK IoStatus,
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
PDEVICE_OBJECT DeviceObject)
|
PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
#else
|
||||||
FSP_ENTER_BOOL(PAGED_CODE());
|
FSP_ENTER_BOOL(PAGED_CODE());
|
||||||
|
|
||||||
Result = FALSE;
|
Result = FALSE;
|
||||||
|
|
||||||
FSP_LEAVE_BOOL("FileObject=%p", FileObject);
|
FSP_LEAVE_BOOL("FileObject=%p", FileObject);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspAcquireFileForNtCreateSection(
|
VOID FspAcquireFileForNtCreateSection(
|
||||||
@ -299,9 +305,16 @@ VOID FspPropagateTopFlags(PIRP Irp, PIRP TopLevelIrp)
|
|||||||
|
|
||||||
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= TopLevelIrp)
|
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= TopLevelIrp)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* FAST I/O only acquires the Main lock.
|
||||||
|
* Other (non-IRP) top levels acquire the Full lock.
|
||||||
|
*/
|
||||||
DEBUGBREAK_EX(iorecu);
|
DEBUGBREAK_EX(iorecu);
|
||||||
|
|
||||||
FspIrpSetTopFlags(Irp, FspFileNodeAcquireFull);
|
FspIrpSetTopFlags(Irp,
|
||||||
|
(PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP == TopLevelIrp ?
|
||||||
|
FspFileNodeAcquireMain :
|
||||||
|
FspFileNodeAcquireFull);
|
||||||
}
|
}
|
||||||
else if ((PIRP)MM_SYSTEM_RANGE_START <= TopLevelIrp && IO_TYPE_IRP == TopLevelIrp->Type)
|
else if ((PIRP)MM_SYSTEM_RANGE_START <= TopLevelIrp && IO_TYPE_IRP == TopLevelIrp->Type)
|
||||||
{
|
{
|
||||||
|
@ -89,8 +89,8 @@ NTSTATUS DriverEntry(
|
|||||||
/* setup fast I/O and resource acquisition */
|
/* setup fast I/O and resource acquisition */
|
||||||
FspFastIoDispatch.SizeOfFastIoDispatch = sizeof FspFastIoDispatch;
|
FspFastIoDispatch.SizeOfFastIoDispatch = sizeof FspFastIoDispatch;
|
||||||
FspFastIoDispatch.FastIoCheckIfPossible = FspFastIoCheckIfPossible;
|
FspFastIoDispatch.FastIoCheckIfPossible = FspFastIoCheckIfPossible;
|
||||||
//FspFastIoDispatch.FastIoRead = 0;
|
FspFastIoDispatch.FastIoRead = FspFastIoRead;
|
||||||
//FspFastIoDispatch.FastIoWrite = 0;
|
FspFastIoDispatch.FastIoWrite = FspFastIoWrite;
|
||||||
FspFastIoDispatch.FastIoQueryBasicInfo = FspFastIoQueryBasicInfo;
|
FspFastIoDispatch.FastIoQueryBasicInfo = FspFastIoQueryBasicInfo;
|
||||||
FspFastIoDispatch.FastIoQueryStandardInfo = FspFastIoQueryStandardInfo;
|
FspFastIoDispatch.FastIoQueryStandardInfo = FspFastIoQueryStandardInfo;
|
||||||
//FspFastIoDispatch.FastIoLock = 0;
|
//FspFastIoDispatch.FastIoLock = 0;
|
||||||
|
@ -304,6 +304,43 @@ VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Sta
|
|||||||
} \
|
} \
|
||||||
); \
|
); \
|
||||||
return Result
|
return Result
|
||||||
|
#define FSP_ENTER_FIO(...) \
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject; \
|
||||||
|
if (FspFsmupDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)\
|
||||||
|
{ \
|
||||||
|
FsvolDeviceObject = FspMupGetFsvolDeviceObject(FileObject);\
|
||||||
|
if (0 == FsvolDeviceObject) \
|
||||||
|
{ \
|
||||||
|
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;\
|
||||||
|
IoStatus->Information = 0; \
|
||||||
|
return TRUE; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
FsvolDeviceObject = DeviceObject;\
|
||||||
|
BOOLEAN Result = TRUE; \
|
||||||
|
BOOLEAN fsp_device_deref = FALSE; \
|
||||||
|
FSP_ENTER_(ioentr, __VA_ARGS__); \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
ASSERT(0 == IoGetTopLevelIrp()); \
|
||||||
|
IoSetTopLevelIrp((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP); \
|
||||||
|
if (!FspDeviceReference(FsvolDeviceObject))\
|
||||||
|
{ \
|
||||||
|
IoStatus->Status = STATUS_CANCELLED;\
|
||||||
|
IoStatus->Information = 0; \
|
||||||
|
goto fsp_leave_label; \
|
||||||
|
} \
|
||||||
|
fsp_device_deref = TRUE; \
|
||||||
|
} while (0,0)
|
||||||
|
#define FSP_LEAVE_FIO(fmt, ...) \
|
||||||
|
FSP_LEAVE_( \
|
||||||
|
FSP_DEBUGLOG_(fmt, " = %s", __VA_ARGS__, Result ? "TRUE" : "FALSE");\
|
||||||
|
if (fsp_device_deref) \
|
||||||
|
FspDeviceDereference(FsvolDeviceObject);\
|
||||||
|
IoSetTopLevelIrp(0); \
|
||||||
|
); \
|
||||||
|
return Result
|
||||||
#define FSP_ENTER_BOOL(...) \
|
#define FSP_ENTER_BOOL(...) \
|
||||||
BOOLEAN Result = TRUE; FSP_ENTER_(iocall, __VA_ARGS__)
|
BOOLEAN Result = TRUE; FSP_ENTER_(iocall, __VA_ARGS__)
|
||||||
#define FSP_LEAVE_BOOL(fmt, ...) \
|
#define FSP_LEAVE_BOOL(fmt, ...) \
|
||||||
@ -383,6 +420,8 @@ FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
|||||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||||
|
|
||||||
/* fast I/O and resource acquisition callbacks */
|
/* fast I/O and resource acquisition callbacks */
|
||||||
|
FAST_IO_READ FspFastIoRead;
|
||||||
|
FAST_IO_WRITE FspFastIoWrite;
|
||||||
FAST_IO_QUERY_BASIC_INFO FspFastIoQueryBasicInfo;
|
FAST_IO_QUERY_BASIC_INFO FspFastIoQueryBasicInfo;
|
||||||
FAST_IO_QUERY_STANDARD_INFO FspFastIoQueryStandardInfo;
|
FAST_IO_QUERY_STANDARD_INFO FspFastIoQueryStandardInfo;
|
||||||
FAST_IO_QUERY_NETWORK_OPEN_INFO FspFastIoQueryNetworkOpenInfo;
|
FAST_IO_QUERY_NETWORK_OPEN_INFO FspFastIoQueryNetworkOpenInfo;
|
||||||
@ -1360,6 +1399,8 @@ NTSTATUS FspMupRegister(
|
|||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
VOID FspMupUnregister(
|
VOID FspMupUnregister(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
|
PDEVICE_OBJECT FspMupGetFsvolDeviceObject(
|
||||||
|
PFILE_OBJECT FileObject);
|
||||||
NTSTATUS FspMupHandleIrp(
|
NTSTATUS FspMupHandleIrp(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
|
|||||||
RtlZeroMemory(FileNode, sizeof *FileNode + ExtraSize);
|
RtlZeroMemory(FileNode, sizeof *FileNode + ExtraSize);
|
||||||
FileNode->Header.NodeTypeCode = FspFileNodeFileKind;
|
FileNode->Header.NodeTypeCode = FspFileNodeFileKind;
|
||||||
FileNode->Header.NodeByteSize = sizeof *FileNode;
|
FileNode->Header.NodeByteSize = sizeof *FileNode;
|
||||||
FileNode->Header.IsFastIoPossible = FastIoIsNotPossible;
|
FileNode->Header.IsFastIoPossible = FastIoIsQuestionable;
|
||||||
FileNode->Header.Resource = &NonPaged->Resource;
|
FileNode->Header.Resource = &NonPaged->Resource;
|
||||||
FileNode->Header.PagingIoResource = &NonPaged->PagingIoResource;
|
FileNode->Header.PagingIoResource = &NonPaged->PagingIoResource;
|
||||||
FileNode->Header.ValidDataLength.QuadPart = MAXLONGLONG;
|
FileNode->Header.ValidDataLength.QuadPart = MAXLONGLONG;
|
||||||
|
@ -43,6 +43,8 @@ NTSTATUS FspMupRegister(
|
|||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
VOID FspMupUnregister(
|
VOID FspMupUnregister(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||||
|
PDEVICE_OBJECT FspMupGetFsvolDeviceObject(
|
||||||
|
PFILE_OBJECT FileObject);
|
||||||
NTSTATUS FspMupHandleIrp(
|
NTSTATUS FspMupHandleIrp(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp);
|
||||||
static NTSTATUS FspMupRedirQueryPathEx(
|
static NTSTATUS FspMupRedirQueryPathEx(
|
||||||
@ -52,6 +54,7 @@ static NTSTATUS FspMupRedirQueryPathEx(
|
|||||||
#pragma alloc_text(PAGE, FspMupGetClassName)
|
#pragma alloc_text(PAGE, FspMupGetClassName)
|
||||||
#pragma alloc_text(PAGE, FspMupRegister)
|
#pragma alloc_text(PAGE, FspMupRegister)
|
||||||
#pragma alloc_text(PAGE, FspMupUnregister)
|
#pragma alloc_text(PAGE, FspMupUnregister)
|
||||||
|
#pragma alloc_text(PAGE, FspMupGetFsvolDeviceObject)
|
||||||
#pragma alloc_text(PAGE, FspMupHandleIrp)
|
#pragma alloc_text(PAGE, FspMupHandleIrp)
|
||||||
#pragma alloc_text(PAGE, FspMupRedirQueryPathEx)
|
#pragma alloc_text(PAGE, FspMupRedirQueryPathEx)
|
||||||
#endif
|
#endif
|
||||||
@ -191,6 +194,27 @@ VOID FspMupUnregister(
|
|||||||
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
ExReleaseResourceLite(&FsmupDeviceExtension->PrefixTableResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FspMupGetFsvolDeviceObject(
|
||||||
|
PFILE_OBJECT FileObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = 0;
|
||||||
|
|
||||||
|
ASSERT(0 != FileObject);
|
||||||
|
|
||||||
|
if (FspFileNodeIsValid(FileObject->FsContext))
|
||||||
|
FsvolDeviceObject = ((FSP_FILE_NODE*)FileObject->FsContext)->FsvolDeviceObject;
|
||||||
|
else if (0 != FileObject->FsContext2 &&
|
||||||
|
#pragma prefast(disable:28175, "We are a filesystem: ok to access DeviceObject->Type")
|
||||||
|
IO_TYPE_DEVICE == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
||||||
|
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
||||||
|
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
||||||
|
FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2;
|
||||||
|
|
||||||
|
return FsvolDeviceObject;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspMupHandleIrp(
|
NTSTATUS FspMupHandleIrp(
|
||||||
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp)
|
PDEVICE_OBJECT FsmupDeviceObject, PIRP Irp)
|
||||||
{
|
{
|
||||||
@ -276,7 +300,7 @@ NTSTATUS FspMupHandleIrp(
|
|||||||
FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject;
|
FsvolDeviceObject = ((FSP_FILE_NODE *)FileObject->FsContext)->FsvolDeviceObject;
|
||||||
else if (0 != FileObject->FsContext2 &&
|
else if (0 != FileObject->FsContext2 &&
|
||||||
#pragma prefast(disable:28175, "We are a filesystem: ok to access DeviceObject->Type")
|
#pragma prefast(disable:28175, "We are a filesystem: ok to access DeviceObject->Type")
|
||||||
3 == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
IO_TYPE_DEVICE == ((PDEVICE_OBJECT)FileObject->FsContext2)->Type &&
|
||||||
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
0 != ((PDEVICE_OBJECT)FileObject->FsContext2)->DeviceExtension &&
|
||||||
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
FspFsvolDeviceExtensionKind == FspDeviceExtension((PDEVICE_OBJECT)FileObject->FsContext2)->Kind)
|
||||||
FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2;
|
FsvolDeviceObject = (PDEVICE_OBJECT)FileObject->FsContext2;
|
||||||
|
103
src/sys/read.c
103
src/sys/read.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
FAST_IO_READ FspFastIoRead;
|
||||||
static NTSTATUS FspFsvolRead(
|
static NTSTATUS FspFsvolRead(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolReadCached(
|
static NTSTATUS FspFsvolReadCached(
|
||||||
@ -35,6 +36,7 @@ static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini;
|
|||||||
FSP_DRIVER_DISPATCH FspRead;
|
FSP_DRIVER_DISPATCH FspRead;
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspFastIoRead)
|
||||||
#pragma alloc_text(PAGE, FspFsvolRead)
|
#pragma alloc_text(PAGE, FspFsvolRead)
|
||||||
#pragma alloc_text(PAGE, FspFsvolReadCached)
|
#pragma alloc_text(PAGE, FspFsvolReadCached)
|
||||||
#pragma alloc_text(PAGE, FspFsvolReadNonCached)
|
#pragma alloc_text(PAGE, FspFsvolReadNonCached)
|
||||||
@ -55,6 +57,107 @@ enum
|
|||||||
};
|
};
|
||||||
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
||||||
|
|
||||||
|
BOOLEAN FspFastIoRead(
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
PLARGE_INTEGER ByteOffset,
|
||||||
|
ULONG Length,
|
||||||
|
BOOLEAN CanWait,
|
||||||
|
ULONG Key,
|
||||||
|
PVOID UserBuffer,
|
||||||
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
|
PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
FSP_ENTER_FIO(PAGED_CODE());
|
||||||
|
|
||||||
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
|
||||||
|
if (!FspFileNodeIsValid(FileObject->FsContext))
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FILE_NODE* FileNode = FileObject->FsContext;
|
||||||
|
LARGE_INTEGER ReadOffset = *ByteOffset;
|
||||||
|
ULONG ReadLength = Length;
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
|
||||||
|
/* only regular files can be read */
|
||||||
|
if (FileNode->IsDirectory)
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do we have anything to read? */
|
||||||
|
if (0 == ReadLength)
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
|
||||||
|
/* does the file support caching? */
|
||||||
|
if (!FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* try to acquire the FileNode Main shared */
|
||||||
|
Result = DEBUGTEST(90) &&
|
||||||
|
FspFileNodeTryAcquireSharedF(FileNode, FspFileNodeAcquireMain, CanWait);
|
||||||
|
if (!Result)
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* is the file actually cached? */
|
||||||
|
if (0 == FileObject->PrivateCacheMap)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* does the file have oplocks or file locks? */
|
||||||
|
Result =
|
||||||
|
FsRtlOplockIsFastIoPossible(FspFileNodeAddrOfOplock(FileNode)) &&
|
||||||
|
!FsRtlAreThereCurrentFileLocks(&FileNode->FileLock);
|
||||||
|
if (!Result)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* trim ReadLength; the cache manager does not tolerate reads beyond file size */
|
||||||
|
ASSERT(FspTimeoutInfinity32 ==
|
||||||
|
FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.FileInfoTimeout);
|
||||||
|
FspFileNodeGetFileInfo(FileNode, &FileInfo);
|
||||||
|
if ((UINT64)ReadOffset.QuadPart >= FileInfo.FileSize)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
IoStatus->Status = STATUS_END_OF_FILE;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
if ((UINT64)ReadLength > FileInfo.FileSize - ReadOffset.QuadPart)
|
||||||
|
ReadLength = (ULONG)(FileInfo.FileSize - ReadOffset.QuadPart);
|
||||||
|
|
||||||
|
NTSTATUS Result0 =
|
||||||
|
FspCcCopyRead(FileObject, &ReadOffset, ReadLength, CanWait, UserBuffer, IoStatus);
|
||||||
|
if (!NT_SUCCESS(Result0))
|
||||||
|
{
|
||||||
|
IoStatus->Status = Result0;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
Result = STATUS_SUCCESS == Result0;
|
||||||
|
|
||||||
|
SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ);
|
||||||
|
if (Result)
|
||||||
|
FileObject->CurrentByteOffset.QuadPart = ReadOffset.QuadPart + ReadLength;
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
|
||||||
|
FSP_LEAVE_FIO(
|
||||||
|
"FileObject=%p, UserBuffer=%p, CanWait=%d, "
|
||||||
|
"Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld",
|
||||||
|
FileObject, UserBuffer, CanWait,
|
||||||
|
Key, ByteOffset->HighPart, ByteOffset->LowPart, Length);
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolRead(
|
static NTSTATUS FspFsvolRead(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
|
125
src/sys/write.c
125
src/sys/write.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <sys/driver.h>
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
FAST_IO_WRITE FspFastIoWrite;
|
||||||
static NTSTATUS FspFsvolWrite(
|
static NTSTATUS FspFsvolWrite(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolWriteCached(
|
static NTSTATUS FspFsvolWriteCached(
|
||||||
@ -36,6 +37,7 @@ static FSP_IOP_REQUEST_FINI FspFsvolWriteNonCachedRequestFini;
|
|||||||
FSP_DRIVER_DISPATCH FspWrite;
|
FSP_DRIVER_DISPATCH FspWrite;
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, FspFastIoWrite)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWrite)
|
#pragma alloc_text(PAGE, FspFsvolWrite)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWriteCached)
|
#pragma alloc_text(PAGE, FspFsvolWriteCached)
|
||||||
#pragma alloc_text(PAGE, FspFsvolWriteNonCached)
|
#pragma alloc_text(PAGE, FspFsvolWriteNonCached)
|
||||||
@ -56,6 +58,129 @@ enum
|
|||||||
};
|
};
|
||||||
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
FSP_FSCTL_STATIC_ASSERT(RequestCookie == RequestSafeMdl, "");
|
||||||
|
|
||||||
|
BOOLEAN FspFastIoWrite(
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
PLARGE_INTEGER ByteOffset,
|
||||||
|
ULONG Length,
|
||||||
|
BOOLEAN CanWait,
|
||||||
|
ULONG Key,
|
||||||
|
PVOID UserBuffer,
|
||||||
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
|
PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
FSP_ENTER_FIO(PAGED_CODE());
|
||||||
|
|
||||||
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
|
||||||
|
if (!FspFileNodeIsValid(FileObject->FsContext))
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FILE_NODE* FileNode = FileObject->FsContext;
|
||||||
|
LARGE_INTEGER WriteOffset = *ByteOffset;
|
||||||
|
ULONG WriteLength = Length;
|
||||||
|
BOOLEAN WriteToEndOfFile =
|
||||||
|
FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart;
|
||||||
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
|
UINT64 WriteEndOffset;
|
||||||
|
BOOLEAN ExtendingFile;
|
||||||
|
|
||||||
|
/* only regular files can be written */
|
||||||
|
if (FileNode->IsDirectory)
|
||||||
|
{
|
||||||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do we have anything to write? */
|
||||||
|
if (0 == WriteLength)
|
||||||
|
FSP_RETURN(Result = TRUE);
|
||||||
|
|
||||||
|
/* WinFsp cannot do Fast I/O when extending file */
|
||||||
|
if (WriteToEndOfFile)
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* does the file support caching? is it write-through? */
|
||||||
|
if (!FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) ||
|
||||||
|
FlagOn(FileObject->Flags, FO_WRITE_THROUGH))
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* can we write without flushing? */
|
||||||
|
Result = DEBUGTEST(90) &&
|
||||||
|
CcCanIWrite(FileObject, WriteLength, CanWait, FALSE) &&
|
||||||
|
CcCopyWriteWontFlush(FileObject, &WriteOffset, WriteLength);
|
||||||
|
if (!Result)
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* try to acquire the FileNode Main exclusive */
|
||||||
|
Result = DEBUGTEST(90) &&
|
||||||
|
FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireMain, CanWait);
|
||||||
|
if (!Result)
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
|
||||||
|
/* is the file actually cached? */
|
||||||
|
if (0 == FileObject->PrivateCacheMap)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* does the file have oplocks or file locks? */
|
||||||
|
Result =
|
||||||
|
FsRtlOplockIsFastIoPossible(FspFileNodeAddrOfOplock(FileNode)) &&
|
||||||
|
!FsRtlAreThereCurrentFileLocks(&FileNode->FileLock);
|
||||||
|
if (!Result)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute new file size */
|
||||||
|
ASSERT(FspTimeoutInfinity32 ==
|
||||||
|
FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.FileInfoTimeout);
|
||||||
|
FspFileNodeGetFileInfo(FileNode, &FileInfo);
|
||||||
|
if (WriteToEndOfFile)
|
||||||
|
WriteOffset.QuadPart = FileInfo.FileSize;
|
||||||
|
WriteEndOffset = WriteOffset.QuadPart + WriteLength;
|
||||||
|
ExtendingFile = FileInfo.FileSize < WriteEndOffset;
|
||||||
|
|
||||||
|
/* WinFsp cannot do Fast I/O when extending file */
|
||||||
|
if (ExtendingFile)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS Result0 =
|
||||||
|
FspCcCopyWrite(FileObject, &WriteOffset, WriteLength, CanWait, UserBuffer);
|
||||||
|
if (!NT_SUCCESS(Result0))
|
||||||
|
{
|
||||||
|
IoStatus->Status = Result0;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
FSP_RETURN(Result = FALSE);
|
||||||
|
}
|
||||||
|
Result = STATUS_SUCCESS == Result0;
|
||||||
|
|
||||||
|
if (Result)
|
||||||
|
{
|
||||||
|
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
||||||
|
FileObject->CurrentByteOffset.QuadPart = WriteEndOffset;
|
||||||
|
IoStatus->Information = WriteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileNodeRelease(FileNode, Main);
|
||||||
|
|
||||||
|
FSP_LEAVE_FIO(
|
||||||
|
"FileObject=%p, UserBuffer=%p, CanWait=%d, "
|
||||||
|
"Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld",
|
||||||
|
FileObject, UserBuffer, CanWait,
|
||||||
|
Key, ByteOffset->HighPart, ByteOffset->LowPart, Length);
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolWrite(
|
static NTSTATUS FspFsvolWrite(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user