sys,dll: Cleanup/TruncateOnClose overhaul

This commit is contained in:
Bill Zissimopoulos 2016-12-21 16:09:24 -08:00
parent 8d6314e2db
commit c897ddd864
13 changed files with 203 additions and 69 deletions

View File

@ -146,7 +146,7 @@ typedef struct
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
UINT32 ReadOnlyVolume:1;
/* kernel-mode flags */
UINT32 PostCleanupOnDeleteOnly:1; /* post Cleanup when deleting a file only */
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
UINT32 KmReservedFlags:5;
/* user-mode flags */
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
@ -248,6 +248,11 @@ typedef struct
UINT64 UserContext;
UINT64 UserContext2;
UINT32 Delete:1; /* file must be deleted */
UINT32 SetAllocationSize:1;
UINT32 SetArchiveBit:1;
UINT32 SetLastAccessTime:1;
UINT32 SetLastWriteTime:1;
UINT32 SetChangeTime:1;
} Cleanup;
struct
{

View File

@ -122,6 +122,15 @@ typedef enum
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE = 0,
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE,
} FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY;
enum
{
FspCleanupDelete = 0x01,
FspCleanupSetAllocationSize = 0x02,
FspCleanupSetArchiveBit = 0x10,
FspCleanupSetLastAccessTime = 0x20,
FspCleanupSetLastWriteTime = 0x40,
FspCleanupSetChangeTime = 0x80,
};
/**
* @class FSP_FILE_SYSTEM
* File system interface.
@ -332,8 +341,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* deleted during Cleanup.
*
* As an optimization a file system may specify the FSP_FSCTL_VOLUME_PARAMS ::
* PostCleanupOnDeleteOnly flag. In this case the FSD will only post Cleanup requests when a
* file is being deleted.
* PostCleanupWhenModifiedOnly flag. In this case the FSD will only post Cleanup requests when
* the file was modified/deleted.
*
* @param FileSystem
* The file system on which this request is posted.
@ -341,16 +350,17 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
* The file context of the file or directory to cleanup.
* @param FileName
* The name of the file or directory to cleanup. Sent only when a Delete is requested.
* @param Delete
* Determines whether to delete the file. Note that there is no way to report failure of
* this operation. Also note that when this parameter is TRUE this is the last outstanding
* cleanup for this particular file node.
* @param Flags
* These flags determine whether the file was modified and whether to delete the file.
* Note that there is no way to report failure of this operation. Also note that when
* this parameter has the FspCleanupDelete bit set, this is the last outstanding cleanup
* for this particular file node.
* @see
* Close
* CanDelete
*/
VOID (*Cleanup)(FSP_FILE_SYSTEM *FileSystem,
PVOID FileContext, PWSTR FileName, BOOLEAN Delete);
PVOID FileContext, PWSTR FileName, ULONG Flags);
/**
* Close a file.
*

View File

@ -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;
}

View File

@ -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));

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -627,9 +627,8 @@ static NTSTATUS GetReparsePointByName(
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize);
#endif
static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo);
static NTSTATUS SetFileSizeInternal(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize);
static NTSTATUS GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_VOLUME_INFO *VolumeInfo)
@ -888,21 +887,6 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
return Result;
}
/*
* NTFS and FastFat do this at Cleanup time, but we are going to cheat.
*
* To properly implement this we should maintain some state of whether
* we modified the file or not. Alternatively we could have the driver
* report to us at Cleanup time whether the file was modified. [The
* FSD does maintain the FO_FILE_MODIFIED bit, but does not send it
* to us.]
*
* TBD.
*/
if (0 == (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
MemfsFileNodeReference(FileNode);
*PFileNode = FileNode;
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
@ -944,7 +928,7 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
MemfsFileNodeMapEnumerateFree(&Context);
#endif
Result = SetFileSize(FileSystem, FileNode, AllocationSize, TRUE, FileInfo);
Result = SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
if (!NT_SUCCESS(Result))
return Result;
@ -954,8 +938,9 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
FileNode->FileInfo.FileAttributes |= FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
FileNode->FileInfo.FileSize = 0;
FileNode->FileInfo.LastAccessTime =
FileNode->FileInfo.LastWriteTime =
FileNode->FileInfo.LastAccessTime = MemfsGetSystemTime();
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
@ -963,14 +948,41 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
}
static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode0, PWSTR FileName, BOOLEAN Delete)
PVOID FileNode0, PWSTR FileName, ULONG Flags)
{
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
assert(Delete); /* the new FSP_FSCTL_VOLUME_PARAMS::PostCleanupOnDeleteOnly ensures this */
assert(0 != Flags); /* FSP_FSCTL_VOLUME_PARAMS::PostCleanupWhenModifiedOnly ensures this */
if (Delete && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
if (Flags & FspCleanupSetArchiveBit)
{
if (0 == (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
}
if (Flags & (FspCleanupSetLastAccessTime | FspCleanupSetLastWriteTime | FspCleanupSetChangeTime))
{
UINT64 SystemTime = MemfsGetSystemTime();
if (Flags & FspCleanupSetLastAccessTime)
FileNode->FileInfo.LastAccessTime = SystemTime;
if (Flags & FspCleanupSetLastWriteTime)
FileNode->FileInfo.LastWriteTime = SystemTime;
if (Flags & FspCleanupSetChangeTime)
FileNode->FileInfo.ChangeTime = SystemTime;
}
if (Flags & FspCleanupSetAllocationSize)
{
UINT64 AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT;
UINT64 AllocationSize = (FileNode->FileInfo.FileSize + AllocationUnit - 1) /
AllocationUnit * AllocationUnit;
SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
}
if ((Flags & FspCleanupDelete) && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
{
#if defined(MEMFS_NAMED_STREAMS)
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { FALSE };
@ -1062,7 +1074,7 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem,
EndOffset = Offset + Length;
if (EndOffset > FileNode->FileInfo.FileSize)
{
Result = SetFileSize(FileSystem, FileNode, EndOffset, FALSE, FileInfo);
Result = SetFileSizeInternal(FileSystem, FileNode, EndOffset, FALSE);
if (!NT_SUCCESS(Result))
return Result;
}
@ -1077,9 +1089,19 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem,
}
NTSTATUS Flush(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode)
PVOID FileNode0)
{
/* nothing to do, since we do not cache anything */
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
/* nothing to flush, since we do not cache anything */
if (0 != FileNode)
{
FileNode->FileInfo.LastAccessTime =
FileNode->FileInfo.LastWriteTime =
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
}
return STATUS_SUCCESS;
}
@ -1120,9 +1142,8 @@ static NTSTATUS SetBasicInfo(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS;
}
static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo)
static NTSTATUS SetFileSizeInternal(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize)
{
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
@ -1154,8 +1175,7 @@ static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
UINT64 AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT;
UINT64 AllocationSize = (NewSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
NTSTATUS Result = SetFileSize(FileSystem, FileNode, AllocationSize, TRUE,
FileInfo);
NTSTATUS Result = SetFileSizeInternal(FileSystem, FileNode, AllocationSize, TRUE);
if (!NT_SUCCESS(Result))
return Result;
}
@ -1167,6 +1187,24 @@ static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
}
}
return STATUS_SUCCESS;
}
static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode0, UINT64 NewSize, BOOLEAN SetAllocationSize,
FSP_FSCTL_FILE_INFO *FileInfo)
{
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
NTSTATUS Result;
Result = SetFileSizeInternal(FileSystem, FileNode0, NewSize, SetAllocationSize);
if (!NT_SUCCESS(Result))
return Result;
FileNode->FileInfo.LastAccessTime =
FileNode->FileInfo.LastWriteTime =
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
return STATUS_SUCCESS;
@ -1319,6 +1357,8 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
FileNode->FileSecuritySize = FileSecuritySize;
FileNode->FileSecurity = FileSecurity;
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
return STATUS_SUCCESS;
}
@ -1523,6 +1563,8 @@ static NTSTATUS SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
FileNode->ReparseData = ReparseData;
memcpy(FileNode->ReparseData, Buffer, Size);
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
return STATUS_SUCCESS;
}
@ -1556,6 +1598,8 @@ static NTSTATUS DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem,
FileNode->ReparseDataSize = 0;
FileNode->ReparseData = 0;
FileNode->FileInfo.ChangeTime = MemfsGetSystemTime();
return STATUS_SUCCESS;
}
#endif
@ -1737,7 +1781,7 @@ NTSTATUS MemfsCreateFunnel(
#if defined(MEMFS_NAMED_STREAMS)
VolumeParams.NamedStreams = 1;
#endif
VolumeParams.PostCleanupOnDeleteOnly = 1;
VolumeParams.PostCleanupWhenModifiedOnly = 1;
if (0 != VolumePrefix)
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
wcscpy_s(VolumeParams.FileSystemName, sizeof VolumeParams.FileSystemName / sizeof(WCHAR),

View File

@ -288,9 +288,9 @@ void create_related_test(void)
create_related_dotest(MemfsNet, L"\\\\memfs\\share");
}
void create_allocation_dotest(ULONG Flags, PWSTR Prefix)
void create_allocation_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
{
void *memfs = memfs_start(Flags);
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
HANDLE DirHandle, FileHandle, FileHandle2;
NTSTATUS Result;
@ -346,10 +346,27 @@ void create_allocation_dotest(ULONG Flags, PWSTR Prefix)
ASSERT(Success);
ASSERT(65536 == StandardInfo.AllocationSize.QuadPart);
CloseHandle(FileHandle2);
AllocationSize.QuadPart = 0;
UnicodePath.Length = (USHORT)wcslen(UnicodePathBuf) * sizeof(WCHAR);
UnicodePath.MaximumLength = sizeof UnicodePathBuf;
UnicodePath.Buffer = UnicodePathBuf;
InitializeObjectAttributes(&Obja, &UnicodePath, 0, DirHandle, 0);
Result = NtCreateFile(&FileHandle2,
FILE_READ_ATTRIBUTES, &Obja, &Iosb,
&AllocationSize, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, 0, 0, 0);
ASSERT(STATUS_SUCCESS == Result);
Success = GetFileInformationByHandleEx(FileHandle2, FileStandardInfo, &StandardInfo, sizeof StandardInfo);
ASSERT(Success);
ASSERT(65536 == StandardInfo.AllocationSize.QuadPart);
CloseHandle(FileHandle2);
CloseHandle(FileHandle);
#if 0
AllocationSize.QuadPart = 0;
UnicodePath.Length = (USHORT)wcslen(UnicodePathBuf) * sizeof(WCHAR);
UnicodePath.MaximumLength = sizeof UnicodePathBuf;
@ -366,7 +383,6 @@ void create_allocation_dotest(ULONG Flags, PWSTR Prefix)
ASSERT(0 == StandardInfo.AllocationSize.QuadPart);
CloseHandle(FileHandle);
#endif
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir1\\file2",
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
@ -388,12 +404,20 @@ void create_allocation_test(void)
{
WCHAR DirBuf[MAX_PATH];
GetTestDirectory(DirBuf);
create_allocation_dotest(-1, DirBuf);
create_allocation_dotest(-1, DirBuf, 0);
}
if (WinFspDiskTests)
create_allocation_dotest(MemfsDisk, 0);
{
create_allocation_dotest(MemfsDisk, 0, 0);
create_allocation_dotest(MemfsDisk, 0, 1000);
create_allocation_dotest(MemfsDisk, 0, INFINITE);
}
if (WinFspNetTests)
create_allocation_dotest(MemfsNet, L"\\\\memfs\\share");
{
create_allocation_dotest(MemfsNet, L"\\\\memfs\\share", 0);
create_allocation_dotest(MemfsNet, L"\\\\memfs\\share", 1000);
create_allocation_dotest(MemfsNet, L"\\\\memfs\\share", INFINITE);
}
}
void create_sd_dotest(ULONG Flags, PWSTR Prefix)