📄 diskperf.c
字号:
NTSTATUS
DiskPerfSendToNextDriver(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine sends the Irp to the next driver in line
when the Irp is not processed by this driver.
Arguments:
DeviceObject
Irp
Return Value:
NTSTATUS
--*/
{
PDEVICE_EXTENSION deviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
} // end DiskPerfSendToNextDriver()
NTSTATUS
DiskPerfDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
return PoCallDriver(deviceExtension->TargetDeviceObject, Irp);
} // end DiskPerfDispatchPower
NTSTATUS
DiskPerfForwardIrpSynchronous(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine sends the Irp to the next driver in line
when the Irp needs to be processed by the lower drivers
prior to being processed by this one.
Arguments:
DeviceObject
Irp
Return Value:
NTSTATUS
--*/
{
PDEVICE_EXTENSION deviceExtension;
KEVENT event;
NTSTATUS status;
KeInitializeEvent(&event, NotificationEvent, FALSE);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// copy the irpstack for the next device
//
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// set a completion routine
//
IoSetCompletionRoutine(Irp, DiskPerfIrpCompletion,
&event, TRUE, TRUE, TRUE);
//
// call the next lower device
//
status = IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
//
// wait for the actual completion
//
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = Irp->IoStatus.Status;
}
return status;
} // end DiskPerfForwardIrpSynchronous()
NTSTATUS
DiskPerfCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine services open commands. It establishes
the driver's existance by returning status success.
Arguments:
DeviceObject - Context for the activity.
Irp - The device control argument block.
Return Value:
NT Status
--*/
{
UNREFERENCED_PARAMETER(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
} // end DiskPerfCreate()
NTSTATUS
DiskPerfReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the driver entry point for read and write requests
to disks to which the diskperf driver has attached.
This driver collects statistics and then sets a completion
routine so that it can collect additional information when
the request completes. Then it calls the next driver below
it.
Arguments:
DeviceObject
Irp
Return Value:
NTSTATUS
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
ULONG processor = (ULONG) KeGetCurrentProcessorNumber();
PDISK_PERFORMANCE partitionCounters = NULL;
LONG queueLen;
PLARGE_INTEGER timeStamp;
if (deviceExtension->DiskCounters != NULL) {
partitionCounters = (PDISK_PERFORMANCE)
((PCHAR) deviceExtension->DiskCounters
+ (processor*PROCESSOR_COUNTERS_SIZE));
}
//
// Device is not initialized properly. Blindly pass the irp along
//
if (deviceExtension->CountersEnabled <= 0 ||
deviceExtension->PhysicalDeviceNameBuffer[0] == 0 ||
partitionCounters == NULL) {
return DiskPerfSendToNextDriver(DeviceObject, Irp);
}
//
// Increment queue depth counter.
//
queueLen = InterlockedIncrement(&deviceExtension->QueueDepth);
//
// Copy current stack to next stack.
//
*nextIrpStack = *currentIrpStack;
//
// Time stamp current request start.
//
timeStamp = (PLARGE_INTEGER) ¤tIrpStack->Parameters.Read;
DiskPerfGetClock(*timeStamp, NULL);
DebugPrint((10, "DiskPerfReadWrite: TS=%I64u\n", *timeStamp));
if (queueLen == 1) {
partitionCounters->IdleTime.QuadPart
+= timeStamp->QuadPart -
deviceExtension->LastIdleClock.QuadPart;
deviceExtension->LastIdleClock.QuadPart = timeStamp->QuadPart;
}
//
// Set completion routine callback.
//
IoSetCompletionRoutine(Irp,
DiskPerfIoCompletion,
DeviceObject,
TRUE,
TRUE,
TRUE);
//
// Return the results of the call to the disk driver.
//
return IoCallDriver(deviceExtension->TargetDeviceObject,
Irp);
} // end DiskPerfReadWrite()
NTSTATUS
DiskPerfIoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine will get control from the system at the completion of an IRP.
It will calculate the difference between the time the IRP was started
and the current time, and decrement the queue depth.
Arguments:
DeviceObject - for the IRP.
Irp - The I/O request that just completed.
Context - Not used.
Return Value:
The IRP status.
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PDISK_PERFORMANCE partitionCounters;
LARGE_INTEGER timeStampComplete;
PLARGE_INTEGER difference;
KIRQL currentIrql;
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;
DebugPrint((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;
DebugPrint((11, "Added RT delta %I64u total %I64u qlen=%d\n",
difference->QuadPart, partitionCounters->ReadTime.QuadPart,
queueLen));
}
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;
DebugPrint((11, "Added WT delta %I64u total %I64u qlen=%d\n",
difference->QuadPart, partitionCounters->WriteTime.QuadPart,
queueLen));
}
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 = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
DebugPrint((2, "DiskPerfDeviceControl: DeviceObject %X Irp %X\n",
DeviceObject, Irp));
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;
}
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -