sys: FspFileNodeCleanupFlush:

- CcFlushCache now happens during initial Cleanup call
- avoids recursive call into file system during Cleanup completion
This commit is contained in:
Bill Zissimopoulos 2018-04-23 14:30:38 -07:00
parent 157c4bc09a
commit c2f87029d7
No known key found for this signature in database
GPG Key ID: 3D4F95D52C7B3EA3
3 changed files with 62 additions and 19 deletions

View File

@ -123,6 +123,8 @@ static NTSTATUS FspFsvolCleanup(
FspFileNodeSetOwner(FileNode, Full, Request); FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp; FspIopRequestContext(Request, RequestIrp) = Irp;
FspFileNodeCleanupFlush(FileNode, FileObject);
if (Request->Req.Cleanup.Delete || if (Request->Req.Cleanup.Delete ||
Request->Req.Cleanup.SetAllocationSize || Request->Req.Cleanup.SetAllocationSize ||
Request->Req.Cleanup.SetArchiveBit || Request->Req.Cleanup.SetArchiveBit ||
@ -228,10 +230,9 @@ static VOID FspFsvolCleanupRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Co
ASSERT(FileNode == FileDesc->FileNode); ASSERT(FileNode == FileDesc->FileNode);
FspFileNodeCleanupComplete(FileNode, FileObject);
FspFileNodeReleaseOwner(FileNode, Pgio, Request); FspFileNodeReleaseOwner(FileNode, Pgio, Request);
FspFileNodeCleanupComplete(FileNode, FileObject);
if (!FileNode->IsDirectory) if (!FileNode->IsDirectory)
FspFileNodeOplockCheck(FileNode, Irp); FspFileNodeOplockCheck(FileNode, Irp);
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE); SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);

View File

@ -1358,6 +1358,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
UINT32 GrantedAccess, UINT32 ShareAccess, UINT32 GrantedAccess, UINT32 ShareAccess,
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason); FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags); VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
PFILE_OBJECT FileObject, /* non-0 to remove share access */ PFILE_OBJECT FileObject, /* non-0 to remove share access */

View File

@ -37,6 +37,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
UINT32 GrantedAccess, UINT32 ShareAccess, UINT32 GrantedAccess, UINT32 ShareAccess,
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason); FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags); VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
PFILE_OBJECT FileObject, /* non-0 to remove share access */ PFILE_OBJECT FileObject, /* non-0 to remove share access */
@ -121,6 +122,7 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp);
#pragma alloc_text(PAGE, FspFileNodeReleaseOwnerF) #pragma alloc_text(PAGE, FspFileNodeReleaseOwnerF)
#pragma alloc_text(PAGE, FspFileNodeOpen) #pragma alloc_text(PAGE, FspFileNodeOpen)
#pragma alloc_text(PAGE, FspFileNodeCleanup) #pragma alloc_text(PAGE, FspFileNodeCleanup)
#pragma alloc_text(PAGE, FspFileNodeCleanupFlush)
#pragma alloc_text(PAGE, FspFileNodeCleanupComplete) #pragma alloc_text(PAGE, FspFileNodeCleanupComplete)
#pragma alloc_text(PAGE, FspFileNodeClose) #pragma alloc_text(PAGE, FspFileNodeClose)
#pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache) #pragma alloc_text(PAGE, FspFileNodeFlushAndPurgeCache)
@ -772,6 +774,59 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG
*PCleanupFlags = SingleHandle ? DeletePending | (SetAllocationSize << 1) : 0; *PCleanupFlags = SingleHandle ? DeletePending | (SetAllocationSize << 1) : 0;
} }
VOID FspFileNodeCleanupFlush(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
{
/*
* Optionally flush the FileNode during Cleanup.
*
* The FileNode must be acquired exclusive (Full) when calling this function.
*/
PAGED_CODE();
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
if (!FsvolDeviceExtension->VolumeParams.FlushAndPurgeOnCleanup)
return; /* nothing to do! */
BOOLEAN DeletePending, SingleHandle;
LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
DeletePending = 0 != FileNode->DeletePending;
MemoryBarrier();
SingleHandle = 1 == FileNode->HandleCount;
if (SingleHandle && FileNode->TruncateOnClose)
{
/*
* Even when the FileInfo is expired, this is the best guess for a file size
* without asking the user-mode file system.
*/
TruncateSize = FileNode->Header.FileSize;
PTruncateSize = &TruncateSize;
}
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
/* Flush and purge on last Cleanup. Keeps files off the "standby" list. (GitHub issue #104) */
if (SingleHandle && !DeletePending)
{
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER ZeroOffset = { 0 };
if (0 != PTruncateSize && 0 == PTruncateSize->HighPart)
FspCcFlushCache(FileObject->SectionObjectPointer, &ZeroOffset, PTruncateSize->LowPart,
&IoStatus);
else
FspCcFlushCache(FileObject->SectionObjectPointer, 0, 0,
&IoStatus);
}
}
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject) VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
{ {
/* /*
@ -791,7 +846,7 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
LARGE_INTEGER TruncateSize, *PTruncateSize = 0; LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
BOOLEAN DeletePending = FALSE, DeletedFromContextTable = FALSE, SingleHandle = FALSE; BOOLEAN DeletePending, DeletedFromContextTable = FALSE, SingleHandle = FALSE;
FspFsvolDeviceLockContextTable(FsvolDeviceObject); FspFsvolDeviceLockContextTable(FsvolDeviceObject);
@ -915,22 +970,8 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
* So we deem this difference in behavior ok and desirable. * So we deem this difference in behavior ok and desirable.
*/ */
if (!DeletePending) TruncateSize.QuadPart = 0;
{ PTruncateSize = &TruncateSize;
/* NOTE: Do not use FspFileNodeFlushAndPurgeCache. It does not work well in CLEANUP! */
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER ZeroOffset = { 0 };
if (0 != PTruncateSize && 0 == PTruncateSize->HighPart)
FspCcFlushCache(FileObject->SectionObjectPointer, &ZeroOffset, PTruncateSize->LowPart,
&IoStatus);
else
FspCcFlushCache(FileObject->SectionObjectPointer, 0, 0,
&IoStatus);
}
CcPurgeCacheSection(FileObject->SectionObjectPointer, 0, 0, TRUE);
} }
CcUninitializeCacheMap(FileObject, PTruncateSize, 0); CcUninitializeCacheMap(FileObject, PTruncateSize, 0);