mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-14 15:52:47 -05:00
sys,dll: Cleanup/TruncateOnClose overhaul
This commit is contained in:
@ -875,7 +875,12 @@ FSP_API NTSTATUS FspFileSystemOpCleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
FileSystem->Interface->Cleanup(FileSystem,
|
||||
(PVOID)ValOfFileContext(Request->Req.Cleanup),
|
||||
0 != Request->FileName.Size ? (PWSTR)Request->Buffer : 0,
|
||||
0 != Request->Req.Cleanup.Delete);
|
||||
(0 != Request->Req.Cleanup.Delete ? FspCleanupDelete : 0) |
|
||||
(0 != Request->Req.Cleanup.SetAllocationSize ? FspCleanupSetAllocationSize : 0) |
|
||||
(0 != Request->Req.Cleanup.SetArchiveBit ? FspCleanupSetArchiveBit : 0) |
|
||||
(0 != Request->Req.Cleanup.SetLastAccessTime ? FspCleanupSetLastAccessTime : 0) |
|
||||
(0 != Request->Req.Cleanup.SetLastWriteTime ? FspCleanupSetLastWriteTime : 0) |
|
||||
(0 != Request->Req.Cleanup.SetChangeTime ? FspCleanupSetChangeTime : 0));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -523,7 +523,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
||||
opt_data.VolumeParams.NamedStreams = FALSE;
|
||||
opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume;
|
||||
opt_data.VolumeParams.PostCleanupOnDeleteOnly = TRUE;
|
||||
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
|
||||
opt_data.VolumeParams.UmFileContextIsUserContext2 = TRUE;
|
||||
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
||||
memcpy(opt_data.VolumeParams.FileSystemName, L"FUSE", 5 * sizeof(WCHAR));
|
||||
|
@ -1050,7 +1050,7 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
|
||||
static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PWSTR FileName, BOOLEAN Delete)
|
||||
PVOID FileNode, PWSTR FileName, ULONG Flags)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = FileNode;
|
||||
@ -1072,7 +1072,7 @@ static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
* FUSE option and can safely remove the file at this time.
|
||||
*/
|
||||
|
||||
if (Delete)
|
||||
if (Flags & FspCleanupDelete)
|
||||
if (filedesc->IsDirectory && !filedesc->IsReparsePoint)
|
||||
{
|
||||
if (0 != f->ops.rmdir)
|
||||
|
@ -77,13 +77,17 @@ static NTSTATUS FspFsvolCleanup(
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
BOOLEAN DeletePending;
|
||||
ULONG CleanupFlags;
|
||||
BOOLEAN DeletePending, SetAllocationSize, FileModified;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
FspFileNodeAcquireExclusive(FileNode, Main);
|
||||
|
||||
FspFileNodeCleanup(FileNode, FileObject, &DeletePending);
|
||||
FspFileNodeCleanup(FileNode, FileObject, &CleanupFlags);
|
||||
DeletePending = CleanupFlags & 1;
|
||||
SetAllocationSize = !!(CleanupFlags & 2);
|
||||
FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
|
||||
|
||||
/* if this is a directory inform the FSRTL Notify mechanism */
|
||||
if (FileNode->IsDirectory)
|
||||
@ -106,13 +110,23 @@ static NTSTATUS FspFsvolCleanup(
|
||||
Request->Req.Cleanup.UserContext = FileNode->UserContext;
|
||||
Request->Req.Cleanup.UserContext2 = FileDesc->UserContext2;
|
||||
Request->Req.Cleanup.Delete = DeletePending;
|
||||
Request->Req.Cleanup.SetAllocationSize = SetAllocationSize;
|
||||
Request->Req.Cleanup.SetArchiveBit = FileModified;
|
||||
Request->Req.Cleanup.SetLastAccessTime = !FileDesc->DidSetLastAccessTime;
|
||||
Request->Req.Cleanup.SetLastWriteTime = FileModified && !FileDesc->DidSetLastWriteTime;
|
||||
Request->Req.Cleanup.SetChangeTime = FileModified;
|
||||
|
||||
FspFileNodeAcquireExclusive(FileNode, Pgio);
|
||||
|
||||
FspFileNodeSetOwner(FileNode, Full, Request);
|
||||
FspIopRequestContext(Request, RequestIrp) = Irp;
|
||||
|
||||
if (DeletePending || !FsvolDeviceExtension->VolumeParams.PostCleanupOnDeleteOnly)
|
||||
if (Request->Req.Cleanup.Delete ||
|
||||
Request->Req.Cleanup.SetAllocationSize ||
|
||||
Request->Req.Cleanup.SetArchiveBit ||
|
||||
Request->Req.Cleanup.SetLastWriteTime ||
|
||||
Request->Req.Cleanup.SetChangeTime ||
|
||||
!FsvolDeviceExtension->VolumeParams.PostCleanupWhenModifiedOnly)
|
||||
/*
|
||||
* Note that it is still possible for this request to not be delivered,
|
||||
* if the volume device Ioq is stopped. But such failures are benign
|
||||
|
@ -1025,6 +1025,10 @@ NTSTATUS FspFsvolCreateComplete(
|
||||
if (0 == FileNode->MainFileNode)
|
||||
FspFileNodeOverwriteStreams(FileNode);
|
||||
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Overwrite.FileInfo);
|
||||
|
||||
if (0 != Response->Rsp.Overwrite.FileInfo.AllocationSize)
|
||||
FileNode->TruncateOnClose = TRUE;
|
||||
|
||||
FspFileNodeNotifyChange(FileNode,
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE,
|
||||
FILE_ACTION_MODIFIED);
|
||||
@ -1115,9 +1119,14 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
|
||||
}
|
||||
|
||||
if (FILE_CREATED == Response->IoStatus.Information)
|
||||
{
|
||||
if (0 != Response->Rsp.Create.Opened.FileInfo.AllocationSize)
|
||||
FileNode->TruncateOnClose = TRUE;
|
||||
|
||||
FspFileNodeNotifyChange(FileNode,
|
||||
FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
|
||||
FILE_ACTION_ADDED);
|
||||
}
|
||||
|
||||
FspFileNodeRelease(FileNode, Main);
|
||||
|
||||
|
@ -1200,6 +1200,7 @@ typedef struct
|
||||
BOOLEAN CaseSensitive;
|
||||
BOOLEAN HasTraversePrivilege;
|
||||
BOOLEAN DeleteOnClose;
|
||||
BOOLEAN DidSetLastAccessTime, DidSetLastWriteTime;
|
||||
BOOLEAN DirectoryHasSuchFile;
|
||||
UNICODE_STRING DirectoryPattern;
|
||||
UINT64 DirectoryOffset;
|
||||
@ -1259,8 +1260,7 @@ VOID FspFileNodeReleaseForeign(FSP_FILE_NODE *FileNode)
|
||||
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
PBOOLEAN PDeletePending);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||
|
@ -34,8 +34,7 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
|
||||
NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
UINT32 GrantedAccess, UINT32 ShareAccess,
|
||||
FSP_FILE_NODE **POpenedFileNode, PULONG PSharingViolationReason);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
PBOOLEAN PDeletePending);
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags);
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
|
||||
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode,
|
||||
PFILE_OBJECT FileObject, /* non-0 to remove share access */
|
||||
@ -635,8 +634,7 @@ exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
PBOOLEAN PDeletePending)
|
||||
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, PULONG PCleanupFlags)
|
||||
{
|
||||
/*
|
||||
* Determine whether a FileNode should be deleted. Note that when FileNode->DeletePending
|
||||
@ -650,7 +648,7 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
BOOLEAN DeletePending, SingleHandle;
|
||||
BOOLEAN DeletePending, SetAllocationSize, SingleHandle;
|
||||
|
||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||
|
||||
@ -659,12 +657,13 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
|
||||
DeletePending = 0 != FileNode->DeletePending;
|
||||
MemoryBarrier();
|
||||
|
||||
SetAllocationSize = !DeletePending && FileNode->TruncateOnClose;
|
||||
|
||||
SingleHandle = 1 == FileNode->HandleCount;
|
||||
|
||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||
|
||||
if (0 != PDeletePending)
|
||||
*PDeletePending = SingleHandle && DeletePending;
|
||||
*PCleanupFlags = SingleHandle ? DeletePending | (SetAllocationSize << 1) : 0;
|
||||
}
|
||||
|
||||
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject)
|
||||
@ -684,7 +683,7 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
PAGED_CODE();
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||
LARGE_INTEGER TruncateSize = { 0 }, *PTruncateSize = 0;
|
||||
LARGE_INTEGER TruncateSize, *PTruncateSize = 0;
|
||||
BOOLEAN DeletePending;
|
||||
BOOLEAN DeletedFromContextTable = FALSE;
|
||||
|
||||
@ -715,23 +714,34 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
|
||||
|
||||
if (DeletePending)
|
||||
{
|
||||
PTruncateSize = &TruncateSize;
|
||||
|
||||
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName,
|
||||
&DeletedFromContextTable);
|
||||
ASSERT(DeletedFromContextTable);
|
||||
|
||||
FileNode->OpenCount = 0;
|
||||
FileNode->Header.FileSize.QuadPart = 0;
|
||||
}
|
||||
else if (FileNode->TruncateOnClose && FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
|
||||
|
||||
if (DeletePending || FileNode->TruncateOnClose)
|
||||
{
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||
FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
UINT64 AllocationUnit =
|
||||
FsvolDeviceExtension->VolumeParams.SectorSize *
|
||||
FsvolDeviceExtension->VolumeParams.SectorsPerAllocationUnit;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
FileNode->Header.AllocationSize.QuadPart = (TruncateSize.QuadPart + AllocationUnit - 1)
|
||||
/ AllocationUnit * AllocationUnit;
|
||||
}
|
||||
|
||||
FileNode->TruncateOnClose = FALSE;
|
||||
}
|
||||
|
||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||
|
@ -956,8 +956,11 @@ static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject,
|
||||
else
|
||||
{
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
ULONG NotifyFilter = 0;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
if (!FileNode->IsDirectory)
|
||||
{
|
||||
/* properly set temporary bit for lazy writer */
|
||||
@ -975,9 +978,15 @@ static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject,
|
||||
if (0 != Request->Req.SetInformation.Info.Basic.CreationTime)
|
||||
NotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;
|
||||
if (0 != Request->Req.SetInformation.Info.Basic.LastAccessTime)
|
||||
{
|
||||
FileDesc->DidSetLastAccessTime = TRUE;
|
||||
NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
|
||||
}
|
||||
if (0 != Request->Req.SetInformation.Info.Basic.LastWriteTime)
|
||||
{
|
||||
FileDesc->DidSetLastWriteTime = TRUE;
|
||||
NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||
}
|
||||
FspFileNodeNotifyChange(FileNode, NotifyFilter, FILE_ACTION_MODIFIED);
|
||||
}
|
||||
|
||||
|
@ -195,6 +195,7 @@ static NTSTATUS FspFsvolWriteCached(
|
||||
{
|
||||
ASSERT(CanWait);
|
||||
|
||||
/* send EndOfFileInformation IRP; this will also set TruncateOnClose, etc. */
|
||||
EndOfFileInformation.EndOfFile.QuadPart = WriteEndOffset;
|
||||
Result = FspSendSetInformationIrp(FsvolDeviceObject/* bypass filters */, FileObject,
|
||||
FileEndOfFileInformation, &EndOfFileInformation, sizeof EndOfFileInformation);
|
||||
@ -471,11 +472,14 @@ NTSTATUS FspFsvolWriteComplete(
|
||||
/* update file info */
|
||||
FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Write.FileInfo);
|
||||
|
||||
if (OriginalFileSize != Response->Rsp.Write.FileInfo.FileSize)
|
||||
if (!PagingIo && OriginalFileSize != Response->Rsp.Write.FileInfo.FileSize)
|
||||
{
|
||||
FileNode->TruncateOnClose = TRUE;
|
||||
FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED);
|
||||
}
|
||||
|
||||
/* update the current file offset if synchronous I/O (and not paging I/O) */
|
||||
if (SynchronousIo && !PagingIo)
|
||||
if (!PagingIo && SynchronousIo)
|
||||
FileObject->CurrentByteOffset.QuadPart = WriteToEndOfFile ?
|
||||
Response->Rsp.Write.FileInfo.FileSize :
|
||||
WriteOffset.QuadPart + Response->IoStatus.Information;
|
||||
|
Reference in New Issue
Block a user