dotnet: add MountEx and fine-grained timeouts

This commit is contained in:
Bill Zissimopoulos 2019-07-07 12:12:04 -07:00
parent 3a12d928e5
commit c97f2cb660
2 changed files with 163 additions and 40 deletions

View File

@ -40,6 +40,7 @@ namespace Fsp
/// <param name="FileSystem">The file system to host.</param> /// <param name="FileSystem">The file system to host.</param>
public FileSystemHost(FileSystemBase FileSystem) public FileSystemHost(FileSystemBase FileSystem)
{ {
_VolumeParams.Version = (UInt16)Marshal.SizeOf(_VolumeParams);
_VolumeParams.Flags = VolumeParams.UmFileContextIsFullContext; _VolumeParams.Flags = VolumeParams.UmFileContextIsFullContext;
_FileSystem = FileSystem; _FileSystem = FileSystem;
} }
@ -126,6 +127,86 @@ namespace Fsp
set { _VolumeParams.FileInfoTimeout = value; } set { _VolumeParams.FileInfoTimeout = value; }
} }
/// <summary> /// <summary>
/// Gets or sets the volume information timeout.
/// </summary>
public UInt32 VolumeInfoTimeout
{
get
{
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.VolumeInfoTimeoutValid) ?
_VolumeParams.VolumeInfoTimeout : _VolumeParams.FileInfoTimeout;
}
set
{
_VolumeParams.AdditionalFlags |= VolumeParams.VolumeInfoTimeoutValid;
_VolumeParams.VolumeInfoTimeout = value;
}
}
/// <summary>
/// Gets or sets the directory information timeout.
/// </summary>
public UInt32 DirInfoTimeout
{
get
{
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.DirInfoTimeoutValid) ?
_VolumeParams.DirInfoTimeout : _VolumeParams.FileInfoTimeout;
}
set
{
_VolumeParams.AdditionalFlags |= VolumeParams.DirInfoTimeoutValid;
_VolumeParams.DirInfoTimeout = value;
}
}
/// <summary>
/// Gets or sets the security information timeout.
/// </summary>
public UInt32 SecurityTimeout
{
get
{
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.SecurityTimeoutValid) ?
_VolumeParams.SecurityTimeout : _VolumeParams.FileInfoTimeout;
}
set
{
_VolumeParams.AdditionalFlags |= VolumeParams.SecurityTimeoutValid;
_VolumeParams.SecurityTimeout = value;
}
}
/// <summary>
/// Gets or sets the stream information timeout.
/// </summary>
public UInt32 StreamInfoTimeout
{
get
{
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.StreamInfoTimeoutValid) ?
_VolumeParams.StreamInfoTimeout : _VolumeParams.FileInfoTimeout;
}
set
{
_VolumeParams.AdditionalFlags |= VolumeParams.StreamInfoTimeoutValid;
_VolumeParams.StreamInfoTimeout = value;
}
}
/// <summary>
/// Gets or sets the EA information timeout.
/// </summary>
public UInt32 EaTimeout
{
get
{
return 0 != (_VolumeParams.AdditionalFlags & VolumeParams.EaTimeoutValid) ?
_VolumeParams.EaTimeout : _VolumeParams.FileInfoTimeout;
}
set
{
_VolumeParams.AdditionalFlags |= VolumeParams.EaTimeoutValid;
_VolumeParams.EaTimeout = value;
}
}
/// <summary>
/// Gets or sets a value that determines whether the file system is case sensitive. /// Gets or sets a value that determines whether the file system is case sensitive.
/// </summary> /// </summary>
public Boolean CaseSensitiveSearch public Boolean CaseSensitiveSearch
@ -279,11 +360,44 @@ namespace Fsp
/// A value of 0 disables all debug logging. /// A value of 0 disables all debug logging.
/// A value of -1 enables all debug logging. /// A value of -1 enables all debug logging.
/// </param> /// </param>
/// <returns></returns> /// <returns>STATUS_SUCCESS or error code.</returns>
public Int32 Mount(String MountPoint, public Int32 Mount(String MountPoint,
Byte[] SecurityDescriptor = null, Byte[] SecurityDescriptor = null,
Boolean Synchronized = false, Boolean Synchronized = false,
UInt32 DebugLog = 0) UInt32 DebugLog = 0)
{
return MountEx(MountPoint, 0, SecurityDescriptor, Synchronized, DebugLog);
}
/// <summary>
/// Mounts a file system.
/// </summary>
/// <param name="MountPoint">
/// The mount point for the new file system. A value of null means that
/// the file system should use the next available drive letter counting
/// downwards from Z: as its mount point.
/// </param>
/// <param name="ThreadCount">
/// Number of threads to use to service file system requests. A value
/// of 0 means that the default number of threads should be used.
/// </param>
/// <param name="SecurityDescriptor">
/// Security descriptor to use if mounting on (newly created) directory.
/// A value of null means the directory should be created with default
/// security.
/// </param>
/// <param name="Synchronized">
/// If true file system operations are synchronized using an exclusive lock.
/// </param>
/// <param name="DebugLog">
/// A value of 0 disables all debug logging.
/// A value of -1 enables all debug logging.
/// </param>
/// <returns>STATUS_SUCCESS or error code.</returns>
public Int32 MountEx(String MountPoint,
UInt32 ThreadCount,
Byte[] SecurityDescriptor = null,
Boolean Synchronized = false,
UInt32 DebugLog = 0)
{ {
Int32 Result; Int32 Result;
try try
@ -320,7 +434,7 @@ namespace Fsp
} }
if (0 <= Result) if (0 <= Result)
{ {
Result = Api.FspFileSystemStartDispatcher(_FileSystemPtr, 0); Result = Api.FspFileSystemStartDispatcher(_FileSystemPtr, ThreadCount);
if (0 > Result) if (0 > Result)
try try
{ {
@ -394,6 +508,28 @@ namespace Fsp
return Api.FspFileSystemGetOperationRequestHint(); return Api.FspFileSystemGetOperationRequestHint();
} }
/// <summary> /// <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)
{
FspFsctlTransactRsp Response = default(FspFsctlTransactRsp);
Response.Size = 128;
Response.Kind = (UInt32)FspFsctlTransact.ReadKind;
Response.Hint = RequestHint;
Response.IoStatus.Information = BytesTransferred;
Response.IoStatus.Status = (UInt32)Status;
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
}
/// <summary>
/// Asynchronously complete a Write operation. /// Asynchronously complete a Write operation.
/// </summary> /// </summary>
/// <param name="RequestHint"> /// <param name="RequestHint">
@ -410,42 +546,16 @@ namespace Fsp
/// </param> /// </param>
public void SendWriteResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred, ref FileInfo FileInfo) public void SendWriteResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred, ref FileInfo FileInfo)
{ {
var Response = new FspFsctlTransactRsp() FspFsctlTransactRsp Response = default(FspFsctlTransactRsp);
{ Response.Size = 128;
Size = 128, Response.Kind = (UInt32)FspFsctlTransact.WriteKind;
Kind = (UInt32) FspFsctlTransact.WriteKind, Response.Hint = RequestHint;
Hint = RequestHint
};
Response.IoStatus.Information = BytesTransferred; Response.IoStatus.Information = BytesTransferred;
Response.IoStatus.Status = (UInt32) Status; Response.IoStatus.Status = (UInt32)Status;
Response.WriteFileInfo = FileInfo; Response.WriteFileInfo = FileInfo;
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response); Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
} }
/// <summary> /// <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. /// Asynchronously complete a ReadDirectory operation.
/// </summary> /// </summary>
/// <param name="RequestHint"> /// <param name="RequestHint">
@ -459,14 +569,12 @@ namespace Fsp
/// </param> /// </param>
public void SendReadDirectoryResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred) public void SendReadDirectoryResponse(UInt64 RequestHint, Int32 Status, UInt32 BytesTransferred)
{ {
var Response = new FspFsctlTransactRsp() FspFsctlTransactRsp Response = default(FspFsctlTransactRsp);
{ Response.Size = 128;
Size = 128, Response.Kind = (UInt32)FspFsctlTransact.QueryDirectoryKind;
Kind = (UInt32) FspFsctlTransact.QueryDirectoryKind, Response.Hint = RequestHint;
Hint = RequestHint
};
Response.IoStatus.Information = BytesTransferred; Response.IoStatus.Information = BytesTransferred;
Response.IoStatus.Status = (UInt32) Status; Response.IoStatus.Status = (UInt32)Status;
Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response); Api.FspFileSystemSendResponse(_FileSystemPtr, ref Response);
} }

View File

@ -57,6 +57,12 @@ namespace Fsp.Interop
internal const int PrefixSize = 192; internal const int PrefixSize = 192;
internal const int FileSystemNameSize = 16; internal const int FileSystemNameSize = 16;
internal const UInt32 VolumeInfoTimeoutValid = 0x00000001;
internal const UInt32 DirInfoTimeoutValid = 0x00000002;
internal const UInt32 SecurityTimeoutValid = 0x00000004;
internal const UInt32 StreamInfoTimeoutValid = 0x00000008;
internal const UInt32 EaTimeoutValid = 0x00000010;
internal UInt16 Version; internal UInt16 Version;
internal UInt16 SectorSize; internal UInt16 SectorSize;
internal UInt16 SectorsPerAllocationUnit; internal UInt16 SectorsPerAllocationUnit;
@ -70,6 +76,15 @@ namespace Fsp.Interop
internal UInt32 Flags; internal UInt32 Flags;
internal unsafe fixed UInt16 Prefix[PrefixSize]; internal unsafe fixed UInt16 Prefix[PrefixSize];
internal unsafe fixed UInt16 FileSystemName[FileSystemNameSize]; internal unsafe fixed UInt16 FileSystemName[FileSystemNameSize];
internal UInt32 AdditionalFlags;
internal UInt32 VolumeInfoTimeout;
internal UInt32 DirInfoTimeout;
internal UInt32 SecurityTimeout;
internal UInt32 StreamInfoTimeout;
internal UInt32 EaTimeout;
internal UInt32 FsextControlCode;
internal unsafe fixed UInt32 Reserved32[1];
internal unsafe fixed UInt64 Reserved64[2];
internal unsafe String GetPrefix() internal unsafe String GetPrefix()
{ {