mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
Merge pull request #237 from dworkin/feature/async-dotnet
Async I/O for dotnet
This commit is contained in:
commit
f0d7e5b322
@ -386,6 +386,89 @@ namespace Fsp
|
|||||||
{
|
{
|
||||||
return Api.GetVersion();
|
return Api.GetVersion();
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a RequestHint to reference the current operation asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
public UInt64 GetOperationRequestHint()
|
||||||
|
{
|
||||||
|
return Api.FspFileSystemGetOperationRequestHint();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously complete a Write operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestHint">
|
||||||
|
/// A reference to the operation to complete.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Status">
|
||||||
|
/// STATUS_SUCCESS or error code.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="BytesTransferred">
|
||||||
|
/// The number of bytes written.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="FileInfo">
|
||||||
|
/// Updated file information.
|
||||||
|
/// </param>
|
||||||
|
public void SendWriteResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred, ref FileInfo FileInfo)
|
||||||
|
{
|
||||||
|
var Response = new FspFsctlTransactRsp()
|
||||||
|
{
|
||||||
|
Size = 128,
|
||||||
|
Kind = (UInt32) FspFsctlTransact.WriteKind,
|
||||||
|
Hint = RequestHint
|
||||||
|
};
|
||||||
|
Response.IoStatus.Information = BytesTransferred;
|
||||||
|
Response.IoStatus.Status = (UInt32) Status;
|
||||||
|
Response.WriteFileInfo = FileInfo;
|
||||||
|
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously complete a Read operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestHint">
|
||||||
|
/// A reference to the operation to complete.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Status">
|
||||||
|
/// STATUS_SUCCESS or error code.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="BytesTransferred">
|
||||||
|
/// Number of bytes read.
|
||||||
|
/// </param>
|
||||||
|
public void SendReadResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred)
|
||||||
|
{
|
||||||
|
var Response = new FspFsctlTransactRsp()
|
||||||
|
{
|
||||||
|
Size = 128,
|
||||||
|
Kind = (UInt32) FspFsctlTransact.ReadKind,
|
||||||
|
Hint = RequestHint
|
||||||
|
};
|
||||||
|
Response.IoStatus.Information = BytesTransferred;
|
||||||
|
Response.IoStatus.Status = (UInt32) Status;
|
||||||
|
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously complete a ReadDirectory operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestHint">
|
||||||
|
/// A reference to the operation to complete.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Status">
|
||||||
|
/// STATUS_SUCCESS or error code.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="BytesTransferred">
|
||||||
|
/// Number of bytes read.
|
||||||
|
/// </param>
|
||||||
|
public void SendReadDirectoryResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred)
|
||||||
|
{
|
||||||
|
var Response = new FspFsctlTransactRsp()
|
||||||
|
{
|
||||||
|
Size = 128,
|
||||||
|
Kind = (UInt32) FspFsctlTransact.QueryDirectoryKind,
|
||||||
|
Hint = RequestHint
|
||||||
|
};
|
||||||
|
Response.IoStatus.Information = BytesTransferred;
|
||||||
|
Response.IoStatus.Status = (UInt32) Status;
|
||||||
|
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
|
||||||
|
}
|
||||||
|
|
||||||
/* FSP_FILE_SYSTEM_INTERFACE */
|
/* FSP_FILE_SYSTEM_INTERFACE */
|
||||||
private static Byte[] ByteBufferNotNull = new Byte[0];
|
private static Byte[] ByteBufferNotNull = new Byte[0];
|
||||||
|
@ -355,6 +355,65 @@ namespace Fsp.Interop
|
|||||||
public IntPtr Information;
|
public IntPtr Information;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct IoStatus
|
||||||
|
{
|
||||||
|
internal UInt32 Information;
|
||||||
|
internal UInt32 Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum FspFsctlTransact
|
||||||
|
{
|
||||||
|
ReadKind = 5,
|
||||||
|
WriteKind = 6,
|
||||||
|
QueryDirectoryKind = 14
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
internal struct FspFsctlTransactReq
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal UInt16 Version;
|
||||||
|
[FieldOffset(2)]
|
||||||
|
internal UInt16 Size;
|
||||||
|
[FieldOffset(4)]
|
||||||
|
internal UInt32 Kind;
|
||||||
|
[FieldOffset(8)]
|
||||||
|
internal UInt64 Hint;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal unsafe fixed Byte Padding[88];
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
internal struct FspFsctlTransactRsp
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal UInt16 Version;
|
||||||
|
[FieldOffset(2)]
|
||||||
|
internal UInt16 Size;
|
||||||
|
[FieldOffset(4)]
|
||||||
|
internal UInt32 Kind;
|
||||||
|
[FieldOffset(8)]
|
||||||
|
internal UInt64 Hint;
|
||||||
|
|
||||||
|
[FieldOffset(16)]
|
||||||
|
internal IoStatus IoStatus;
|
||||||
|
|
||||||
|
[FieldOffset(24)]
|
||||||
|
internal FileInfo WriteFileInfo;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal unsafe fixed Byte Padding[128];
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal unsafe struct FspFileSystemOperationContext
|
||||||
|
{
|
||||||
|
internal FspFsctlTransactReq *Request;
|
||||||
|
internal FspFsctlTransactRsp *Response;
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
internal struct FileSystemInterface
|
internal struct FileSystemInterface
|
||||||
{
|
{
|
||||||
@ -664,6 +723,12 @@ namespace Fsp.Interop
|
|||||||
internal delegate Int32 FspFileSystemStopDispatcher(
|
internal delegate Int32 FspFileSystemStopDispatcher(
|
||||||
IntPtr FileSystem);
|
IntPtr FileSystem);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal delegate void FspFileSystemSendResponse(
|
||||||
|
IntPtr FileSystem,
|
||||||
|
ref FspFsctlTransactRsp Response);
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
internal unsafe delegate FspFileSystemOperationContext *FspFileSystemGetOperationContext();
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
internal delegate IntPtr FspFileSystemMountPointF(
|
internal delegate IntPtr FspFileSystemMountPointF(
|
||||||
IntPtr FileSystem);
|
IntPtr FileSystem);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
@ -848,6 +913,8 @@ namespace Fsp.Interop
|
|||||||
internal static Proto.FspFileSystemRemoveMountPoint FspFileSystemRemoveMountPoint;
|
internal static Proto.FspFileSystemRemoveMountPoint FspFileSystemRemoveMountPoint;
|
||||||
internal static Proto.FspFileSystemStartDispatcher FspFileSystemStartDispatcher;
|
internal static Proto.FspFileSystemStartDispatcher FspFileSystemStartDispatcher;
|
||||||
internal static Proto.FspFileSystemStopDispatcher FspFileSystemStopDispatcher;
|
internal static Proto.FspFileSystemStopDispatcher FspFileSystemStopDispatcher;
|
||||||
|
internal static Proto.FspFileSystemSendResponse FspFileSystemSendResponse;
|
||||||
|
internal static Proto.FspFileSystemGetOperationContext FspFileSystemGetOperationContext;
|
||||||
internal static Proto.FspFileSystemMountPointF FspFileSystemMountPoint;
|
internal static Proto.FspFileSystemMountPointF FspFileSystemMountPoint;
|
||||||
internal static Proto.FspFileSystemSetOperationGuardStrategyF FspFileSystemSetOperationGuardStrategy;
|
internal static Proto.FspFileSystemSetOperationGuardStrategyF FspFileSystemSetOperationGuardStrategy;
|
||||||
internal static Proto.FspFileSystemSetDebugLogF FspFileSystemSetDebugLog;
|
internal static Proto.FspFileSystemSetDebugLogF FspFileSystemSetDebugLog;
|
||||||
@ -894,6 +961,10 @@ namespace Fsp.Interop
|
|||||||
else
|
else
|
||||||
return _FspFileSystemSetMountPointEx(FileSystem, MountPoint, IntPtr.Zero);
|
return _FspFileSystemSetMountPointEx(FileSystem, MountPoint, IntPtr.Zero);
|
||||||
}
|
}
|
||||||
|
internal static unsafe UInt64 FspFileSystemGetOperationRequestHint()
|
||||||
|
{
|
||||||
|
return FspFileSystemGetOperationContext()->Request->Hint;
|
||||||
|
}
|
||||||
internal static unsafe Boolean FspFileSystemAddDirInfo(
|
internal static unsafe Boolean FspFileSystemAddDirInfo(
|
||||||
ref DirInfo DirInfo,
|
ref DirInfo DirInfo,
|
||||||
IntPtr Buffer,
|
IntPtr Buffer,
|
||||||
@ -1242,6 +1313,8 @@ namespace Fsp.Interop
|
|||||||
FspFileSystemRemoveMountPoint = GetEntryPoint<Proto.FspFileSystemRemoveMountPoint>(Module);
|
FspFileSystemRemoveMountPoint = GetEntryPoint<Proto.FspFileSystemRemoveMountPoint>(Module);
|
||||||
FspFileSystemStartDispatcher = GetEntryPoint<Proto.FspFileSystemStartDispatcher>(Module);
|
FspFileSystemStartDispatcher = GetEntryPoint<Proto.FspFileSystemStartDispatcher>(Module);
|
||||||
FspFileSystemStopDispatcher = GetEntryPoint<Proto.FspFileSystemStopDispatcher>(Module);
|
FspFileSystemStopDispatcher = GetEntryPoint<Proto.FspFileSystemStopDispatcher>(Module);
|
||||||
|
FspFileSystemSendResponse = GetEntryPoint<Proto.FspFileSystemSendResponse>(Module);
|
||||||
|
FspFileSystemGetOperationContext = GetEntryPoint<Proto.FspFileSystemGetOperationContext>(Module);
|
||||||
FspFileSystemMountPoint = GetEntryPoint<Proto.FspFileSystemMountPointF>(Module);
|
FspFileSystemMountPoint = GetEntryPoint<Proto.FspFileSystemMountPointF>(Module);
|
||||||
FspFileSystemSetOperationGuardStrategy = GetEntryPoint<Proto.FspFileSystemSetOperationGuardStrategyF>(Module);
|
FspFileSystemSetOperationGuardStrategy = GetEntryPoint<Proto.FspFileSystemSetOperationGuardStrategyF>(Module);
|
||||||
FspFileSystemSetDebugLog = GetEntryPoint<Proto.FspFileSystemSetDebugLogF>(Module);
|
FspFileSystemSetDebugLog = GetEntryPoint<Proto.FspFileSystemSetDebugLogF>(Module);
|
||||||
|
@ -71,6 +71,7 @@ set dfl_tests=^
|
|||||||
winfsp-tests-dotnet-external-share ^
|
winfsp-tests-dotnet-external-share ^
|
||||||
fsx-memfs-dotnet-disk ^
|
fsx-memfs-dotnet-disk ^
|
||||||
fsx-memfs-dotnet-net ^
|
fsx-memfs-dotnet-net ^
|
||||||
|
fsx-memfs-dotnet-slowio ^
|
||||||
winfstest-memfs-dotnet-disk ^
|
winfstest-memfs-dotnet-disk ^
|
||||||
winfstest-memfs-dotnet-net
|
winfstest-memfs-dotnet-net
|
||||||
set opt_tests=^
|
set opt_tests=^
|
||||||
@ -498,6 +499,11 @@ call :__run_fsx_memfs_slowio_test memfs32-slowio memfs-x86
|
|||||||
if !ERRORLEVEL! neq 0 goto fail
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:fsx-memfs-dotnet-slowio
|
||||||
|
call :__run_fsx_memfs_slowio_test memfs.net-slowio memfs-dotnet-msil
|
||||||
|
if !ERRORLEVEL! neq 0 goto fail
|
||||||
|
exit /b 0
|
||||||
|
|
||||||
:__run_fsx_memfs_slowio_test
|
:__run_fsx_memfs_slowio_test
|
||||||
set RunSampleTestExit=0
|
set RunSampleTestExit=0
|
||||||
call "%ProjRoot%\tools\fsreg" %1 "%ProjRoot%\build\VStudio\build\%Configuration%\%2.exe" "-u %%%%1 -m %%%%2 -M 50 -P 10 -R 5" "D:P(A;;RPWPLC;;;WD)"
|
call "%ProjRoot%\tools\fsreg" %1 "%ProjRoot%\build\VStudio\build\%Configuration%\%2.exe" "-u %%%%1 -m %%%%2 -M 50 -P 10 -R 5" "D:P(A;;RPWPLC;;;WD)"
|
||||||
|
@ -19,12 +19,17 @@
|
|||||||
* associated repository.
|
* associated repository.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define MEMFS_SLOWIO
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.AccessControl;
|
using System.Security.AccessControl;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
#endif
|
||||||
|
|
||||||
using Fsp;
|
using Fsp;
|
||||||
using VolumeInfo = Fsp.Interop.VolumeInfo;
|
using VolumeInfo = Fsp.Interop.VolumeInfo;
|
||||||
@ -232,15 +237,20 @@ namespace memfs
|
|||||||
|
|
||||||
class Memfs : FileSystemBase
|
class Memfs : FileSystemBase
|
||||||
{
|
{
|
||||||
|
private FileSystemHost Host;
|
||||||
public const UInt16 MEMFS_SECTOR_SIZE = 512;
|
public const UInt16 MEMFS_SECTOR_SIZE = 512;
|
||||||
public const UInt16 MEMFS_SECTORS_PER_ALLOCATION_UNIT = 1;
|
public const UInt16 MEMFS_SECTORS_PER_ALLOCATION_UNIT = 1;
|
||||||
|
|
||||||
public Memfs(
|
public Memfs(
|
||||||
Boolean CaseInsensitive, UInt32 MaxFileNodes, UInt32 MaxFileSize, String RootSddl)
|
Boolean CaseInsensitive, UInt32 MaxFileNodes, UInt32 MaxFileSize, String RootSddl,
|
||||||
|
UInt64 SlowioMaxDelay, UInt64 SlowioPercentDelay, UInt64 SlowioRarefyDelay)
|
||||||
{
|
{
|
||||||
this.FileNodeMap = new FileNodeMap(CaseInsensitive);
|
this.FileNodeMap = new FileNodeMap(CaseInsensitive);
|
||||||
this.MaxFileNodes = MaxFileNodes;
|
this.MaxFileNodes = MaxFileNodes;
|
||||||
this.MaxFileSize = MaxFileSize;
|
this.MaxFileSize = MaxFileSize;
|
||||||
|
this.SlowioMaxDelay = SlowioMaxDelay;
|
||||||
|
this.SlowioPercentDelay = SlowioPercentDelay;
|
||||||
|
this.SlowioRarefyDelay = SlowioRarefyDelay;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create root directory.
|
* Create root directory.
|
||||||
@ -259,7 +269,7 @@ namespace memfs
|
|||||||
|
|
||||||
public override Int32 Init(Object Host0)
|
public override Int32 Init(Object Host0)
|
||||||
{
|
{
|
||||||
FileSystemHost Host = (FileSystemHost)Host0;
|
Host = (FileSystemHost)Host0;
|
||||||
Host.SectorSize = Memfs.MEMFS_SECTOR_SIZE;
|
Host.SectorSize = Memfs.MEMFS_SECTOR_SIZE;
|
||||||
Host.SectorsPerAllocationUnit = Memfs.MEMFS_SECTORS_PER_ALLOCATION_UNIT;
|
Host.SectorsPerAllocationUnit = Memfs.MEMFS_SECTORS_PER_ALLOCATION_UNIT;
|
||||||
Host.VolumeCreationTime = (UInt64)DateTime.Now.ToFileTimeUtc();
|
Host.VolumeCreationTime = (UInt64)DateTime.Now.ToFileTimeUtc();
|
||||||
@ -278,6 +288,20 @@ namespace memfs
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
public override int Mounted(object Host)
|
||||||
|
{
|
||||||
|
SlowioTasksRunning = 0;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Unmounted(object Host)
|
||||||
|
{
|
||||||
|
while (SlowioTasksRunning != 0)
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public override Int32 GetVolumeInfo(
|
public override Int32 GetVolumeInfo(
|
||||||
out VolumeInfo VolumeInfo)
|
out VolumeInfo VolumeInfo)
|
||||||
{
|
{
|
||||||
@ -561,6 +585,93 @@ namespace memfs
|
|||||||
Interlocked.Decrement(ref FileNode.OpenCount);
|
Interlocked.Decrement(ref FileNode.OpenCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
private UInt64 Hash(UInt64 X)
|
||||||
|
{
|
||||||
|
X = (X ^ (X >> 30)) * 0xbf58476d1ce4e5b9ul;
|
||||||
|
X = (X ^ (X >> 27)) * 0x94d049bb133111ebul;
|
||||||
|
X = X ^ (X >> 31);
|
||||||
|
return X;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Spin = 0;
|
||||||
|
|
||||||
|
private UInt64 PseudoRandom(UInt64 To)
|
||||||
|
{
|
||||||
|
/* John Oberschelp's PRNG */
|
||||||
|
Interlocked.Increment(ref Spin);
|
||||||
|
return Hash((UInt64)Spin) % To;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SlowioReturnPending()
|
||||||
|
{
|
||||||
|
if (0 == SlowioMaxDelay)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return PseudoRandom(100) < SlowioPercentDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SlowioSnooze()
|
||||||
|
{
|
||||||
|
double Millis = PseudoRandom(SlowioMaxDelay + 1) >> (int) PseudoRandom(SlowioRarefyDelay + 1);
|
||||||
|
Thread.Sleep(TimeSpan.FromMilliseconds(Millis));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SlowioReadTask(
|
||||||
|
Object FileNode0,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt64 Offset,
|
||||||
|
UInt64 EndOffset,
|
||||||
|
UInt64 RequestHint)
|
||||||
|
{
|
||||||
|
SlowioSnooze();
|
||||||
|
|
||||||
|
UInt32 BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
|
FileNode FileNode = (FileNode)FileNode0;
|
||||||
|
Marshal.Copy(FileNode.FileData, (int)Offset, Buffer, (int)BytesTransferred);
|
||||||
|
|
||||||
|
Host.SendReadResponse(RequestHint, STATUS_SUCCESS, BytesTransferred);
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SlowioWriteTask(
|
||||||
|
Object FileNode0,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt64 Offset,
|
||||||
|
UInt64 EndOffset,
|
||||||
|
UInt64 RequestHint)
|
||||||
|
{
|
||||||
|
SlowioSnooze();
|
||||||
|
|
||||||
|
UInt32 BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
|
FileNode FileNode = (FileNode)FileNode0;
|
||||||
|
FileInfo FileInfo = FileNode.GetFileInfo();
|
||||||
|
Marshal.Copy(Buffer, FileNode.FileData, (int)Offset, (int)BytesTransferred);
|
||||||
|
|
||||||
|
Host.SendWriteResponse(RequestHint, STATUS_SUCCESS, BytesTransferred, ref FileInfo);
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SlowioReadDirectoryTask(
|
||||||
|
Object FileNode0,
|
||||||
|
Object FileDesc,
|
||||||
|
String Pattern,
|
||||||
|
String Marker,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt32 Length,
|
||||||
|
UInt64 RequestHint)
|
||||||
|
{
|
||||||
|
SlowioSnooze();
|
||||||
|
|
||||||
|
UInt32 BytesTransferred;
|
||||||
|
var Status = SeekableReadDirectory(FileNode0, FileDesc, Pattern, Marker, Buffer, Length, out BytesTransferred);
|
||||||
|
|
||||||
|
Host.SendReadDirectoryResponse(RequestHint, Status, BytesTransferred);
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public override Int32 Read(
|
public override Int32 Read(
|
||||||
Object FileNode0,
|
Object FileNode0,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
@ -582,6 +693,25 @@ namespace memfs
|
|||||||
if (EndOffset > FileNode.FileInfo.FileSize)
|
if (EndOffset > FileNode.FileInfo.FileSize)
|
||||||
EndOffset = FileNode.FileInfo.FileSize;
|
EndOffset = FileNode.FileInfo.FileSize;
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
if (SlowioReturnPending())
|
||||||
|
{
|
||||||
|
var Hint = Host.GetOperationRequestHint();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref SlowioTasksRunning);
|
||||||
|
Task.Run(() => SlowioReadTask(FileNode0, Buffer, Offset, EndOffset, Hint)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
BytesTransferred = 0;
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BytesTransferred = (UInt32)(EndOffset - Offset);
|
BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
Marshal.Copy(FileNode.FileData, (int)Offset, Buffer, (int)BytesTransferred);
|
Marshal.Copy(FileNode.FileData, (int)Offset, Buffer, (int)BytesTransferred);
|
||||||
|
|
||||||
@ -631,6 +761,26 @@ namespace memfs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
if (SlowioReturnPending())
|
||||||
|
{
|
||||||
|
var hint = Host.GetOperationRequestHint();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref SlowioTasksRunning);
|
||||||
|
Task.Run(() => SlowioWriteTask(FileNode0, Buffer, Offset, EndOffset, hint)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
BytesTransferred = 0;
|
||||||
|
FileInfo = default(FileInfo);
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BytesTransferred = (UInt32)(EndOffset - Offset);
|
BytesTransferred = (UInt32)(EndOffset - Offset);
|
||||||
Marshal.Copy(Buffer, FileNode.FileData, (int)Offset, (int)BytesTransferred);
|
Marshal.Copy(Buffer, FileNode.FileData, (int)Offset, (int)BytesTransferred);
|
||||||
|
|
||||||
@ -914,6 +1064,37 @@ namespace memfs
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MEMFS_SLOWIO
|
||||||
|
public override int ReadDirectory(
|
||||||
|
Object FileNode0,
|
||||||
|
Object FileDesc,
|
||||||
|
String Pattern,
|
||||||
|
String Marker,
|
||||||
|
IntPtr Buffer,
|
||||||
|
UInt32 Length,
|
||||||
|
out UInt32 BytesTransferred)
|
||||||
|
{
|
||||||
|
if (SlowioReturnPending())
|
||||||
|
{
|
||||||
|
var Hint = Host.GetOperationRequestHint();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref SlowioTasksRunning);
|
||||||
|
Task.Run(() => SlowioReadDirectoryTask(FileNode0, FileDesc, Pattern, Marker, Buffer, Length, Hint));
|
||||||
|
BytesTransferred = 0;
|
||||||
|
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Interlocked.Decrement(ref SlowioTasksRunning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SeekableReadDirectory(FileNode0, FileDesc, Pattern, Marker, Buffer, Length, out BytesTransferred);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public override int GetDirInfoByName(
|
public override int GetDirInfoByName(
|
||||||
Object ParentNode0,
|
Object ParentNode0,
|
||||||
Object FileDesc,
|
Object FileDesc,
|
||||||
@ -1152,6 +1333,10 @@ namespace memfs
|
|||||||
private FileNodeMap FileNodeMap;
|
private FileNodeMap FileNodeMap;
|
||||||
private UInt32 MaxFileNodes;
|
private UInt32 MaxFileNodes;
|
||||||
private UInt32 MaxFileSize;
|
private UInt32 MaxFileSize;
|
||||||
|
private UInt64 SlowioMaxDelay;
|
||||||
|
private UInt64 SlowioPercentDelay;
|
||||||
|
private UInt64 SlowioRarefyDelay;
|
||||||
|
private volatile Int32 SlowioTasksRunning;
|
||||||
private String VolumeLabel;
|
private String VolumeLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1182,6 +1367,9 @@ namespace memfs
|
|||||||
UInt32 FileInfoTimeout = unchecked((UInt32)(-1));
|
UInt32 FileInfoTimeout = unchecked((UInt32)(-1));
|
||||||
UInt32 MaxFileNodes = 1024;
|
UInt32 MaxFileNodes = 1024;
|
||||||
UInt32 MaxFileSize = 16 * 1024 * 1024;
|
UInt32 MaxFileSize = 16 * 1024 * 1024;
|
||||||
|
UInt32 SlowioMaxDelay = 0;
|
||||||
|
UInt32 SlowioPercentDelay = 0;
|
||||||
|
UInt32 SlowioRarefyDelay = 0;
|
||||||
String FileSystemName = null;
|
String FileSystemName = null;
|
||||||
String VolumePrefix = null;
|
String VolumePrefix = null;
|
||||||
String MountPoint = null;
|
String MountPoint = null;
|
||||||
@ -1214,9 +1402,18 @@ namespace memfs
|
|||||||
case 'm':
|
case 'm':
|
||||||
argtos(Args, ref I, ref MountPoint);
|
argtos(Args, ref I, ref MountPoint);
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
argtol(Args, ref I, ref SlowioMaxDelay);
|
||||||
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
argtol(Args, ref I, ref MaxFileNodes);
|
argtol(Args, ref I, ref MaxFileNodes);
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
argtol(Args, ref I, ref SlowioPercentDelay);
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
argtol(Args, ref I, ref SlowioRarefyDelay);
|
||||||
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
argtos(Args, ref I, ref RootSddl);
|
argtos(Args, ref I, ref RootSddl);
|
||||||
break;
|
break;
|
||||||
@ -1245,7 +1442,8 @@ namespace memfs
|
|||||||
throw new CommandLineUsageException("cannot open debug log file");
|
throw new CommandLineUsageException("cannot open debug log file");
|
||||||
|
|
||||||
Host = new FileSystemHost(Memfs = new Memfs(
|
Host = new FileSystemHost(Memfs = new Memfs(
|
||||||
CaseInsensitive, MaxFileNodes, MaxFileSize, RootSddl));
|
CaseInsensitive, MaxFileNodes, MaxFileSize, RootSddl,
|
||||||
|
SlowioMaxDelay, SlowioPercentDelay, SlowioRarefyDelay));
|
||||||
Host.FileInfoTimeout = FileInfoTimeout;
|
Host.FileInfoTimeout = FileInfoTimeout;
|
||||||
Host.Prefix = VolumePrefix;
|
Host.Prefix = VolumePrefix;
|
||||||
Host.FileSystemName = null != FileSystemName ? FileSystemName : "-MEMFS";
|
Host.FileSystemName = null != FileSystemName ? FileSystemName : "-MEMFS";
|
||||||
@ -1274,6 +1472,9 @@ namespace memfs
|
|||||||
" -t FileInfoTimeout [millis]\n" +
|
" -t FileInfoTimeout [millis]\n" +
|
||||||
" -n MaxFileNodes\n" +
|
" -n MaxFileNodes\n" +
|
||||||
" -s MaxFileSize [bytes]\n" +
|
" -s MaxFileSize [bytes]\n" +
|
||||||
|
" -M MaxDelay [maximum slow IO delay in millis]\n" +
|
||||||
|
" -P PercentDelay [percent of slow IO to make pending]\n" +
|
||||||
|
" -R RarefyDelay [adjust the rarity of pending slow IO]\n" +
|
||||||
" -F FileSystemName\n" +
|
" -F FileSystemName\n" +
|
||||||
" -S RootSddl [file rights: FA, etc; NO generic rights: GA, etc.]\n" +
|
" -S RootSddl [file rights: FA, etc; NO generic rights: GA, etc.]\n" +
|
||||||
" -u \\Server\\Share [UNC prefix (single backslash)]\n" +
|
" -u \\Server\\Share [UNC prefix (single backslash)]\n" +
|
||||||
|
Loading…
x
Reference in New Issue
Block a user