From 41296044e6eca25023a227b27a8917a736325103 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Wed, 13 Apr 2016 18:00:02 -0700 Subject: [PATCH] sys: IRP_MJ_READ, IRP_MJ_WRITE: fix paging I/O sizes --- inc/winfsp/fsctl.h | 1 + inc/winfsp/winfsp.h | 3 ++- src/dll/fsop.c | 1 + src/sys/read.c | 9 +++++---- src/sys/write.c | 23 +++++++---------------- tst/memfs/memfs.cpp | 24 ++++++++++++++++++------ 6 files changed, 34 insertions(+), 27 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index 28a6798b..f6c156aa 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -206,6 +206,7 @@ typedef struct UINT64 Offset; UINT32 Length; UINT32 Key; + UINT32 ConstrainedIo:1; } Write; struct { diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 1ead2dc9..d8248276 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -70,7 +70,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo); NTSTATUS (*Write)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length, BOOLEAN WriteToEndOfFile, + PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length, + BOOLEAN WriteToEndOfFile, BOOLEAN ConstrainedIo, PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo); NTSTATUS (*Flush)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, diff --git a/src/dll/fsop.c b/src/dll/fsop.c index a806be84..41f6c39e 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -449,6 +449,7 @@ FSP_API NTSTATUS FspFileSystemOpWrite(FSP_FILE_SYSTEM *FileSystem, Request->Req.Write.Offset, Request->Req.Write.Length, (UINT64)-1LL == Request->Req.Write.Offset, + 0 != Request->Req.Write.ConstrainedIo, &BytesTransferred, &FileInfo); if (!NT_SUCCESS(Result)) diff --git a/src/sys/read.c b/src/sys/read.c index 1e7e8ad4..d7aac06f 100644 --- a/src/sys/read.c +++ b/src/sys/read.c @@ -220,10 +220,11 @@ static NTSTATUS FspFsvolReadNonCached( if (FlagOn(IrpSp->MinorFunction, IRP_MN_MDL)) return STATUS_INVALID_PARAMETER; - /* if this is a recursive read (cache) see if we can optimize it away! */ - if (FlagOn(FspIrpTopFlags(Irp), FspFileNodeAcquireMain) && /* if TopLevelIrp has acquired Main */ - FspFileNodeTryGetFileInfo(FileNode, &FileInfo) && /* and the cached FileSize is valid */ - (UINT64)ReadOffset.QuadPart >= FileInfo.FileSize) /* and the ReadOffset is past EOF */ + /* if this is a Paging I/O see if we can optimize it away! */ + if (PagingIo && /* if this is Paging I/O */ + FlagOn(FspIrpTopFlags(Irp), FspFileNodeAcquireMain) && /* and TopLevelIrp has acquired Main */ + FspFileNodeTryGetFileInfo(FileNode, &FileInfo) && /* and the cached FileSize is valid */ + (UINT64)ReadOffset.QuadPart >= FileInfo.FileSize) /* and the ReadOffset is past EOF */ return STATUS_END_OF_FILE; /* probe and lock the user buffer */ diff --git a/src/sys/write.c b/src/sys/write.c index 2cf169e0..8af828e4 100644 --- a/src/sys/write.c +++ b/src/sys/write.c @@ -276,22 +276,12 @@ static NTSTATUS FspFsvolWriteNonCached( if (FspIoqStopped(FspFsvolDeviceExtension(FsvolDeviceObject)->Ioq)) return FspFsvolDeviceStoppedStatus(FsvolDeviceObject); - /* if we are called by the lazy writer we must constrain writes */ - if (FlagOn(FspIrpTopFlags(Irp), FspFileNodeAcquireMain) && /* if TopLevelIrp has acquired Main */ - FileNode->Tls.LazyWriteThread == PsGetCurrentThread()) /* and this is a lazy writer thread */ - { - ASSERT(PagingIo); - ASSERT(FspTimeoutInfinity32 == - FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.FileInfoTimeout); - - FspFileNodeGetFileInfo(FileNode, &FileInfo); - - if ((UINT64)WriteOffset.QuadPart >= FileInfo.FileSize) - return STATUS_SUCCESS; - - if (WriteLength > (ULONG)(FileInfo.FileSize - WriteOffset.QuadPart)) - WriteLength = (ULONG)(FileInfo.FileSize - WriteOffset.QuadPart); - } + /* if this is a Paging I/O see if we can optimize it away! */ + if (PagingIo && /* if this is Paging I/O */ + FlagOn(FspIrpTopFlags(Irp), FspFileNodeAcquireMain) && /* and TopLevelIrp has acquired Main */ + FspFileNodeTryGetFileInfo(FileNode, &FileInfo) && /* and the cached FileSize is valid */ + (UINT64)WriteOffset.QuadPart >= FileInfo.FileSize) /* and the WriteOffset is past EOF */ + return STATUS_SUCCESS; /* probe and lock the user buffer */ Result = FspLockUserBuffer(Irp, WriteLength, IoReadAccess); @@ -348,6 +338,7 @@ static NTSTATUS FspFsvolWriteNonCached( Request->Req.Write.Offset = WriteOffset.QuadPart; Request->Req.Write.Length = WriteLength; Request->Req.Write.Key = WriteKey; + Request->Req.Write.ConstrainedIo = !!PagingIo; FspFileNodeSetOwner(FileNode, Full, Request); FspIopRequestContext(Request, RequestIrp) = Irp; diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index 07443120..05015be5 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -482,17 +482,29 @@ static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem, static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, - PVOID FileNode0, PVOID Buffer, UINT64 Offset, ULONG Length, BOOLEAN WriteToEndOfFile, + PVOID FileNode0, PVOID Buffer, UINT64 Offset, ULONG Length, + BOOLEAN WriteToEndOfFile, BOOLEAN ConstrainedIo, PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo) { MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0; UINT64 EndOffset; - if (WriteToEndOfFile) - Offset = FileNode->FileInfo.FileSize; - EndOffset = Offset + Length; - if (EndOffset > FileNode->FileInfo.FileSize) - SetFileSize(FileSystem, Request, FileNode, EndOffset, FileInfo); + if (ConstrainedIo) + { + if (Offset >= FileNode->FileInfo.FileSize) + return STATUS_SUCCESS; + EndOffset = Offset + Length; + if (EndOffset > FileNode->FileInfo.FileSize) + EndOffset = FileNode->FileInfo.FileSize; + } + else + { + if (WriteToEndOfFile) + Offset = FileNode->FileInfo.FileSize; + EndOffset = Offset + Length; + if (EndOffset > FileNode->FileInfo.FileSize) + SetFileSize(FileSystem, Request, FileNode, EndOffset, FileInfo); + } memcpy((PUINT8)FileNode->FileData + Offset, Buffer, EndOffset - Offset);