mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
inc,sys,tst: FSP_FSCTL_VOLUME_PARAMS: fine-grained timeouts
This commit is contained in:
parent
5d34a3bd8c
commit
9501b5771d
@ -124,44 +124,64 @@ enum
|
||||
FspFsctlIrpCapacityMaximum = 1000,
|
||||
FspFsctlIrpCapacityDefault = 1000,
|
||||
};
|
||||
#define FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN\
|
||||
UINT16 Version; /* set to 0 or sizeof(FSP_FSCTL_VOLUME_PARAMS) */\
|
||||
/* volume information */\
|
||||
UINT16 SectorSize;\
|
||||
UINT16 SectorsPerAllocationUnit;\
|
||||
UINT16 MaxComponentLength; /* maximum file name component length (bytes) */\
|
||||
UINT64 VolumeCreationTime;\
|
||||
UINT32 VolumeSerialNumber;\
|
||||
/* I/O timeouts, capacity, etc. */\
|
||||
UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */\
|
||||
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */\
|
||||
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/\
|
||||
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */\
|
||||
/* FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes */\
|
||||
UINT32 CaseSensitiveSearch:1; /* file system supports case-sensitive file names */\
|
||||
UINT32 CasePreservedNames:1; /* file system preserves the case of file names */\
|
||||
UINT32 UnicodeOnDisk:1; /* file system supports Unicode in file names */\
|
||||
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */\
|
||||
UINT32 ReparsePoints:1; /* file system supports reparse points */\
|
||||
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */\
|
||||
UINT32 NamedStreams:1; /* file system supports named streams */\
|
||||
UINT32 HardLinks:1; /* unimplemented; set to 0 */\
|
||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */\
|
||||
UINT32 ReadOnlyVolume:1;\
|
||||
/* kernel-mode flags */\
|
||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */\
|
||||
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */\
|
||||
UINT32 AlwaysUseDoubleBuffering:1;\
|
||||
UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */\
|
||||
UINT32 FlushAndPurgeOnCleanup:1; /* keeps file off "standby" list */\
|
||||
UINT32 KmReservedFlags:1;\
|
||||
/* user-mode flags */\
|
||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */\
|
||||
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */\
|
||||
UINT32 UmReservedFlags:14;\
|
||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */\
|
||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||
#define FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN\
|
||||
/* additional fields; specify .Version == sizeof(FSP_FSCTL_VOLUME_PARAMS) */\
|
||||
UINT32 VolumeInfoTimeoutValid:1; /* VolumeInfoTimeout field is valid */\
|
||||
UINT32 DirInfoTimeoutValid:1; /* DirInfoTimeout field is valid */\
|
||||
UINT32 SecurityTimeoutValid:1; /* SecurityTimeout field is valid*/\
|
||||
UINT32 StreamInfoTimeoutValid:1; /* StreamInfoTimeout field is valid */\
|
||||
UINT32 KmAdditionalReservedFlags:28;\
|
||||
UINT32 VolumeInfoTimeout; /* volume info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 DirInfoTimeout; /* dir info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 SecurityTimeout; /* security info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 StreamInfoTimeout; /* stream info timeout (millis); overrides FileInfoTimeout */\
|
||||
UINT32 Reserved32[3];\
|
||||
UINT64 Reserved64[2];
|
||||
typedef struct
|
||||
{
|
||||
UINT16 Version; /* set to 0 */
|
||||
/* volume information */
|
||||
UINT16 SectorSize;
|
||||
UINT16 SectorsPerAllocationUnit;
|
||||
UINT16 MaxComponentLength; /* maximum file name component length (bytes) */
|
||||
UINT64 VolumeCreationTime;
|
||||
UINT32 VolumeSerialNumber;
|
||||
/* I/O timeouts, capacity, etc. */
|
||||
UINT32 TransactTimeout; /* FSP_FSCTL_TRANSACT timeout (millis; 1 sec - 10 sec) */
|
||||
UINT32 IrpTimeout; /* pending IRP timeout (millis; 1 min - 10 min) */
|
||||
UINT32 IrpCapacity; /* maximum number of pending IRP's (100 - 1000)*/
|
||||
UINT32 FileInfoTimeout; /* FileInfo/Security/VolumeInfo timeout (millis) */
|
||||
/* FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes */
|
||||
UINT32 CaseSensitiveSearch:1; /* file system supports case-sensitive file names */
|
||||
UINT32 CasePreservedNames:1; /* file system preserves the case of file names */
|
||||
UINT32 UnicodeOnDisk:1; /* file system supports Unicode in file names */
|
||||
UINT32 PersistentAcls:1; /* file system preserves and enforces access control lists */
|
||||
UINT32 ReparsePoints:1; /* file system supports reparse points */
|
||||
UINT32 ReparsePointsAccessCheck:1; /* file system performs reparse point access checks */
|
||||
UINT32 NamedStreams:1; /* file system supports named streams */
|
||||
UINT32 HardLinks:1; /* unimplemented; set to 0 */
|
||||
UINT32 ExtendedAttributes:1; /* unimplemented; set to 0 */
|
||||
UINT32 ReadOnlyVolume:1;
|
||||
/* kernel-mode flags */
|
||||
UINT32 PostCleanupWhenModifiedOnly:1; /* post Cleanup when a file was modified/deleted */
|
||||
UINT32 PassQueryDirectoryPattern:1; /* pass Pattern during QueryDirectory operations */
|
||||
UINT32 AlwaysUseDoubleBuffering:1;
|
||||
UINT32 PassQueryDirectoryFileName:1; /* pass FileName during QueryDirectory (GetDirInfoByName) */
|
||||
UINT32 FlushAndPurgeOnCleanup:1; /* keeps file off "standby" list */
|
||||
UINT32 KmReservedFlags:1;
|
||||
/* user-mode flags */
|
||||
UINT32 UmFileContextIsUserContext2:1; /* user mode: FileContext parameter is UserContext2 */
|
||||
UINT32 UmFileContextIsFullContext:1; /* user mode: FileContext parameter is FullContext */
|
||||
UINT32 UmReservedFlags:14;
|
||||
WCHAR Prefix[FSP_FSCTL_VOLUME_PREFIX_SIZE / sizeof(WCHAR)]; /* UNC prefix (\Server\Share) */
|
||||
WCHAR FileSystemName[FSP_FSCTL_VOLUME_FSNAME_SIZE / sizeof(WCHAR)];
|
||||
FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN
|
||||
} FSP_FSCTL_VOLUME_PARAMS_V0;
|
||||
typedef struct
|
||||
{
|
||||
FSP_FSCTL_VOLUME_PARAMS_V0_FIELD_DEFN
|
||||
FSP_FSCTL_VOLUME_PARAMS_V1_FIELD_DEFN
|
||||
} FSP_FSCTL_VOLUME_PARAMS;
|
||||
typedef struct
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
{
|
||||
NTSTATUS Result;
|
||||
PWSTR DeviceRoot;
|
||||
SIZE_T DeviceRootSize, DevicePathSize;
|
||||
SIZE_T DeviceRootSize, DevicePathSize, VolumeParamsSize;
|
||||
WCHAR DevicePathBuf[MAX_PATH + sizeof *VolumeParams], *DevicePathPtr, *DevicePathEnd;
|
||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD Bytes;
|
||||
@ -55,8 +55,11 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
memcpy(DevicePathPtr, DevicePath, DevicePathSize);
|
||||
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DevicePathSize);
|
||||
memcpy(DevicePathPtr, PREFIXW, PREFIXW_SIZE);
|
||||
VolumeParamsSize = 0 == VolumeParams->Version ?
|
||||
sizeof(FSP_FSCTL_VOLUME_PARAMS_V0) :
|
||||
VolumeParams->Version;
|
||||
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + PREFIXW_SIZE);
|
||||
DevicePathEnd = (PVOID)((PUINT8)DevicePathPtr + sizeof *VolumeParams * sizeof(WCHAR));
|
||||
DevicePathEnd = (PVOID)((PUINT8)DevicePathPtr + VolumeParamsSize * sizeof(WCHAR));
|
||||
for (PUINT8 VolumeParamsPtr = (PVOID)VolumeParams;
|
||||
DevicePathEnd > DevicePathPtr; DevicePathPtr++, VolumeParamsPtr++)
|
||||
{
|
||||
|
@ -346,7 +346,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneIoq = 1;
|
||||
|
||||
/* create our security meta cache */
|
||||
SecurityTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
SecurityTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.SecurityTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceSecurityCacheCapacity, FspFsvolDeviceSecurityCacheItemSizeMax, &SecurityTimeout,
|
||||
@ -356,7 +356,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneSec = 1;
|
||||
|
||||
/* create our directory meta cache */
|
||||
DirInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
DirInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.DirInfoTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceDirInfoCacheCapacity, FspFsvolDeviceDirInfoCacheItemSizeMax, &DirInfoTimeout,
|
||||
@ -366,7 +366,7 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
FsvolDeviceExtension->InitDoneDir = 1;
|
||||
|
||||
/* create our stream info meta cache */
|
||||
StreamInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
StreamInfoTimeout.QuadPart = FspTimeoutFromMillis(FsvolDeviceExtension->VolumeParams.StreamInfoTimeout);
|
||||
/* convert millis to nanos */
|
||||
Result = FspMetaCacheCreate(
|
||||
FspFsvolDeviceStreamInfoCacheCapacity, FspFsvolDeviceStreamInfoCacheItemSizeMax, &StreamInfoTimeout,
|
||||
@ -873,7 +873,7 @@ VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VO
|
||||
KeAcquireSpinLock(&FsvolDeviceExtension->InfoSpinLock, &Irql);
|
||||
FsvolDeviceExtension->VolumeInfo = VolumeInfoNp;
|
||||
FsvolDeviceExtension->InfoExpirationTime = FspExpirationTimeFromMillis(
|
||||
FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
|
||||
FsvolDeviceExtension->VolumeParams.VolumeInfoTimeout);
|
||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR);
|
||||
QueryDirectoryLengthMin = FSP_FSCTL_ALIGN_UP(QueryDirectoryLengthMin, 8);
|
||||
ASSERT(QueryDirectoryLengthMin < FspFsvolQueryDirectoryLengthMax);
|
||||
if (0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout &&
|
||||
if (0 != FsvolDeviceExtension->VolumeParams.DirInfoTimeout &&
|
||||
0 == FileDesc->DirectoryMarker.Buffer)
|
||||
{
|
||||
if (PatternIsFileName)
|
||||
|
@ -101,18 +101,26 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
|
||||
|
||||
/* check parameters */
|
||||
if (PREFIXW_SIZE + sizeof(FSP_FSCTL_VOLUME_PARAMS) * sizeof(WCHAR) > FileObject->FileName.Length)
|
||||
if (PREFIXW_SIZE + sizeof(FSP_FSCTL_VOLUME_PARAMS_V0) * sizeof(WCHAR) > FileObject->FileName.Length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* copy the VolumeParams */
|
||||
for (USHORT Index = 0, Length = sizeof(FSP_FSCTL_VOLUME_PARAMS); Length > Index; Index++)
|
||||
{
|
||||
if (PREFIXW_SIZE / sizeof(WCHAR) + Index >= FileObject->FileName.Length / sizeof(WCHAR))
|
||||
break;
|
||||
|
||||
WCHAR Value = FileObject->FileName.Buffer[PREFIXW_SIZE / sizeof(WCHAR) + Index];
|
||||
if (0xF000 != (Value & 0xFF00))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
((PUINT8)&VolumeParams)[Index] = Value & 0xFF;
|
||||
}
|
||||
|
||||
/* check VolumeParams size */
|
||||
if (0 != VolumeParams.Version &&
|
||||
PREFIXW_SIZE + VolumeParams.Version * sizeof(WCHAR) != FileObject->FileName.Length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* check the VolumeParams */
|
||||
if (0 == VolumeParams.SectorSize)
|
||||
VolumeParams.SectorSize = 512;
|
||||
@ -133,6 +141,28 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
if (FspFsctlIrpCapacityMinimum > VolumeParams.IrpCapacity ||
|
||||
VolumeParams.IrpCapacity > FspFsctlIrpCapacityMaximum)
|
||||
VolumeParams.IrpCapacity = FspFsctlIrpCapacityDefault;
|
||||
if (sizeof(FSP_FSCTL_VOLUME_PARAMS_V0) >= VolumeParams.Version)
|
||||
{
|
||||
VolumeParams.VolumeInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
VolumeParams.DirInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
VolumeParams.SecurityTimeout = VolumeParams.FileInfoTimeout;
|
||||
VolumeParams.StreamInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!VolumeParams.VolumeInfoTimeoutValid)
|
||||
VolumeParams.VolumeInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
if (!VolumeParams.DirInfoTimeoutValid)
|
||||
VolumeParams.DirInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
if (!VolumeParams.SecurityTimeoutValid)
|
||||
VolumeParams.SecurityTimeout = VolumeParams.FileInfoTimeout;
|
||||
if (!VolumeParams.StreamInfoTimeoutValid)
|
||||
VolumeParams.StreamInfoTimeout = VolumeParams.FileInfoTimeout;
|
||||
}
|
||||
VolumeParams.VolumeInfoTimeoutValid = 1;
|
||||
VolumeParams.DirInfoTimeoutValid = 1;
|
||||
VolumeParams.SecurityTimeoutValid = 1;
|
||||
VolumeParams.StreamInfoTimeoutValid = 1;
|
||||
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
|
||||
{
|
||||
VolumeParams.Prefix[sizeof VolumeParams.Prefix / sizeof(WCHAR) - 1] = L'\0';
|
||||
|
@ -2008,6 +2008,7 @@ NTSTATUS MemfsCreateFunnel(
|
||||
}
|
||||
|
||||
memset(&VolumeParams, 0, sizeof VolumeParams);
|
||||
VolumeParams.Version = sizeof FSP_FSCTL_VOLUME_PARAMS;
|
||||
VolumeParams.SectorSize = MEMFS_SECTOR_SIZE;
|
||||
VolumeParams.SectorsPerAllocationUnit = MEMFS_SECTORS_PER_ALLOCATION_UNIT;
|
||||
VolumeParams.VolumeCreationTime = MemfsGetSystemTime();
|
||||
|
@ -61,11 +61,40 @@ void mount_open_device_test(void)
|
||||
mount_open_device_dotest(L"WinFsp.Net");
|
||||
}
|
||||
|
||||
void mount_create_volume_v0_dotest(PWSTR DeviceName)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
BOOL Success;
|
||||
FSP_FSCTL_VOLUME_PARAMS_V0 VolumeParams = { 0 };
|
||||
WCHAR VolumeName[MAX_PATH];
|
||||
HANDLE VolumeHandle;
|
||||
|
||||
VolumeParams.SectorSize = 16384;
|
||||
VolumeParams.VolumeSerialNumber = 0x12345678;
|
||||
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), L"\\winfsp-tests\\share");
|
||||
Result = FspFsctlCreateVolume(DeviceName, (FSP_FSCTL_VOLUME_PARAMS *)&VolumeParams,
|
||||
VolumeName, sizeof VolumeName, &VolumeHandle);
|
||||
ASSERT(STATUS_SUCCESS == Result);
|
||||
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
||||
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
||||
|
||||
Success = CloseHandle(VolumeHandle);
|
||||
ASSERT(Success);
|
||||
}
|
||||
|
||||
void mount_create_volume_v0_test(void)
|
||||
{
|
||||
if (WinFspDiskTests)
|
||||
mount_create_volume_v0_dotest(L"WinFsp.Disk");
|
||||
if (WinFspNetTests)
|
||||
mount_create_volume_v0_dotest(L"WinFsp.Net");
|
||||
}
|
||||
|
||||
void mount_create_volume_dotest(PWSTR DeviceName)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
BOOL Success;
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams = { 0 };
|
||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams = { .Version = sizeof VolumeParams };
|
||||
WCHAR VolumeName[MAX_PATH];
|
||||
HANDLE VolumeHandle;
|
||||
|
||||
@ -341,6 +370,7 @@ void mount_tests(void)
|
||||
|
||||
TEST_OPT(mount_invalid_test);
|
||||
TEST_OPT(mount_open_device_test);
|
||||
TEST_OPT(mount_create_volume_v0_test);
|
||||
TEST_OPT(mount_create_volume_test);
|
||||
TEST_OPT(mount_volume_cancel_test);
|
||||
TEST_OPT(mount_volume_transact_test);
|
||||
|
Loading…
x
Reference in New Issue
Block a user