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 */
|
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */
|
||||||
FspFileNodeDereference(FileNode);
|
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.
|
* and return immediately.
|
||||||
*/
|
*/
|
||||||
FspIopPostWorkRequestBestEffort(FsvolDeviceObject, Request);
|
FspIopPostWorkRequestBestEffort(FsvolDeviceObject, Request);
|
||||||
|
@ -41,6 +41,7 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
|||||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||||
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject,
|
||||||
@ -80,6 +81,7 @@ VOID FspDeviceDeleteAll(VOID);
|
|||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolDeviceFileRenameIsAcquiredExclusive)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable)
|
#pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable)
|
#pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
|
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
|
||||||
@ -574,6 +576,15 @@ VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Own
|
|||||||
ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner);
|
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)
|
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
@ -1064,6 +1064,7 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject);
|
|||||||
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner);
|
||||||
|
BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject);
|
||||||
NTSTATUS FspFsvolDeviceCopyContextList(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 */
|
/* break any Batch or Handle oplocks on descendants */
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
for (
|
for (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user