mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-08 04:52:10 -05:00
sys: cached read/write testing
This commit is contained in:
parent
3f98d1cb01
commit
151247f1e6
@ -197,7 +197,6 @@ typedef struct
|
||||
UINT64 Offset;
|
||||
UINT32 Length;
|
||||
UINT32 Key;
|
||||
UINT32 Constrained:1; /* write's beyond EOF are NOP's (file size remains same) */
|
||||
} Write;
|
||||
struct
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ 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 Constrained,
|
||||
PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length, BOOLEAN WriteToEndOfFile,
|
||||
PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo);
|
||||
NTSTATUS (*GetFileInfo)(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||
|
@ -446,7 +446,7 @@ FSP_API NTSTATUS FspFileSystemOpWrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
(PVOID)Request->Req.Write.Address,
|
||||
Request->Req.Write.Offset,
|
||||
Request->Req.Write.Length,
|
||||
Request->Req.Write.Constrained,
|
||||
(UINT64)-1LL == Request->Req.Write.Offset,
|
||||
&BytesTransferred,
|
||||
&FileInfo);
|
||||
if (!NT_SUCCESS(Result))
|
||||
|
@ -174,7 +174,10 @@ BOOLEAN FspAcquireForLazyWrite(
|
||||
ASSERT(0 == IoGetTopLevelIrp());
|
||||
Result = FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, Wait);
|
||||
if (Result)
|
||||
{
|
||||
FileNode->LazyWriteThread = PsGetCurrentThread();
|
||||
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
||||
}
|
||||
|
||||
FSP_LEAVE_BOOL("Context=%p, Wait=%d", Context, Wait);
|
||||
}
|
||||
@ -192,6 +195,7 @@ VOID FspReleaseFromLazyWrite(
|
||||
|
||||
ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == IoGetTopLevelIrp());
|
||||
IoSetTopLevelIrp(0);
|
||||
FileNode->LazyWriteThread = 0;
|
||||
FspFileNodeRelease(FileNode, Full);
|
||||
|
||||
FSP_LEAVE_VOID("Context=%p", Context);
|
||||
|
@ -793,6 +793,7 @@ typedef struct
|
||||
UINT64 Security;
|
||||
ULONG SecurityChangeNumber;
|
||||
BOOLEAN TruncateOnClose;
|
||||
PVOID LazyWriteThread;
|
||||
/* read-only after creation (and insertion in the ContextTable) */
|
||||
PDEVICE_OBJECT FsvolDeviceObject;
|
||||
UINT64 UserContext;
|
||||
|
@ -88,6 +88,9 @@ static NTSTATUS FspFsvolReadCached(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* assert: must be top-level IRP */
|
||||
ASSERT(0 == FspIrpTopFlags(Irp));
|
||||
|
||||
NTSTATUS Result;
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
@ -151,6 +154,11 @@ static NTSTATUS FspFsvolReadCached(
|
||||
|
||||
Result = FspCcCopyRead(FileObject, &ReadOffset, ReadLength, CanWait, Buffer,
|
||||
&Irp->IoStatus);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
return Result;
|
||||
}
|
||||
if (STATUS_PENDING == Result)
|
||||
{
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
@ -184,6 +192,9 @@ static NTSTATUS FspFsvolReadNonCached(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* assert: either a top-level IRP or Paging I/O */
|
||||
ASSERT(0 == FspIrpTopFlags(Irp) || FlagOn(Irp->Flags, IRP_PAGING_IO));
|
||||
|
||||
NTSTATUS Result;
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
@ -191,6 +202,7 @@ static NTSTATUS FspFsvolReadNonCached(
|
||||
LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset;
|
||||
ULONG ReadLength = IrpSp->Parameters.Read.Length;
|
||||
ULONG ReadKey = IrpSp->Parameters.Read.Key;
|
||||
FSP_FSCTL_FILE_INFO FileInfo;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
@ -199,6 +211,12 @@ 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 */
|
||||
return STATUS_END_OF_FILE;
|
||||
|
||||
/* probe and lock the user buffer */
|
||||
if (0 == Irp->MdlAddress)
|
||||
{
|
||||
@ -306,18 +324,19 @@ NTSTATUS FspFsvolReadComplete(
|
||||
if (0 != SafeMdl)
|
||||
FspSafeMdlCopyBack(SafeMdl);
|
||||
|
||||
if (!PagingIo)
|
||||
/* if we are top-level */
|
||||
if (0 == FspIrpTopFlags(Irp))
|
||||
{
|
||||
if (FspFsctlTransactReadKind == Request->Kind)
|
||||
{
|
||||
InfoChangeNumber = FileNode->InfoChangeNumber;
|
||||
FspIopResetRequest(Request, 0);
|
||||
|
||||
Request->Kind = FspFsctlTransactReservedKind;
|
||||
FspIopResetRequest(Request, 0);
|
||||
FspIopRequestContext(Request, RequestInfoChangeNumber) = (PVOID)InfoChangeNumber;
|
||||
}
|
||||
else
|
||||
InfoChangeNumber = (ULONG)(UINT_PTR)FspIopRequestContext(Request, RequestInfoChangeNumber);
|
||||
InfoChangeNumber =
|
||||
(ULONG)(UINT_PTR)FspIopRequestContext(Request, RequestInfoChangeNumber);
|
||||
|
||||
Success = DEBUGTEST(90, TRUE) && FspFileNodeTryAcquireExclusive(FileNode, Main);
|
||||
if (!Success)
|
||||
@ -326,18 +345,22 @@ NTSTATUS FspFsvolReadComplete(
|
||||
FSP_RETURN();
|
||||
}
|
||||
|
||||
/* update file info */
|
||||
FspFileNodeTrySetFileInfo(FileNode, FileObject, &Response->Rsp.Read.FileInfo,
|
||||
InfoChangeNumber);
|
||||
|
||||
/* update the current file offset if synchronous I/O (and not paging I/O) */
|
||||
if (SynchronousIo)
|
||||
if (SynchronousIo && !PagingIo)
|
||||
FileObject->CurrentByteOffset.QuadPart =
|
||||
ReadOffset.QuadPart + Response->IoStatus.Information;
|
||||
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(PagingIo);
|
||||
FspIopResetRequest(Request, 0);
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = Response->IoStatus.Information;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
@ -88,6 +88,9 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* assert: must be top-level IRP */
|
||||
ASSERT(0 == FspIrpTopFlags(Irp));
|
||||
|
||||
NTSTATUS Result;
|
||||
BOOLEAN Retrying = 0 != FspIrpRequest(Irp);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
@ -104,6 +107,7 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
FSP_FSCTL_FILE_INFO FileInfo;
|
||||
CC_FILE_SIZES FileSizes;
|
||||
UINT64 WriteEndOffset;
|
||||
BOOLEAN ExtendingFile;
|
||||
BOOLEAN Success;
|
||||
|
||||
/* should we defer the write? */
|
||||
@ -132,22 +136,19 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
ASSERT(FspTimeoutInfinity32 ==
|
||||
FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.FileInfoTimeout);
|
||||
FspFileNodeGetFileInfo(FileNode, &FileInfo);
|
||||
FileSizes.AllocationSize.QuadPart = FileInfo.AllocationSize;
|
||||
FileSizes.FileSize.QuadPart = FileInfo.FileSize;
|
||||
FileSizes.ValidDataLength.QuadPart = MAXLONGLONG;
|
||||
WriteEndOffset = WriteToEndOfFile ?
|
||||
FileInfo.FileSize + WriteLength : WriteOffset.QuadPart + WriteLength;
|
||||
if (FileInfo.FileSize < WriteEndOffset)
|
||||
ExtendingFile = FileInfo.FileSize < WriteEndOffset;
|
||||
if (ExtendingFile)
|
||||
{
|
||||
/* file is being extended */
|
||||
FileSizes.FileSize.QuadPart = WriteEndOffset;
|
||||
if (FileSizes.FileSize.QuadPart > FileSizes.AllocationSize.QuadPart)
|
||||
FileInfo.FileSize = WriteEndOffset;
|
||||
if (FileInfo.FileSize > FileInfo.AllocationSize)
|
||||
{
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||
FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
UINT64 AllocationUnit = FsvolDeviceExtension->VolumeParams.SectorSize *
|
||||
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
|
||||
FileSizes.AllocationSize.QuadPart = (FileSizes.FileSize.QuadPart + AllocationUnit - 1)
|
||||
FileInfo.AllocationSize = (FileInfo.FileSize + AllocationUnit - 1)
|
||||
/ AllocationUnit * AllocationUnit;
|
||||
}
|
||||
}
|
||||
@ -155,6 +156,10 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
/* initialize cache if not already initialized! */
|
||||
if (0 == FileObject->PrivateCacheMap)
|
||||
{
|
||||
FileSizes.AllocationSize.QuadPart = FileInfo.AllocationSize;
|
||||
FileSizes.FileSize.QuadPart = FileInfo.FileSize;
|
||||
FileSizes.ValidDataLength.QuadPart = MAXLONGLONG;
|
||||
|
||||
Result = FspCcInitializeCacheMap(FileObject, &FileSizes, FALSE,
|
||||
&FspCacheManagerCallbacks, FileNode);
|
||||
if (!NT_SUCCESS(Result))
|
||||
@ -163,8 +168,12 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
else if (FileInfo.FileSize < WriteEndOffset)
|
||||
else if (ExtendingFile)
|
||||
{
|
||||
FileSizes.AllocationSize.QuadPart = FileInfo.AllocationSize;
|
||||
FileSizes.FileSize.QuadPart = FileInfo.FileSize;
|
||||
FileSizes.ValidDataLength.QuadPart = MAXLONGLONG;
|
||||
|
||||
/* file is being extended */
|
||||
Result = FspCcSetFileSizes(FileObject, &FileSizes);
|
||||
if (!NT_SUCCESS(Result))
|
||||
@ -188,6 +197,11 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
}
|
||||
|
||||
Result = FspCcCopyWrite(FileObject, &WriteOffset, WriteLength, CanWait, Buffer);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
return Result;
|
||||
}
|
||||
if (STATUS_PENDING == Result)
|
||||
{
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
@ -213,6 +227,9 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
if (SynchronousIo)
|
||||
FileObject->CurrentByteOffset.QuadPart = WriteEndOffset;
|
||||
|
||||
if (ExtendingFile)
|
||||
FspFileNodeSetFileInfo(FileNode, 0, &FileInfo);
|
||||
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@ -228,6 +245,9 @@ static NTSTATUS FspFsvolWriteNonCached(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
/* assert: either a top-level IRP or Paging I/O */
|
||||
ASSERT(0 == FspIrpTopFlags(Irp) || FlagOn(Irp->Flags, IRP_PAGING_IO));
|
||||
|
||||
NTSTATUS Result;
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
@ -238,6 +258,7 @@ static NTSTATUS FspFsvolWriteNonCached(
|
||||
BOOLEAN WriteToEndOfFile =
|
||||
FILE_WRITE_TO_END_OF_FILE == WriteOffset.LowPart && -1L == WriteOffset.HighPart;
|
||||
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||
FSP_FSCTL_FILE_INFO FileInfo;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
@ -254,6 +275,23 @@ 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->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);
|
||||
}
|
||||
|
||||
/* probe and lock the user buffer */
|
||||
if (0 == Irp->MdlAddress)
|
||||
{
|
||||
@ -274,7 +312,6 @@ static NTSTATUS FspFsvolWriteNonCached(
|
||||
Request->Req.Write.Offset = WriteOffset.QuadPart;
|
||||
Request->Req.Write.Length = WriteLength;
|
||||
Request->Req.Write.Key = WriteKey;
|
||||
Request->Req.Write.Constrained = PagingIo;
|
||||
|
||||
return FSP_STATUS_IOQ_POST;
|
||||
}
|
||||
@ -386,19 +423,25 @@ NTSTATUS FspFsvolWriteComplete(
|
||||
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
|
||||
BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
|
||||
|
||||
if (!PagingIo)
|
||||
/* if we are top-level */
|
||||
if (0 == FspIrpTopFlags(Irp))
|
||||
{
|
||||
/* update file info */
|
||||
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Write.FileInfo);
|
||||
|
||||
/* update the current file offset if synchronous I/O (and not paging I/O) */
|
||||
if (SynchronousIo)
|
||||
if (SynchronousIo && !PagingIo)
|
||||
FileObject->CurrentByteOffset.QuadPart = WriteToEndOfFile ?
|
||||
Response->Rsp.Write.FileInfo.FileSize :
|
||||
WriteOffset.QuadPart + Response->IoStatus.Information;
|
||||
}
|
||||
|
||||
FspIopResetRequest(Request, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(PagingIo);
|
||||
FspIopResetRequest(Request, 0);
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = Response->IoStatus.Information;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
@ -438,33 +438,17 @@ 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 Constrained,
|
||||
PVOID FileNode0, PVOID Buffer, UINT64 Offset, ULONG Length, BOOLEAN WriteToEndOfFile,
|
||||
PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||
UINT64 EndOffset;
|
||||
|
||||
if ((UINT64)-1LL == Offset)
|
||||
if (WriteToEndOfFile)
|
||||
Offset = FileNode->FileInfo.FileSize;
|
||||
|
||||
if (Constrained)
|
||||
{
|
||||
if (Offset >= FileNode->FileInfo.FileSize)
|
||||
{
|
||||
*PBytesTransferred = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
EndOffset = Offset + Length;
|
||||
if (EndOffset > FileNode->FileInfo.FileSize)
|
||||
EndOffset = FileNode->FileInfo.FileSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
EndOffset = Offset + Length;
|
||||
if (EndOffset > FileNode->FileInfo.FileSize)
|
||||
SetFileSize(FileSystem, Request, FileNode, EndOffset, FileInfo);
|
||||
}
|
||||
|
||||
memcpy((PUINT8)FileNode->FileData + Offset, Buffer, EndOffset - Offset);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user