mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
Experimental fix for github issue #45
This commit is contained in:
parent
46d5c98926
commit
ccd4bb869c
@ -80,8 +80,18 @@ static NTSTATUS FspFsvolClose(
|
||||
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */
|
||||
FspFileNodeDereference(FileNode);
|
||||
|
||||
/* if we are closing files in the context of a rename make it synchronous */
|
||||
if (FspFsvolDeviceFileRenameIsAcquiredExclusive(FsvolDeviceObject))
|
||||
{
|
||||
/* acquire ownership of the Request */
|
||||
Request->Hint = (UINT_PTR)Irp;
|
||||
FspIrpSetRequest(Irp, Request);
|
||||
|
||||
return FSP_STATUS_IOQ_POST_BEST_EFFORT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Post as a BestEffort work request. This allows us to complete our own IRP
|
||||
* Post as a BestEffort WORK request. This allows us to complete our own IRP
|
||||
* and return immediately.
|
||||
*/
|
||||
FspIopPostWorkRequestBestEffort(FsvolDeviceObject, Request);
|
||||
|
@ -41,6 +41,7 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
|
||||
@ -80,6 +81,7 @@ VOID FspDeviceDeleteAll(VOID);
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameIsAcquiredExclusive)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
|
||||
@ -574,6 +576,15 @@ VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Own
|
||||
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner);
|
||||
}
|
||||
|
||||
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
||||
|
||||
return ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->FileRenameResource);
|
||||
}
|
||||
|
||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
@ -1064,6 +1064,7 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -1243,6 +1243,50 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
|
||||
}
|
||||
}
|
||||
|
||||
/* flush and purge cleaned up but still open files affected by rename (github issue #45) */
|
||||
{
|
||||
PIRP TopLevelIrp;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
/* reset the top-level IRP to avoid deadlock on the FileNodes' resources */
|
||||
TopLevelIrp = IoGetTopLevelIrp();
|
||||
IoSetTopLevelIrp(0);
|
||||
|
||||
/* enumerate in reverse order so that files are flushed before containing directories */
|
||||
for (
|
||||
DescendantFileNodeIndex = DescendantFileNodeCount - 1;
|
||||
DescendantFileNodeCount > DescendantFileNodeIndex;
|
||||
DescendantFileNodeIndex--)
|
||||
{
|
||||
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
|
||||
HasHandles = (UINT_PTR)DescendantFileNode & 1;
|
||||
DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7);
|
||||
|
||||
if (HasHandles)
|
||||
continue;
|
||||
if (CheckingOldName &&
|
||||
(DescendantFileNode->FileName.Length <= FileName->Length ||
|
||||
L'\\' != DescendantFileNode->FileName.Buffer[FileName->Length / sizeof(WCHAR)]))
|
||||
continue;
|
||||
if (MmDoesFileHaveUserWritableReferences(&DescendantFileNode->NonPaged->SectionObjectPointers))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* There are no handles and no writable user mappings. [Ideally we would want to know
|
||||
* that there are no handles and no user mappings, period. Is there an DDI/method to
|
||||
* do that?] There may be a read-only user mapping, but in this case CcFlushCache
|
||||
* should be a no-op and MmForceSectionClosed will fail (which is fine).
|
||||
*/
|
||||
|
||||
ASSERT(DescendantFileNode != FileNode && DescendantFileNode->MainFileNode != FileNode);
|
||||
|
||||
FspCcFlushCache(&DescendantFileNode->NonPaged->SectionObjectPointers, 0, 0, &IoStatus);
|
||||
MmForceSectionClosed(&DescendantFileNode->NonPaged->SectionObjectPointers, FALSE);
|
||||
}
|
||||
|
||||
IoSetTopLevelIrp(TopLevelIrp);
|
||||
}
|
||||
|
||||
/* break any Batch or Handle oplocks on descendants */
|
||||
Result = STATUS_SUCCESS;
|
||||
for (
|
||||
|
Loading…
x
Reference in New Issue
Block a user