sys: IRP_MJ_READ, IRP_MJ_WRITE: do not block user-mode file system thread for FlushAndPurge

This commit is contained in:
Bill Zissimopoulos 2016-03-17 14:16:22 -07:00
parent 15f39c3ca8
commit b44c6d64db
3 changed files with 110 additions and 92 deletions

View File

@ -12,7 +12,8 @@ static NTSTATUS FspFsvolReadCached(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN CanWait); BOOLEAN CanWait);
static NTSTATUS FspFsvolReadNonCached( static NTSTATUS FspFsvolReadNonCached(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN CanWait);
FSP_IOPREP_DISPATCH FspFsvolReadPrepare; FSP_IOPREP_DISPATCH FspFsvolReadPrepare;
FSP_IOCMPL_DISPATCH FspFsvolReadComplete; FSP_IOCMPL_DISPATCH FspFsvolReadComplete;
static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini; static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini;
@ -77,7 +78,7 @@ static NTSTATUS FspFsvolRead(
!FlagOn(Irp->Flags, IRP_PAGING_IO | IRP_NOCACHE)) !FlagOn(Irp->Flags, IRP_PAGING_IO | IRP_NOCACHE))
Result = FspFsvolReadCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp)); Result = FspFsvolReadCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp));
else else
Result = FspFsvolReadNonCached(FsvolDeviceObject, Irp, IrpSp); Result = FspFsvolReadNonCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp));
return Result; return Result;
} }
@ -190,7 +191,8 @@ cleanup:
} }
static NTSTATUS FspFsvolReadNonCached( static NTSTATUS FspFsvolReadNonCached(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN CanWait)
{ {
PAGED_CODE(); PAGED_CODE();
@ -204,8 +206,10 @@ static NTSTATUS FspFsvolReadNonCached(
LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset; LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset;
ULONG ReadLength = IrpSp->Parameters.Read.Length; ULONG ReadLength = IrpSp->Parameters.Read.Length;
ULONG ReadKey = IrpSp->Parameters.Read.Key; ULONG ReadKey = IrpSp->Parameters.Read.Key;
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
FSP_FSCTL_FILE_INFO FileInfo; FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_TRANSACT_REQ *Request; FSP_FSCTL_TRANSACT_REQ *Request;
BOOLEAN Success;
ASSERT(FileNode == FileDesc->FileNode); ASSERT(FileNode == FileDesc->FileNode);
@ -228,10 +232,42 @@ static NTSTATUS FspFsvolReadNonCached(
return Result; return Result;
} }
/* acquire FileNode exclusive Full */
Success = DEBUGTEST(90, TRUE) &&
FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, CanWait);
if (!Success)
return FspWqRepostIrpWorkItem(Irp, FspFsvolReadNonCached, 0);
/* if this is a non-cached transfer on a cached file then flush the file */
if (!PagingIo && 0 != FileObject->SectionObjectPointer->DataSectionObject)
{
if (!CanWait)
{
FspFileNodeRelease(FileNode, Full);
return FspWqRepostIrpWorkItem(Irp, FspFsvolReadNonCached, 0);
}
Result = FspFileNodeFlushAndPurgeCache(FileNode,
IrpSp->Parameters.Read.ByteOffset.QuadPart,
IrpSp->Parameters.Read.Length,
FALSE);
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return Result;
}
}
/* convert FileNode to shared */
FspFileNodeConvertExclusiveToShared(FileNode, Full);
/* create request */ /* create request */
Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolReadNonCachedRequestFini, &Request); Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolReadNonCachedRequestFini, &Request);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return Result; return Result;
}
Request->Kind = FspFsctlTransactReadKind; Request->Kind = FspFsctlTransactReadKind;
Request->Req.Read.UserContext = FileNode->UserContext; Request->Req.Read.UserContext = FileNode->UserContext;
@ -240,6 +276,9 @@ static NTSTATUS FspFsvolReadNonCached(
Request->Req.Read.Length = ReadLength; Request->Req.Read.Length = ReadLength;
Request->Req.Read.Key = ReadKey; Request->Req.Read.Key = ReadKey;
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
return FSP_STATUS_IOQ_POST; return FSP_STATUS_IOQ_POST;
} }
@ -249,54 +288,16 @@ NTSTATUS FspFsvolReadPrepare(
PAGED_CODE(); PAGED_CODE();
NTSTATUS Result; NTSTATUS Result;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
FSP_SAFE_MDL *SafeMdl = 0; FSP_SAFE_MDL *SafeMdl = 0;
PVOID Address; PVOID Address;
PEPROCESS Process; PEPROCESS Process;
BOOLEAN FlushCache;
BOOLEAN Success;
FlushCache = !PagingIo && 0 != FileObject->SectionObjectPointer->DataSectionObject;
/* !!!: DataSectionObject accessed outside a lock. Hmmm! */
if (FlushCache)
Success = DEBUGTEST(90, TRUE) && FspFileNodeTryAcquireExclusive(FileNode, Full);
else
Success = DEBUGTEST(90, TRUE) && FspFileNodeTryAcquireShared(FileNode, Full);
if (!Success)
{
FspIopRetryPrepareIrp(Irp, &Result);
return Result;
}
/* if this is a non-cached transfer on a cached file then flush the file */
if (FlushCache)
{
Result = FspFileNodeFlushAndPurgeCache(FileNode,
IrpSp->Parameters.Read.ByteOffset.QuadPart,
IrpSp->Parameters.Read.Length,
FALSE);
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return Result;
}
FspFileNodeConvertExclusiveToShared(FileNode, Full);
}
/* create a "safe" MDL if necessary */ /* create a "safe" MDL if necessary */
if (!FspSafeMdlCheck(Irp->MdlAddress)) if (!FspSafeMdlCheck(Irp->MdlAddress))
{ {
Result = FspSafeMdlCreate(Irp->MdlAddress, IoWriteAccess, &SafeMdl); Result = FspSafeMdlCreate(Irp->MdlAddress, IoWriteAccess, &SafeMdl);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ return Result;
FspFileNodeRelease(FileNode, Full);
return STATUS_INSUFFICIENT_RESOURCES;
}
} }
/* map the MDL into user-mode */ /* map the MDL into user-mode */
@ -306,7 +307,6 @@ NTSTATUS FspFsvolReadPrepare(
if (0 != SafeMdl) if (0 != SafeMdl)
FspSafeMdlDelete(SafeMdl); FspSafeMdlDelete(SafeMdl);
FspFileNodeRelease(FileNode, Full);
return Result; return Result;
} }
@ -316,8 +316,6 @@ NTSTATUS FspFsvolReadPrepare(
Request->Req.Read.Address = (UINT64)(UINT_PTR)Address; Request->Req.Read.Address = (UINT64)(UINT_PTR)Address;
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl; FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
FspIopRequestContext(Request, RequestAddress) = Address; FspIopRequestContext(Request, RequestAddress) = Address;
FspIopRequestContext(Request, RequestProcess) = Process; FspIopRequestContext(Request, RequestProcess) = Process;

View File

@ -67,6 +67,7 @@ static VOID FspWqWorkRoutine(PVOID Context)
{ {
PIRP Irp = Context; PIRP Irp = Context;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
FSP_FSCTL_TRANSACT_REQ *RequestWorkItem = FspIrpRequest(Irp); FSP_FSCTL_TRANSACT_REQ *RequestWorkItem = FspIrpRequest(Irp);
FSP_WQ_REQUEST_WORK *WorkRoutine = (FSP_WQ_REQUEST_WORK *)(UINT_PTR) FSP_WQ_REQUEST_WORK *WorkRoutine = (FSP_WQ_REQUEST_WORK *)(UINT_PTR)
FspIopRequestContext(RequestWorkItem, FspWqRequestWorkRoutine); FspIopRequestContext(RequestWorkItem, FspWqRequestWorkRoutine);
@ -74,10 +75,26 @@ static VOID FspWqWorkRoutine(PVOID Context)
IoSetTopLevelIrp(Irp); IoSetTopLevelIrp(Irp);
Result = WorkRoutine(IrpSp->DeviceObject, Irp, IrpSp, TRUE); Result = WorkRoutine(DeviceObject, Irp, IrpSp, TRUE);
if (STATUS_PENDING != Result) if (STATUS_PENDING != Result)
{ {
ASSERT(0 == (FSP_STATUS_PRIVATE_BIT & Result) ||
FSP_STATUS_IOQ_POST == Result || FSP_STATUS_IOQ_POST_BEST_EFFORT == Result);
DEBUGLOGIRP(Irp, Result); DEBUGLOGIRP(Irp, Result);
if (FSP_STATUS_PRIVATE_BIT & Result)
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
FspFsvolDeviceExtension(DeviceObject);
if (!FspIoqPostIrpEx(FsvolDeviceExtension->Ioq, Irp,
FSP_STATUS_IOQ_POST_BEST_EFFORT == Result, &Result))
{
DEBUGLOG("FspIoqPostIrpEx = %s", NtStatusSym(Result));
FspIopCompleteIrp(Irp, Result);
}
}
else
FspIopCompleteIrp(Irp, Result); FspIopCompleteIrp(Irp, Result);
} }

View File

@ -13,7 +13,8 @@ static NTSTATUS FspFsvolWriteCached(
BOOLEAN CanWait); BOOLEAN CanWait);
static VOID FspFsvolWriteCachedDeferred(PVOID Context1, PVOID Context2); static VOID FspFsvolWriteCachedDeferred(PVOID Context1, PVOID Context2);
static NTSTATUS FspFsvolWriteNonCached( static NTSTATUS FspFsvolWriteNonCached(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN CanWait);
FSP_IOPREP_DISPATCH FspFsvolWritePrepare; FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete; FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
static FSP_IOP_REQUEST_FINI FspFsvolWriteNonCachedRequestFini; static FSP_IOP_REQUEST_FINI FspFsvolWriteNonCachedRequestFini;
@ -77,7 +78,7 @@ static NTSTATUS FspFsvolWrite(
!FlagOn(Irp->Flags, IRP_PAGING_IO | IRP_NOCACHE)) !FlagOn(Irp->Flags, IRP_PAGING_IO | IRP_NOCACHE))
Result = FspFsvolWriteCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp)); Result = FspFsvolWriteCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp));
else else
Result = FspFsvolWriteNonCached(FsvolDeviceObject, Irp, IrpSp); Result = FspFsvolWriteNonCached(FsvolDeviceObject, Irp, IrpSp, IoIsOperationSynchronous(Irp));
return Result; return Result;
} }
@ -235,7 +236,8 @@ static VOID FspFsvolWriteCachedDeferred(PVOID Context1, PVOID Context2)
} }
static NTSTATUS FspFsvolWriteNonCached( static NTSTATUS FspFsvolWriteNonCached(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN CanWait)
{ {
PAGED_CODE(); PAGED_CODE();
@ -254,6 +256,7 @@ static NTSTATUS FspFsvolWriteNonCached(
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO); BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
FSP_FSCTL_FILE_INFO FileInfo; FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_TRANSACT_REQ *Request; FSP_FSCTL_TRANSACT_REQ *Request;
BOOLEAN Success;
ASSERT(FileNode == FileDesc->FileNode); ASSERT(FileNode == FileDesc->FileNode);
@ -295,46 +298,21 @@ static NTSTATUS FspFsvolWriteNonCached(
return Result; return Result;
} }
/* create request */ /* acquire FileNode exclusive Full */
Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolWriteNonCachedRequestFini, &Request); Success = DEBUGTEST(90, TRUE) &&
if (!NT_SUCCESS(Result)) FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, CanWait);
return Result;
Request->Kind = FspFsctlTransactWriteKind;
Request->Req.Write.UserContext = FileNode->UserContext;
Request->Req.Write.UserContext2 = FileDesc->UserContext2;
Request->Req.Write.Offset = WriteOffset.QuadPart;
Request->Req.Write.Length = WriteLength;
Request->Req.Write.Key = WriteKey;
return FSP_STATUS_IOQ_POST;
}
NTSTATUS FspFsvolWritePrepare(
PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
{
PAGED_CODE();
NTSTATUS Result;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext;
BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
FSP_SAFE_MDL *SafeMdl = 0;
PVOID Address;
PEPROCESS Process;
BOOLEAN Success;
Success = DEBUGTEST(90, TRUE) && FspFileNodeTryAcquireExclusive(FileNode, Full);
if (!Success) if (!Success)
{ return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteNonCached, 0);
FspIopRetryPrepareIrp(Irp, &Result);
return Result;
}
/* if this is a non-cached transfer on a cached file then flush and purge the file */ /* if this is a non-cached transfer on a cached file then flush and purge the file */
if (!PagingIo && 0 != FileObject->SectionObjectPointer->DataSectionObject) if (!PagingIo && 0 != FileObject->SectionObjectPointer->DataSectionObject)
{ {
if (!CanWait)
{
FspFileNodeRelease(FileNode, Full);
return FspWqRepostIrpWorkItem(Irp, FspFsvolWriteNonCached, 0);
}
Result = FspFileNodeFlushAndPurgeCache(FileNode, Result = FspFileNodeFlushAndPurgeCache(FileNode,
IrpSp->Parameters.Write.ByteOffset.QuadPart, IrpSp->Parameters.Write.ByteOffset.QuadPart,
IrpSp->Parameters.Write.Length, IrpSp->Parameters.Write.Length,
@ -346,15 +324,43 @@ NTSTATUS FspFsvolWritePrepare(
} }
} }
/* create request */
Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolWriteNonCachedRequestFini, &Request);
if (!NT_SUCCESS(Result))
{
FspFileNodeRelease(FileNode, Full);
return Result;
}
Request->Kind = FspFsctlTransactWriteKind;
Request->Req.Write.UserContext = FileNode->UserContext;
Request->Req.Write.UserContext2 = FileDesc->UserContext2;
Request->Req.Write.Offset = WriteOffset.QuadPart;
Request->Req.Write.Length = WriteLength;
Request->Req.Write.Key = WriteKey;
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
return FSP_STATUS_IOQ_POST;
}
NTSTATUS FspFsvolWritePrepare(
PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
{
PAGED_CODE();
NTSTATUS Result;
FSP_SAFE_MDL *SafeMdl = 0;
PVOID Address;
PEPROCESS Process;
/* create a "safe" MDL if necessary */ /* create a "safe" MDL if necessary */
if (!FspSafeMdlCheck(Irp->MdlAddress)) if (!FspSafeMdlCheck(Irp->MdlAddress))
{ {
Result = FspSafeMdlCreate(Irp->MdlAddress, IoReadAccess, &SafeMdl); Result = FspSafeMdlCreate(Irp->MdlAddress, IoReadAccess, &SafeMdl);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ return Result;
FspFileNodeRelease(FileNode, Full);
return STATUS_INSUFFICIENT_RESOURCES;
}
} }
/* map the MDL into user-mode */ /* map the MDL into user-mode */
@ -364,7 +370,6 @@ NTSTATUS FspFsvolWritePrepare(
if (0 != SafeMdl) if (0 != SafeMdl)
FspSafeMdlDelete(SafeMdl); FspSafeMdlDelete(SafeMdl);
FspFileNodeRelease(FileNode, Full);
return Result; return Result;
} }
@ -374,8 +379,6 @@ NTSTATUS FspFsvolWritePrepare(
Request->Req.Write.Address = (UINT64)(UINT_PTR)Address; Request->Req.Write.Address = (UINT64)(UINT_PTR)Address;
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl; FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl;
FspIopRequestContext(Request, RequestAddress) = Address; FspIopRequestContext(Request, RequestAddress) = Address;
FspIopRequestContext(Request, RequestProcess) = Process; FspIopRequestContext(Request, RequestProcess) = Process;