📄 diskperf.cpp
字号:
LONG queueLen;
UNREFERENCED_PARAMETER(Context);
// Get the per processor partition counters
// NOTE: DiskPerfReadWrite already check to see if this buffer is NON
// NULL before scheduling this completion routine, so we assume that it
// is always non-NULL when we get here
partitionCounters = (PDISK_PERFORMANCE)
((PCHAR) deviceExtension->DiskCounters
+ ((ULONG)KeGetCurrentProcessorNumber()
* PROCESSOR_COUNTERS_SIZE));
// Time stamp current request complete.
if (partitionCounters == NULL) { // just in case
return STATUS_SUCCESS;
};
difference = (PLARGE_INTEGER) &irpStack->Parameters.Read;
DiskPerfGetClock(timeStampComplete, NULL);
difference->QuadPart = timeStampComplete.QuadPart - difference->QuadPart;
DBGOUT((10, "DiskPerfIoCompletion: TS=%I64u diff %I64u\n",
timeStampComplete, difference->QuadPart));
// Decrement the queue depth counters for the volume. This is
// done without the spinlock using the Interlocked functions.
// This is the only
// legal way to do this.
queueLen = InterlockedDecrement(&deviceExtension->QueueDepth);
if (queueLen < 0) { // do not over-decrement. Only happens at start
queueLen = InterlockedIncrement(&deviceExtension->QueueDepth);
}
if (queueLen == 0) {
deviceExtension->LastIdleClock = timeStampComplete;
}
// Update counters
if (irpStack->MajorFunction == IRP_MJ_READ) {
// Add bytes in this request to bytes read counters.
partitionCounters->BytesRead.QuadPart += Irp->IoStatus.Information;
// Increment read requests processed counters.
partitionCounters->ReadCount++;
// Calculate request processing time.
partitionCounters->ReadTime.QuadPart += difference->QuadPart;
DBGOUT((11, "Added RT delta %I64u total %I64u qlen=%d\n",
difference->QuadPart, partitionCounters->ReadTime.QuadPart,
queueLen));
DbgPrint(("读操作 diskperf.c\n"));
}
else {
// 写操作
// Add bytes in this request to bytes write counters.
partitionCounters->BytesWritten.QuadPart += Irp->IoStatus.Information;
// Increment write requests processed counters.
// partitionCounters->WriteCount++;
// Calculate request processing time.
partitionCounters->WriteTime.QuadPart += difference->QuadPart;
DBGOUT((11, "Added WT delta %I64u total %I64u qlen=%d\n",
difference->QuadPart, partitionCounters->WriteTime.QuadPart,
queueLen));
DbgPrint(("写操作 diskperf.c\n"));
}
if (Irp->Flags & IRP_ASSOCIATED_IRP) {
partitionCounters->SplitCount++;
}
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
return STATUS_SUCCESS;
} // DiskPerfIoCompletion
NTSTATUS
DiskPerfDeviceControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
Routine Description:
This device control dispatcher handles only the disk performance
device control. All others are passed down to the disk drivers.
The disk performane device control returns a current snapshot of
the performance data.
Arguments:
DeviceObject - Context for the activity.
Irp - The device control argument block.
Return Value:
Status is returned.
--*/
{
PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
DBGOUT((2, "DiskPerfDeviceControl: DeviceObject %X Irp %X\n",
DeviceObject, Irp));
//////////////////////////////////////////////////////////////////////////
if( currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
DISK_READONLY )
{
//
IsReadOnly = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint(("My Ioctrl DISK_READONLY \n"));
return STATUS_SUCCESS;
}
if( currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
DISK_NONREADONLY )
{
//
IsReadOnly = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint(("My Ioctrl DISK_NONREADONLY \n"));
return STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////////
if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_DISK_PERFORMANCE) {
NTSTATUS status;
KIRQL currentIrql;
// Verify user buffer is large enough for the performance data.
if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DISK_PERFORMANCE)) {
// Indicate unsuccessful status and no data transferred.
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
}
else {
ULONG i;
PDISK_PERFORMANCE totalCounters;
PDISK_PERFORMANCE diskCounters = deviceExtension->DiskCounters;
LARGE_INTEGER frequency, perfctr;
if (diskCounters == NULL) {
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
if (InterlockedCompareExchange(&deviceExtension->EnabledAlways, 1, 0) == 0)
{
InterlockedIncrement(&deviceExtension->CountersEnabled);
// reset per processor counters only
if (deviceExtension->DiskCounters != NULL)
{
RtlZeroMemory(deviceExtension->DiskCounters, PROCESSOR_COUNTERS_SIZE * deviceExtension->Processors);
}
DiskPerfGetClock(deviceExtension->LastIdleClock, NULL);
deviceExtension->QueueDepth = 0;
DBGOUT((10, "DiskPerfDeviceControl: LIC=%I64u\n", deviceExtension->LastIdleClock));
DBGOUT((3, "DiskPerfDeviceControl: Counters enabled %d\n", deviceExtension->CountersEnabled));
}
totalCounters = (PDISK_PERFORMANCE) Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(totalCounters, sizeof(DISK_PERFORMANCE));
#ifdef USE_PERF_CTR
perfctr = KeQueryPerformanceCounter(&frequency);
#endif
KeQuerySystemTime(&totalCounters->QueryTime);
for (i=0; i<deviceExtension->Processors; i++) {
DiskPerfAddCounters(totalCounters, diskCounters, frequency);
diskCounters = (PDISK_PERFORMANCE)
((PCHAR) diskCounters + PROCESSOR_COUNTERS_SIZE);
}
totalCounters->QueueDepth = deviceExtension->QueueDepth;
if (totalCounters->QueueDepth == 0) {
LARGE_INTEGER difference;
difference.QuadPart =
#ifdef USE_PERF_CTR
perfctr.QuadPart
#else
totalCounters->QueryTime.QuadPart
#endif
- deviceExtension->LastIdleClock.QuadPart;
if (difference.QuadPart > 0) {
totalCounters->IdleTime.QuadPart +=
#ifdef USE_PERF_CTR
10000000 * difference.QuadPart / frequency.QuadPart;
#else
difference.QuadPart;
#endif
}
}
totalCounters->StorageDeviceNumber
= deviceExtension->DiskNumber;
RtlCopyMemory(
&totalCounters->StorageManagerName[0],
&deviceExtension->StorageManagerName[0],
8 * sizeof(WCHAR));
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(DISK_PERFORMANCE);
}
// Complete request.
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
else {
// Set current stack back one.
Irp->CurrentLocation++,
Irp->Tail.Overlay.CurrentStackLocation++;
// Pass unrecognized device control requests
// down to next driver layer.
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
}
} // end DiskPerfDeviceControl()
NTSTATUS DiskPerfWmi(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine handles any WMI requests for information. Since the disk
information is read-only, is always collected and does not have any
events only QueryAllData, QuerySingleInstance and GetRegInfo requests
are supported.
Arguments:
DeviceObject - Context for the activity.
Irp - The device control argument block.
Return Value:
Status is returned.
--*/
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
PWMILIB_CONTEXT wmilibContext;
SYSCTL_IRP_DISPOSITION disposition;
PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
PAGED_CODE();
DBGOUT((2, "DiskPerfWmi: DeviceObject %X Irp %X\n",
DeviceObject, Irp));
wmilibContext = &deviceExtension->WmilibContext;
if (wmilibContext->GuidCount == 0) // wmilibContext is not valid
{
DBGOUT((3, "DiskPerfWmi: WmilibContext invalid"));
return DiskPerfSendToNextDriver(DeviceObject, Irp);
}
irpSp = IoGetCurrentIrpStackLocation(Irp);
DBGOUT((3, "DiskPerfWmi: Calling WmiSystemControl\n"));
status = WmiSystemControl(wmilibContext,
DeviceObject,
Irp,
&disposition);
switch (disposition)
{
case IrpProcessed:
{
break;
}
case IrpNotCompleted:
{
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
}
// case IrpForward:
// case IrpNotWmi:
default:
{
status = DiskPerfSendToNextDriver(DeviceObject, Irp);
break;
}
}
return(status);
}
NTSTATUS
DiskPerfShutdownFlush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called for a shutdown and flush IRPs. These are sent by the
system before it actually shuts down or when the file system does a flush.
Arguments:
DriverObject - Pointer to device object to being shutdown by system.
Irp - IRP involved.
Return Value:
NT Status
--*/
{
PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
// Set current stack back one.
DBGOUT((2, "DiskPerfShutdownFlush: DeviceObject %X Irp %X\n",
DeviceObject, Irp));
Irp->CurrentLocation++,
Irp->Tail.Overlay.CurrentStackLocation++;
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
} // end DiskPerfShutdownFlush()
VOID
DiskPerfUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object.
Return Value:
VOID.
--*/
{
PAGED_CODE();
return;
}
NTSTATUS
DiskPerfRegisterDevice(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Routine to initialize a proper name for the device object, and
register it with WMI
Arguments:
DeviceObject - pointer to a device object to be initialized.
Return Value:
Status of the initialization. NOTE: If the registration fails,
the device name in the DeviceExtension will be left as empty.
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
PDEVICE_EXTENSION deviceExtension;
PIRP irp;
STORAGE_DEVICE_NUMBER number;
ULONG registrationFlag = 0;
PAGED_CODE();
DBGOUT((2, "DiskPerfRegisterDevice: DeviceObject %X\n",
DeviceObject));
deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
KeInitializeEvent(&event, NotificationEvent, FALSE);
// Request for the device number
irp = IoBuildDeviceIoControlRequest(
IOCTL_STORAGE_GET_DEVICE_NUMBER,
deviceExtension->TargetDeviceObject,
NULL,
0,
&number,
sizeof(number),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -