|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: diskperf.c ! 8: ! 9: Abstract: ! 10: ! 11: This driver monitors disk accesses capturing performance data. ! 12: ! 13: Authors: ! 14: ! 15: Mike Glass ! 16: Bob Rinne ! 17: ! 18: Environment: ! 19: ! 20: kernel mode only ! 21: ! 22: Notes: ! 23: ! 24: Revision History: ! 25: ! 26: --*/ ! 27: ! 28: #include "ntddk.h" ! 29: #include "stdarg.h" ! 30: #include "stdio.h" ! 31: #include "ntdddisk.h" ! 32: ! 33: // ! 34: // This macro has the effect of Bit = log2(Data) ! 35: // and is used to calculate sector shifts. ! 36: // ! 37: ! 38: #define WHICH_BIT(Data, Bit) { \ ! 39: for (Bit = 0; Bit < 32; Bit++) { \ ! 40: if ((Data >> Bit) == 1) { \ ! 41: break; \ ! 42: } \ ! 43: } \ ! 44: } ! 45: ! 46: // ! 47: // Device Extension ! 48: // ! 49: ! 50: typedef struct _DEVICE_EXTENSION { ! 51: ! 52: // ! 53: // Back pointer to device object ! 54: // ! 55: ! 56: PDEVICE_OBJECT DeviceObject; ! 57: ! 58: // ! 59: // Target Device Object ! 60: // ! 61: ! 62: PDEVICE_OBJECT TargetDeviceObject; ! 63: ! 64: // ! 65: // Physical Device Object ! 66: // ! 67: ! 68: PDEVICE_OBJECT PhysicalDevice; ! 69: ! 70: // ! 71: // Sector size ! 72: // ! 73: ! 74: ULONG SectorSize; ! 75: ! 76: // ! 77: // Sector Shift Count ! 78: // ! 79: ! 80: ULONG SectorShift; ! 81: ! 82: // ! 83: // Disk performance counters ! 84: // ! 85: ! 86: DISK_PERFORMANCE DiskCounters; ! 87: ! 88: // ! 89: // Spinlock for counters (physical disks only) ! 90: // ! 91: ! 92: KSPIN_LOCK Spinlock; ! 93: ! 94: } DEVICE_EXTENSION, *PDEVICE_EXTENSION; ! 95: ! 96: #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) ! 97: ! 98: ! 99: // ! 100: // Function declarations ! 101: // ! 102: ! 103: NTSTATUS ! 104: DriverEntry( ! 105: IN PDRIVER_OBJECT DriverObject, ! 106: IN PUNICODE_STRING RegistryPath ! 107: ); ! 108: ! 109: VOID ! 110: DiskPerfInitialize( ! 111: IN PDRIVER_OBJECT DriverObject, ! 112: IN PVOID NextDisk, ! 113: IN ULONG Count ! 114: ); ! 115: ! 116: NTSTATUS ! 117: DiskPerfCreate( ! 118: IN PDEVICE_OBJECT DeviceObject, ! 119: IN PIRP Irp ! 120: ); ! 121: ! 122: NTSTATUS ! 123: DiskPerfReadWrite( ! 124: IN PDEVICE_OBJECT DeviceObject, ! 125: IN PIRP Irp ! 126: ); ! 127: ! 128: NTSTATUS ! 129: DiskPerfIoCompletion( ! 130: IN PDEVICE_OBJECT DeviceObject, ! 131: IN PIRP Irp, ! 132: IN PVOID Context ! 133: ); ! 134: ! 135: NTSTATUS ! 136: DiskPerfDeviceControl( ! 137: IN PDEVICE_OBJECT DeviceObject, ! 138: IN PIRP Irp ! 139: ); ! 140: ! 141: NTSTATUS ! 142: DiskPerfShutdownFlush( ! 143: IN PDEVICE_OBJECT DeviceObject, ! 144: IN PIRP Irp ! 145: ); ! 146: ! 147: ! 148: NTSTATUS ! 149: DriverEntry( ! 150: IN PDRIVER_OBJECT DriverObject, ! 151: IN PUNICODE_STRING RegistryPath ! 152: ) ! 153: ! 154: /*++ ! 155: ! 156: Routine Description: ! 157: ! 158: This is the routine called by the system to initialize the disk ! 159: performance driver. The driver object is set up and then the ! 160: driver calls DiskPerfInitialize to attach to the boot devices. ! 161: ! 162: Arguments: ! 163: ! 164: DriverObject - The disk performance driver object. ! 165: ! 166: Return Value: ! 167: ! 168: NTSTATUS ! 169: ! 170: --*/ ! 171: ! 172: { ! 173: ! 174: // ! 175: // Set up the device driver entry points. ! 176: // ! 177: ! 178: DriverObject->MajorFunction[IRP_MJ_CREATE] = DiskPerfCreate; ! 179: DriverObject->MajorFunction[IRP_MJ_READ] = DiskPerfReadWrite; ! 180: DriverObject->MajorFunction[IRP_MJ_WRITE] = DiskPerfReadWrite; ! 181: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DiskPerfDeviceControl; ! 182: DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DiskPerfShutdownFlush; ! 183: DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = DiskPerfShutdownFlush; ! 184: ! 185: // ! 186: // Call the initialization routine for the first time. ! 187: // ! 188: ! 189: DiskPerfInitialize(DriverObject, 0, 0); ! 190: ! 191: return(STATUS_SUCCESS); ! 192: ! 193: } // DriverEntry ! 194: ! 195: ! 196: VOID ! 197: DiskPerfInitialize( ! 198: IN PDRIVER_OBJECT DriverObject, ! 199: IN PVOID NextDisk, ! 200: IN ULONG Count ! 201: ) ! 202: ! 203: /*++ ! 204: ! 205: Routine Description: ! 206: ! 207: Attach to new disk devices and partitions. ! 208: Set up device objects for counts and times. ! 209: If this is the first time this routine is called, ! 210: then register with the IO system to be called ! 211: after all other disk device drivers have initiated. ! 212: ! 213: Arguments: ! 214: ! 215: DriverObject - Disk performance driver object. ! 216: NextDisk - Starting disk for this part of the initialization. ! 217: Count - Not used. Number of times this routine has been called. ! 218: ! 219: Return Value: ! 220: ! 221: NTSTATUS ! 222: ! 223: --*/ ! 224: ! 225: { ! 226: PCONFIGURATION_INFORMATION configurationInformation; ! 227: CCHAR ntNameBuffer[256]; ! 228: STRING ntNameString; ! 229: UNICODE_STRING ntUnicodeString; ! 230: PDEVICE_OBJECT deviceObject; ! 231: PDEVICE_OBJECT physicalDevice; ! 232: PDEVICE_EXTENSION deviceExtension; ! 233: PFILE_OBJECT fileObject; ! 234: PIRP irp; ! 235: PDISK_GEOMETRY diskGeometry; ! 236: PDRIVE_LAYOUT_INFORMATION partitionInfo; ! 237: KEVENT event; ! 238: IO_STATUS_BLOCK ioStatusBlock; ! 239: NTSTATUS status; ! 240: ULONG diskNumber; ! 241: ULONG partNumber; ! 242: ! 243: // ! 244: // Get the configuration information. ! 245: // ! 246: ! 247: configurationInformation = IoGetConfigurationInformation(); ! 248: ! 249: // ! 250: // Find disk devices. ! 251: // ! 252: ! 253: for (diskNumber = (ULONG)NextDisk; ! 254: diskNumber < configurationInformation->DiskCount; ! 255: diskNumber++) { ! 256: ! 257: // ! 258: // Create device name for the physical disk. ! 259: // ! 260: ! 261: sprintf(ntNameBuffer, ! 262: "\\Device\\Harddisk%d\\Partition0", ! 263: diskNumber); ! 264: ! 265: RtlInitAnsiString(&ntNameString, ! 266: ntNameBuffer); ! 267: ! 268: RtlAnsiStringToUnicodeString(&ntUnicodeString, ! 269: &ntNameString, ! 270: TRUE); ! 271: ! 272: // ! 273: // Create device object for partition 0. ! 274: // ! 275: ! 276: status = IoCreateDevice(DriverObject, ! 277: sizeof(DEVICE_EXTENSION), ! 278: NULL, ! 279: FILE_DEVICE_DISK, ! 280: 0, ! 281: FALSE, ! 282: &physicalDevice); ! 283: ! 284: physicalDevice->Flags |= DO_DIRECT_IO; ! 285: ! 286: // ! 287: // Point device extension back at device object. ! 288: // ! 289: ! 290: deviceExtension = physicalDevice->DeviceExtension; ! 291: deviceExtension->DeviceObject = physicalDevice; ! 292: ! 293: // ! 294: // This is the physical device object. ! 295: // ! 296: ! 297: deviceExtension->PhysicalDevice = physicalDevice; ! 298: ! 299: // ! 300: // Attach to partition0. This call links the newly created ! 301: // device to the target device, returning the target device object. ! 302: // ! 303: ! 304: status = IoAttachDevice(physicalDevice, ! 305: &ntUnicodeString, ! 306: &deviceExtension->TargetDeviceObject); ! 307: ! 308: if (!NT_SUCCESS(status)) { ! 309: IoDeleteDevice(physicalDevice); ! 310: break; ! 311: } ! 312: ! 313: RtlFreeUnicodeString(&ntUnicodeString); ! 314: ! 315: // ! 316: // Allocate buffer for drive geometry. ! 317: // ! 318: ! 319: diskGeometry = ExAllocatePool(NonPagedPool, ! 320: sizeof(DISK_GEOMETRY)); ! 321: ! 322: // ! 323: // Create IRP for get drive geometry device control. ! 324: // ! 325: ! 326: irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, ! 327: deviceExtension->TargetDeviceObject, ! 328: NULL, ! 329: 0, ! 330: diskGeometry, ! 331: sizeof(DISK_GEOMETRY), ! 332: FALSE, ! 333: &event, ! 334: &ioStatusBlock); ! 335: ! 336: // ! 337: // Set the event object to the unsignaled state. ! 338: // It will be used to signal request completion. ! 339: // ! 340: ! 341: KeInitializeEvent(&event, ! 342: NotificationEvent, ! 343: FALSE); ! 344: ! 345: // ! 346: // No need to check the following two returned statuses as ! 347: // ioBlockStatus will have ending status. ! 348: // ! 349: ! 350: IoCallDriver(deviceExtension->TargetDeviceObject, ! 351: irp); ! 352: ! 353: KeWaitForSingleObject(&event, ! 354: Suspended, ! 355: KernelMode, ! 356: FALSE, ! 357: NULL); ! 358: ! 359: if (!NT_SUCCESS(ioStatusBlock.Status)) { ! 360: ExFreePool(diskGeometry); ! 361: IoDeleteDevice(physicalDevice); ! 362: break; ! 363: } ! 364: ! 365: // ! 366: // Store number of bytes per sector. ! 367: // ! 368: ! 369: deviceExtension->SectorSize = diskGeometry->BytesPerSector; ! 370: ! 371: // ! 372: // Calculate and store sector shift. ! 373: // ! 374: ! 375: WHICH_BIT(deviceExtension->SectorSize, deviceExtension->SectorShift); ! 376: ! 377: // ! 378: // Initialize spinlock for performance measures. ! 379: // ! 380: ! 381: KeInitializeSpinLock(&deviceExtension->Spinlock); ! 382: ! 383: // ! 384: // Allocate buffer for drive layout. ! 385: // ! 386: ! 387: partitionInfo = ExAllocatePool(NonPagedPool, ! 388: (26 * sizeof(PARTITION_INFORMATION) + 4)); ! 389: ! 390: // ! 391: // Create IRP for get drive layout device control. ! 392: // ! 393: ! 394: irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT, ! 395: deviceExtension->TargetDeviceObject, ! 396: NULL, ! 397: 0, ! 398: partitionInfo, ! 399: (26 * sizeof(PARTITION_INFORMATION) + 4), ! 400: FALSE, ! 401: &event, ! 402: &ioStatusBlock); ! 403: ! 404: // ! 405: // Set the event object to the unsignaled state. ! 406: // It will be used to signal request completion. ! 407: // ! 408: ! 409: KeInitializeEvent(&event, ! 410: NotificationEvent, ! 411: FALSE); ! 412: ! 413: // ! 414: // No need to check the following two returned statuses as ! 415: // ioBlockStatus will have ending status. ! 416: // ! 417: ! 418: IoCallDriver(deviceExtension->TargetDeviceObject, ! 419: irp); ! 420: ! 421: KeWaitForSingleObject(&event, ! 422: Suspended, ! 423: KernelMode, ! 424: FALSE, ! 425: NULL); ! 426: ! 427: if (!NT_SUCCESS(ioStatusBlock.Status)) { ! 428: ExFreePool(partitionInfo); ! 429: ExFreePool(diskGeometry); ! 430: IoDeleteDevice(physicalDevice); ! 431: break; ! 432: } ! 433: ! 434: for (partNumber = 1; ! 435: partNumber < partitionInfo->PartitionCount; ! 436: partNumber++) { ! 437: ! 438: // ! 439: // Create device name for partition. ! 440: // ! 441: ! 442: sprintf(ntNameBuffer, ! 443: "\\Device\\Harddisk%d\\Partition%d", ! 444: diskNumber, ! 445: partNumber); ! 446: ! 447: RtlInitAnsiString(&ntNameString, ! 448: ntNameBuffer); ! 449: ! 450: RtlAnsiStringToUnicodeString(&ntUnicodeString, ! 451: &ntNameString, ! 452: TRUE); ! 453: ! 454: // ! 455: // Get target device object. ! 456: // ! 457: ! 458: status = IoGetDeviceObjectPointer(&ntUnicodeString, ! 459: FILE_READ_ATTRIBUTES, ! 460: &fileObject, ! 461: &deviceObject); ! 462: ! 463: if (!NT_SUCCESS(status)) { ! 464: RtlFreeUnicodeString(&ntUnicodeString); ! 465: continue; ! 466: } ! 467: ! 468: // ! 469: // Check if this device is already mounted. ! 470: // ! 471: ! 472: if (!deviceObject->Vpb || ! 473: (deviceObject->Vpb->Flags & VPB_MOUNTED)) { ! 474: ! 475: // ! 476: // Can't attach to a device that is already mounted. ! 477: // ! 478: ! 479: ObDereferenceObject(fileObject); ! 480: RtlFreeUnicodeString(&ntUnicodeString); ! 481: continue; ! 482: } ! 483: ! 484: ObDereferenceObject(fileObject); ! 485: ! 486: // ! 487: // Create device object for this partition. ! 488: // ! 489: ! 490: status = IoCreateDevice(DriverObject, ! 491: sizeof(DEVICE_EXTENSION), ! 492: NULL, ! 493: FILE_DEVICE_DISK, ! 494: 0, ! 495: FALSE, ! 496: &deviceObject); ! 497: ! 498: deviceObject->Flags |= DO_DIRECT_IO; ! 499: ! 500: // ! 501: // Point device extension back at device object. ! 502: // ! 503: ! 504: deviceExtension = deviceObject->DeviceExtension; ! 505: deviceExtension->DeviceObject = deviceObject; ! 506: ! 507: // ! 508: // Store pointer to physical device. ! 509: // ! 510: ! 511: deviceExtension->PhysicalDevice = physicalDevice; ! 512: ! 513: // ! 514: // Attach to the partition. This call links the newly created ! 515: // device to the target device, returning the target device object. ! 516: // ! 517: ! 518: status = IoAttachDevice(deviceObject, ! 519: &ntUnicodeString, ! 520: &deviceExtension->TargetDeviceObject); ! 521: ! 522: RtlFreeUnicodeString(&ntUnicodeString); ! 523: ! 524: if (!NT_SUCCESS(status)) { ! 525: ExFreePool(diskGeometry); ! 526: IoDeleteDevice(deviceObject); ! 527: break; ! 528: } ! 529: } ! 530: } ! 531: ! 532: // ! 533: // Check if this is the first time this routine has been called. ! 534: // ! 535: ! 536: if (!NextDisk) { ! 537: ! 538: // ! 539: // Register with IO system to be called a second time after all ! 540: // other device drivers have initialized. ! 541: // ! 542: ! 543: IoRegisterDriverReinitialization(DriverObject, ! 544: DiskPerfInitialize, ! 545: (PVOID)configurationInformation->DiskCount); ! 546: } ! 547: ! 548: return; ! 549: ! 550: } // end DiskPerfInitialize() ! 551: ! 552: ! 553: NTSTATUS ! 554: DiskPerfCreate( ! 555: IN PDEVICE_OBJECT DeviceObject, ! 556: IN PIRP Irp ! 557: ) ! 558: ! 559: /*++ ! 560: ! 561: Routine Description: ! 562: ! 563: This routine services open commands. It establishes ! 564: the driver's existance by returning status success. ! 565: ! 566: Arguments: ! 567: ! 568: DeviceObject - Context for the activity. ! 569: Irp - The device control argument block. ! 570: ! 571: Return Value: ! 572: ! 573: NT Status ! 574: ! 575: --*/ ! 576: ! 577: { ! 578: UNREFERENCED_PARAMETER(DeviceObject); ! 579: ! 580: Irp->IoStatus.Status = STATUS_SUCCESS; ! 581: ! 582: IoCompleteRequest(Irp, 0); ! 583: return STATUS_SUCCESS; ! 584: ! 585: } // end DiskPerfCreate() ! 586: ! 587: ! 588: NTSTATUS ! 589: DiskPerfReadWrite( ! 590: IN PDEVICE_OBJECT DeviceObject, ! 591: IN PIRP Irp ! 592: ) ! 593: ! 594: /*++ ! 595: ! 596: Routine Description: ! 597: ! 598: This is the driver entry point for read and write requests ! 599: to disks to which the diskperf driver has attached. ! 600: This driver collects statistics and then sets a completion ! 601: routine so that it can collect additional information when ! 602: the request completes. Then it calls the next driver below ! 603: it. ! 604: ! 605: Arguments: ! 606: ! 607: DeviceObject ! 608: Irp ! 609: ! 610: Return Value: ! 611: ! 612: NTSTATUS ! 613: ! 614: --*/ ! 615: ! 616: { ! 617: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 618: PDEVICE_EXTENSION physicalDisk = ! 619: deviceExtension->PhysicalDevice->DeviceExtension; ! 620: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); ! 621: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); ! 622: ! 623: // ! 624: // Increment queue depth counter. ! 625: // ! 626: ! 627: ExInterlockedIncrementLong(&deviceExtension->DiskCounters.QueueDepth, ! 628: &physicalDisk->Spinlock); ! 629: ! 630: // ! 631: // Now get the physical disk counters and increment queue depth. ! 632: // ! 633: ! 634: ExInterlockedIncrementLong(&physicalDisk->DiskCounters.QueueDepth, ! 635: &physicalDisk->Spinlock); ! 636: ! 637: // ! 638: // Copy current stack to next stack. ! 639: // ! 640: ! 641: *nextIrpStack = *currentIrpStack; ! 642: ! 643: // ! 644: // Time stamp current request start. ! 645: // ! 646: ! 647: currentIrpStack->Parameters.Read.ByteOffset = KeQueryPerformanceCounter((PVOID)NULL); ! 648: ! 649: // ! 650: // Set completion routine callback. ! 651: // ! 652: ! 653: IoSetCompletionRoutine(Irp, ! 654: DiskPerfIoCompletion, ! 655: DeviceObject, ! 656: TRUE, ! 657: TRUE, ! 658: TRUE); ! 659: ! 660: // ! 661: // Return the results of the call to the disk driver. ! 662: // ! 663: ! 664: return IoCallDriver(deviceExtension->TargetDeviceObject, ! 665: Irp); ! 666: ! 667: } // end DiskPerfReadWrite() ! 668: ! 669: ! 670: NTSTATUS ! 671: DiskPerfIoCompletion( ! 672: IN PDEVICE_OBJECT DeviceObject, ! 673: IN PIRP Irp, ! 674: IN PVOID Context ! 675: ) ! 676: ! 677: /*++ ! 678: ! 679: Routine Description: ! 680: ! 681: This routine will get control from the system at the completion of an IRP. ! 682: It will calculate the difference between the time the IRP was started ! 683: and the current time, and decrement the queue depth. ! 684: ! 685: Arguments: ! 686: ! 687: DeviceObject - for the IRP. ! 688: Irp - The I/O request that just completed. ! 689: Context - Not used. ! 690: ! 691: Return Value: ! 692: ! 693: The IRP status. ! 694: ! 695: --*/ ! 696: ! 697: { ! 698: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 699: PDEVICE_EXTENSION physicalDisk = ! 700: deviceExtension->PhysicalDevice->DeviceExtension; ! 701: PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); ! 702: PDISK_PERFORMANCE partitionCounters = &deviceExtension->DiskCounters; ! 703: PDISK_PERFORMANCE diskCounters = &physicalDisk->DiskCounters; ! 704: LARGE_INTEGER timeStampStart = ! 705: irpStack->Parameters.Read.ByteOffset; ! 706: LARGE_INTEGER timeStampComplete; ! 707: KIRQL currentIrql; ! 708: ! 709: UNREFERENCED_PARAMETER(Context); ! 710: ! 711: // ! 712: // Determine if STATUS_PENDING was returned in the dispatch routine. ! 713: // ! 714: ! 715: if (Irp->PendingReturned) { ! 716: IoMarkIrpPending(Irp); ! 717: } ! 718: // ! 719: // Time stamp current request complete. ! 720: // ! 721: ! 722: timeStampComplete = KeQueryPerformanceCounter((PVOID)NULL); ! 723: ! 724: // ! 725: // Update counters under spinlock protection. ! 726: // ! 727: ! 728: KeAcquireSpinLock(&physicalDisk->Spinlock, ¤tIrql); ! 729: ! 730: // ! 731: // Decrement the queue depth counters for the volume and physical disk. ! 732: // ! 733: ! 734: partitionCounters->QueueDepth--; ! 735: diskCounters->QueueDepth--; ! 736: ! 737: #if DBG ! 738: ! 739: // ! 740: // Verify that the information field, which is used to ! 741: // return bytes transferred, is being updated by lower drivers. ! 742: // ! 743: ! 744: if (NT_SUCCESS(Irp->IoStatus.Status)) { ! 745: ASSERT(Irp->IoStatus.Information); ! 746: } ! 747: ! 748: #endif ! 749: ! 750: if (irpStack->MajorFunction == IRP_MJ_READ) { ! 751: ! 752: // ! 753: // Add bytes in this request to bytes read counters. ! 754: // ! 755: ! 756: partitionCounters->BytesRead = RtlLargeIntegerAdd(partitionCounters->BytesRead, ! 757: RtlConvertUlongToLargeInteger(Irp->IoStatus.Information)); ! 758: ! 759: diskCounters->BytesRead = RtlLargeIntegerAdd(diskCounters->BytesRead, ! 760: RtlConvertUlongToLargeInteger(Irp->IoStatus.Information)); ! 761: ! 762: // ! 763: // Increment read requests processed counters. ! 764: // ! 765: ! 766: partitionCounters->ReadCount++; ! 767: diskCounters->ReadCount++; ! 768: ! 769: // ! 770: // Calculate request processing time. ! 771: // ! 772: ! 773: partitionCounters->ReadTime = RtlLargeIntegerAdd(partitionCounters->ReadTime, ! 774: RtlLargeIntegerSubtract(timeStampComplete, timeStampStart)); ! 775: ! 776: diskCounters->ReadTime = RtlLargeIntegerAdd(diskCounters->ReadTime, ! 777: RtlLargeIntegerSubtract(timeStampComplete, timeStampStart)); ! 778: ! 779: } else { ! 780: ! 781: // ! 782: // Add bytes in this request to bytes write counters. ! 783: // ! 784: ! 785: partitionCounters->BytesWritten = RtlLargeIntegerAdd(partitionCounters->BytesWritten, ! 786: RtlConvertUlongToLargeInteger(Irp->IoStatus.Information)); ! 787: ! 788: diskCounters->BytesWritten = RtlLargeIntegerAdd(diskCounters->BytesWritten, ! 789: RtlConvertUlongToLargeInteger(Irp->IoStatus.Information)); ! 790: ! 791: // ! 792: // Increment write requests processed counters. ! 793: // ! 794: ! 795: partitionCounters->WriteCount++; ! 796: diskCounters->WriteCount++; ! 797: ! 798: // ! 799: // Calculate request processing time. ! 800: // ! 801: ! 802: partitionCounters->WriteTime = RtlLargeIntegerAdd(partitionCounters->WriteTime, ! 803: RtlLargeIntegerSubtract(timeStampComplete, timeStampStart)); ! 804: ! 805: diskCounters->WriteTime = RtlLargeIntegerAdd(diskCounters->WriteTime, ! 806: RtlLargeIntegerSubtract(timeStampComplete, timeStampStart)); ! 807: } ! 808: ! 809: // ! 810: // Release spinlock. ! 811: // ! 812: ! 813: KeReleaseSpinLock(&physicalDisk->Spinlock, currentIrql); ! 814: ! 815: return Irp->IoStatus.Status; ! 816: ! 817: } // DiskPerfIoCompletion ! 818: ! 819: ! 820: NTSTATUS ! 821: DiskPerfDeviceControl( ! 822: PDEVICE_OBJECT DeviceObject, ! 823: PIRP Irp ! 824: ) ! 825: ! 826: /*++ ! 827: ! 828: Routine Description: ! 829: ! 830: This device control dispatcher handles only the disk performance ! 831: device control. All others are passed down to the disk drivers. ! 832: The disk performane device control returns a current snapshot of ! 833: the performance data. ! 834: ! 835: Arguments: ! 836: ! 837: DeviceObject - Context for the activity. ! 838: Irp - The device control argument block. ! 839: ! 840: Return Value: ! 841: ! 842: Status is returned. ! 843: ! 844: --*/ ! 845: ! 846: { ! 847: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 848: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); ! 849: KIRQL currentIrql; ! 850: ! 851: if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == ! 852: IOCTL_DISK_PERFORMANCE) { ! 853: ! 854: NTSTATUS status; ! 855: ! 856: // ! 857: // Verify user buffer is large enough for the performance data. ! 858: // ! 859: ! 860: if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength < ! 861: sizeof(DISK_PERFORMANCE)) { ! 862: ! 863: // ! 864: // Indicate unsuccessful status and no data transferred. ! 865: // ! 866: ! 867: status = STATUS_BUFFER_TOO_SMALL; ! 868: Irp->IoStatus.Information = 0; ! 869: ! 870: } else { ! 871: ! 872: PDEVICE_EXTENSION physicalDisk = ! 873: deviceExtension->PhysicalDevice->DeviceExtension; ! 874: ! 875: // ! 876: // Copy disk counters to buffer under spinlock protection. ! 877: // ! 878: ! 879: KeAcquireSpinLock(&physicalDisk->Spinlock, ¤tIrql); ! 880: ! 881: RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, ! 882: &deviceExtension->DiskCounters, ! 883: sizeof(DISK_PERFORMANCE)); ! 884: ! 885: KeReleaseSpinLock(&physicalDisk->Spinlock, currentIrql); ! 886: ! 887: // ! 888: // Set IRP status to success and indicate bytes transferred. ! 889: // ! 890: ! 891: status = STATUS_SUCCESS; ! 892: Irp->IoStatus.Information = sizeof(DISK_PERFORMANCE); ! 893: } ! 894: ! 895: // ! 896: // Complete request. ! 897: // ! 898: ! 899: Irp->IoStatus.Status = status; ! 900: IoCompleteRequest(Irp, 0); ! 901: return status; ! 902: ! 903: } else { ! 904: ! 905: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); ! 906: ! 907: #if 0 ! 908: // ! 909: // Copy stack parameters to next stack. ! 910: // ! 911: ! 912: RtlMoveMemory(nextIrpStack, ! 913: currentIrpStack, ! 914: sizeof(IO_STACK_LOCATION)); ! 915: ! 916: // ! 917: // Set IRP so IoComplete does not call completion routine ! 918: // for this driver. ! 919: // ! 920: ! 921: IoSetCompletionRoutine(Irp, ! 922: NULL, ! 923: DeviceObject, ! 924: FALSE, ! 925: FALSE, ! 926: FALSE); ! 927: #endif ! 928: ! 929: // ! 930: // Set current stack back one. ! 931: // ! 932: ! 933: Irp->CurrentLocation++, ! 934: Irp->Tail.Overlay.CurrentStackLocation++; ! 935: ! 936: // ! 937: // Pass unrecognized device control requests ! 938: // down to next driver layer. ! 939: // ! 940: ! 941: return IoCallDriver(deviceExtension->TargetDeviceObject, Irp); ! 942: } ! 943: ! 944: } // end DiskPerfDeviceControl() ! 945: ! 946: ! 947: NTSTATUS ! 948: DiskPerfShutdownFlush( ! 949: IN PDEVICE_OBJECT DeviceObject, ! 950: IN PIRP Irp ! 951: ) ! 952: ! 953: /*++ ! 954: ! 955: Routine Description: ! 956: ! 957: This routine is called for a shutdown and flush IRPs. These are sent by the ! 958: system before it actually shuts down or when the file system does a flush. ! 959: ! 960: Arguments: ! 961: ! 962: DriverObject - Pointer to device object to being shutdown by system. ! 963: Irp - IRP involved. ! 964: ! 965: Return Value: ! 966: ! 967: NT Status ! 968: ! 969: --*/ ! 970: ! 971: { ! 972: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 973: ! 974: // ! 975: // Set current stack back one. ! 976: // ! 977: ! 978: Irp->CurrentLocation++, ! 979: Irp->Tail.Overlay.CurrentStackLocation++; ! 980: ! 981: return IoCallDriver(deviceExtension->TargetDeviceObject, Irp); ! 982: ! 983: } // end DiskPerfShutdownFlush() ! 984:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.