sys: cached read/write testing

This commit is contained in:
Bill Zissimopoulos 2016-03-11 14:44:17 -08:00
parent 3f98d1cb01
commit 151247f1e6
8 changed files with 97 additions and 43 deletions

View File

@ -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
{

View File

@ -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,

View File

@ -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))

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);