sys: statistics: implement FSCTL_FILESYSTEM_GET_STATISTICS

This commit is contained in:
Bill Zissimopoulos 2016-12-26 22:45:48 -08:00
parent c8206751d2
commit 168acb1a1f
11 changed files with 196 additions and 3 deletions

View File

@ -177,6 +177,7 @@
<ClCompile Include="..\..\src\sys\read.c" />
<ClCompile Include="..\..\src\sys\security.c" />
<ClCompile Include="..\..\src\sys\shutdown.c" />
<ClCompile Include="..\..\src\sys\statistics.c" />
<ClCompile Include="..\..\src\sys\util.c" />
<ClCompile Include="..\..\src\sys\volinfo.c" />
<ClCompile Include="..\..\src\sys\volume.c" />

View File

@ -95,6 +95,9 @@
<ClCompile Include="..\..\src\sys\name.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="..\..\src\sys\statistics.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\sys\driver.h">

View File

@ -364,6 +364,12 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
InitializeListHead(&FsvolDeviceExtension->NotifyList);
FsvolDeviceExtension->InitDoneNotify = 1;
/* create file system statistics */
Result = FspStatisticsCreate(&FsvolDeviceExtension->Statistics);
if (!NT_SUCCESS(Result))
return Result;
FsvolDeviceExtension->InitDoneStat = 1;
/* initialize our context table */
ExInitializeResourceLite(&FsvolDeviceExtension->FileRenameResource);
ExInitializeResourceLite(&FsvolDeviceExtension->ContextTableResource);
@ -408,6 +414,10 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
if (FsvolDeviceExtension->InitDoneTimer)
IoStopTimer(DeviceObject);
/* delete the file system statistics */
if (FsvolDeviceExtension->InitDoneStat)
FspStatisticsDelete(FsvolDeviceExtension->Statistics);
/* uninitialize the FSRTL Notify mechanism */
if (FsvolDeviceExtension->InitDoneNotify)
{

View File

@ -176,6 +176,8 @@ NTSTATUS DriverEntry(
static VOID FspDriverMultiVersionInitialize(VOID)
{
FspProcessorCount = KeQueryActiveProcessorCount(0);
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
if (RtlIsNtDdiVersionAvailable(NTDDI_WIN7))
@ -216,5 +218,6 @@ PDEVICE_OBJECT FspFsctlNetDeviceObject;
FAST_IO_DISPATCH FspFastIoDispatch;
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
ULONG FspProcessorCount;
FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
ULONG FspMvMdlMappingNoWrite = 0;

View File

@ -949,6 +949,21 @@ VOID FspWqPostIrpWorkItem(PIRP Irp);
#define FspWqRepostIrpWorkItem(I, RW, RF)\
FspWqCreateAndPostIrpWorkItem(I, RW, RF, TRUE)
/* file system statistics */
typedef struct
{
FILESYSTEM_STATISTICS Base;
FAT_STATISTICS Specific; /* pretend that we are FAT when it comes to stats */
/* align to 64 bytes */
__declspec(align(64)) UINT8 EndOfStruct[];
} FSP_STATISTICS;
NTSTATUS FspStatisticsCreate(FSP_STATISTICS **PStatistics);
VOID FspStatisticsDelete(FSP_STATISTICS *Statistics);
NTSTATUS FspStatisticsCopy(FSP_STATISTICS *Statistics, PVOID Buffer, PULONG PLength);
#define FspStatistics(S) (&(S)[KeGetCurrentProcessorNumber() % FspProcessorCount])
#define FspStatisticsInc(S,F) ((S)->F++)
#define FspStatisticsAdd(S,F,V) ((S)->F += (V))
/* device management */
enum
{
@ -990,7 +1005,7 @@ typedef struct
{
FSP_DEVICE_EXTENSION Base;
UINT32 InitDoneFsvrt:1, InitDoneIoq:1, InitDoneSec:1, InitDoneDir:1, InitDoneStrm:1,
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1;
InitDoneCtxTab:1, InitDoneTimer:1, InitDoneInfo:1, InitDoneNotify:1, InitDoneStat:1;
PDEVICE_OBJECT FsctlDeviceObject;
PDEVICE_OBJECT FsvrtDeviceObject;
HANDLE MupHandle;
@ -1016,6 +1031,7 @@ typedef struct
FSP_FSCTL_VOLUME_INFO VolumeInfo;
PNOTIFY_SYNC NotifySync;
LIST_ENTRY NotifyList;
FSP_STATISTICS *Statistics;
} FSP_FSVOL_DEVICE_EXTENSION;
static inline
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
@ -1083,6 +1099,8 @@ VOID FspDeviceGlobalUnlock(VOID)
extern ERESOURCE FspDeviceGlobalResource;
ExReleaseResourceLite(&FspDeviceGlobalResource);
}
#define FspFsvolDeviceStatistics(DeviceObject)\
FspStatistics(FspFsvolDeviceExtension(DeviceObject)->Statistics)
#define FspFsvolDeviceStoppedStatus(DeviceObject)\
STATUS_VOLUME_DISMOUNTED
//(FILE_DEVICE_DISK_FILE_SYSTEM == (DeviceObject)->DeviceType ?\
@ -1486,6 +1504,7 @@ extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
extern ERESOURCE FspDeviceGlobalResource;
extern WCHAR FspFileDescDirectoryPatternMatchAll[];
extern const GUID FspMainFileOpenEcpGuid;
extern ULONG FspProcessorCount;
extern FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
extern ULONG FspMvMdlMappingNoWrite;

View File

@ -31,6 +31,8 @@ static IO_COMPLETION_ROUTINE FspFsvolFileSystemControlOplockCompletion;
static WORKER_THREAD_ROUTINE FspFsvolFileSystemControlOplockCompletionWork;
static NTSTATUS FspFsvolFileSystemControlQueryPersistentVolumeState(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolFileSystemControlGetStatistics(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspFsvolFileSystemControl(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolFileSystemControlComplete;
@ -45,6 +47,7 @@ FSP_DRIVER_DISPATCH FspFileSystemControl;
// !#pragma alloc_text(PAGE, FspFsvolFileSystemControlOplockCompletion)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlOplockCompletionWork)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlQueryPersistentVolumeState)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlGetStatistics)
#pragma alloc_text(PAGE, FspFsvolFileSystemControl)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlComplete)
#pragma alloc_text(PAGE, FspFsvolFileSystemControlRequestFini)
@ -513,6 +516,23 @@ static NTSTATUS FspFsvolFileSystemControlQueryPersistentVolumeState(
return STATUS_SUCCESS;
}
static NTSTATUS FspFsvolFileSystemControlGetStatistics(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
NTSTATUS Result;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
ULONG Length = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
Result = FspStatisticsCopy(FsvolDeviceExtension->Statistics, Buffer, &Length);
Irp->IoStatus.Information = Length;
return Result;
}
static NTSTATUS FspFsvolFileSystemControl(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
@ -549,6 +569,9 @@ static NTSTATUS FspFsvolFileSystemControl(
case FSCTL_QUERY_PERSISTENT_VOLUME_STATE:
Result = FspFsvolFileSystemControlQueryPersistentVolumeState(FsvolDeviceObject, Irp, IrpSp);
break;
case FSCTL_FILESYSTEM_GET_STATISTICS:
Result = FspFsvolFileSystemControlGetStatistics(FsvolDeviceObject, Irp, IrpSp);
break;
}
break;
}

View File

@ -281,6 +281,28 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference)
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject;
/*
* HACK:
*
* We update the Create statistics here to avoid doing it in multiple places.
*/
if (IRP_MJ_CREATE == IrpSp->MajorFunction)
{
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
if (FspFsvolDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)
{
FSP_STATISTICS *Statistics = FspStatistics(
((FSP_FSVOL_DEVICE_EXTENSION *)DeviceExtension)->Statistics);
FspStatisticsInc(Statistics, Specific.CreateHits);
if (STATUS_SUCCESS == Result)
FspStatisticsInc(Statistics, Specific.SuccessfulCreates);
else
FspStatisticsInc(Statistics, Specific.FailedCreates);
}
}
else
/*
* HACK:
*

View File

@ -324,6 +324,20 @@ static NTSTATUS FspFsvolReadNonCached(
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
FSP_STATISTICS *Statistics = FspFsvolDeviceStatistics(FsvolDeviceObject);
if (PagingIo)
{
FspStatisticsInc(Statistics, Base.UserFileReads);
FspStatisticsAdd(Statistics, Base.UserFileReadBytes, ReadLength);
FspStatisticsInc(Statistics, Base.UserDiskReads);
}
else
{
FspStatisticsInc(Statistics, Specific.NonCachedReads);
FspStatisticsAdd(Statistics, Specific.NonCachedReadBytes, ReadLength);
FspStatisticsInc(Statistics, Specific.NonCachedDiskReads);
}
return FSP_STATUS_IOQ_POST;
}

84
src/sys/statistics.c Normal file
View File

@ -0,0 +1,84 @@
/**
* @file sys/statistics.c
*
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this file in
* accordance with the commercial license agreement provided with the
* software.
*/
#include <sys/driver.h>
NTSTATUS FspStatisticsCreate(FSP_STATISTICS **PStatistics);
VOID FspStatisticsDelete(FSP_STATISTICS *Statistics);
NTSTATUS FspStatisticsCopy(FSP_STATISTICS *Statistics, PVOID Buffer, PULONG PLength);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspStatisticsCreate)
#pragma alloc_text(PAGE, FspStatisticsDelete)
#pragma alloc_text(PAGE, FspStatisticsCopy)
#endif
NTSTATUS FspStatisticsCreate(FSP_STATISTICS **PStatistics)
{
*PStatistics = FspAllocNonPaged(sizeof(FSP_STATISTICS) * FspProcessorCount);
if (0 == *PStatistics)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(*PStatistics, sizeof(FSP_STATISTICS) * FspProcessorCount);
for (ULONG Index = 0; FspProcessorCount > Index; Index++)
{
FSP_STATISTICS *Statistics = PStatistics[Index];
/* pretend that we are FAT when it comes to stats */
Statistics->Base.FileSystemType = FILESYSTEM_STATISTICS_TYPE_FAT;
Statistics->Base.Version = 1;
Statistics->Base.SizeOfCompleteStructure = sizeof(FSP_STATISTICS);
}
return STATUS_SUCCESS;
}
VOID FspStatisticsDelete(FSP_STATISTICS *Statistics)
{
FspFree(Statistics);
}
NTSTATUS FspStatisticsCopy(FSP_STATISTICS *Statistics, PVOID Buffer, PULONG PLength)
{
NTSTATUS Result;
ULONG StatLength;
if (0 == Buffer)
{
*PLength = 0;
return STATUS_INVALID_PARAMETER;
}
if (sizeof(FILESYSTEM_STATISTICS) > *PLength)
{
*PLength = 0;
return STATUS_BUFFER_TOO_SMALL;
}
StatLength = sizeof(FSP_STATISTICS) * FspProcessorCount;
if (*PLength >= StatLength)
{
*PLength = StatLength;
Result = STATUS_SUCCESS;
}
else
Result = STATUS_BUFFER_OVERFLOW;
RtlCopyMemory(Buffer, Statistics, *PLength);
return Result;
}

View File

@ -394,6 +394,20 @@ static NTSTATUS FspFsvolWriteNonCached(
FspFileNodeSetOwner(FileNode, Full, Request);
FspIopRequestContext(Request, RequestIrp) = Irp;
FSP_STATISTICS *Statistics = FspFsvolDeviceStatistics(FsvolDeviceObject);
if (PagingIo)
{
FspStatisticsInc(Statistics, Base.UserFileWrites);
FspStatisticsAdd(Statistics, Base.UserFileWriteBytes, WriteLength);
FspStatisticsInc(Statistics, Base.UserDiskWrites);
}
else
{
FspStatisticsInc(Statistics, Specific.NonCachedWrites);
FspStatisticsAdd(Statistics, Specific.NonCachedWriteBytes, WriteLength);
FspStatisticsInc(Statistics, Specific.NonCachedDiskWrites);
}
return FSP_STATUS_IOQ_POST;
}

View File

@ -379,8 +379,8 @@ rem call :__ifstest %1 /d %2 /g ChangeNotification /z /v
rem if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
call :__ifstest %1 /d %2 /g ReadWrite /z /v
if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
rem call :__ifstest %1 /d %2 /g SectionsCaching /z /v
rem if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
call :__ifstest %1 /d %2 /g SectionsCaching /z /v
if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
rem call :__ifstest %1 /d %2 /g ReparsePoints /z /v
rem if !ERRORLEVEL! neq 0 set IfsTestMemfsExit=1
rem call :__ifstest %1 /d %2 /g StreamEnhancements /z /v