123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- #include <CoreFoundation/CoreFoundation.h>
- #include <IOKit/IOKitLib.h>
- #include <IOKit/storage/IOBlockStorageDriver.h>
- #include <IOKit/storage/IOMedia.h>
- #include <IOKit/IOBSD.h>
- // The iterator of all things disk. Allocated by StartIOCounterFetch, released
- // by EndIOCounterFetch.
- static io_iterator_t diskIter;
- // Begins fetching IO counters.
- //
- // Returns 1 if the fetch started successfully, false otherwise.
- //
- // If the fetch was started successfully, you must call EndIOCounterFetch once
- // done to release resources.
- int StartIOCounterFetch()
- {
- if (IOServiceGetMatchingServices(kIOMasterPortDefault,
- IOServiceMatching(kIOMediaClass),
- &diskIter) != kIOReturnSuccess) {
- return 0;
- }
- return 1;
- }
- // Releases resources from fetching IO counters.
- void EndIOCounterFetch()
- {
- IOObjectRelease(diskIter);
- }
- // The current disk entry of interest. Allocated by FetchNextDisk(), released by
- // ReadDiskInfo().
- static io_registry_entry_t diskEntry;
- // The parent of diskEntry. Same lifetimes.
- static io_registry_entry_t parentEntry;
- // Fetches the next disk. Note that a disk entry is allocated, and will be held
- // until it is processed and freed by ReadDiskInfo.
- int FetchNextDisk()
- {
- while ((diskEntry = IOIteratorNext(diskIter)) != 0) {
- // We are iterating IOMedia. We need to get the parent too (IOBSD).
- if (IORegistryEntryGetParentEntry(diskEntry, kIOServicePlane, &parentEntry) != kIOReturnSuccess) {
- // something is wrong...
- IOObjectRelease(diskEntry);
- continue;
- }
- if (!IOObjectConformsTo(parentEntry, "IOBlockStorageDriver")) {
- // no use to us, try the next disk
- IOObjectRelease(diskEntry);
- IOObjectRelease(parentEntry);
- continue;
- }
- // Got a disk OK.
- return 1;
- }
- // No more disks.
- return 0;
- }
- // Reads the current disk (from iteration) info into DiskInfo struct.
- // Once done, all resources from the current iteration of reading are freed,
- // ready for FetchNextDisk() to be called again.
- int ReadDiskInfo(DiskInfo *info)
- {
- // Parent props. Allocated by us.
- CFDictionaryRef parentProps = NULL;
- // Disk props. Allocated by us.
- CFDictionaryRef diskProps = NULL;
- // Disk stats, fetched by us, but not allocated by us.
- CFDictionaryRef stats = NULL;
- if (IORegistryEntryCreateCFProperties(diskEntry, (CFMutableDictionaryRef *)&parentProps,
- kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
- {
- // can't get parent props, give up
- CFRelease(parentProps);
- IOObjectRelease(diskEntry);
- IOObjectRelease(parentEntry);
- return -1;
- }
- if (IORegistryEntryCreateCFProperties(parentEntry, (CFMutableDictionaryRef *)&diskProps,
- kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
- {
- // can't get disk props, give up
- CFRelease(parentProps);
- CFRelease(diskProps);
- IOObjectRelease(diskEntry);
- IOObjectRelease(parentEntry);
- return -1;
- }
- // Start fetching
- CFStringRef cfDiskName = (CFStringRef)CFDictionaryGetValue(parentProps, CFSTR(kIOBSDNameKey));
- CFStringGetCString(cfDiskName, info->DiskName, MAX_DISK_NAME, CFStringGetSystemEncoding());
- stats = (CFDictionaryRef)CFDictionaryGetValue( diskProps, CFSTR(kIOBlockStorageDriverStatisticsKey));
- if (stats == NULL) {
- // stat fetch failed...
- CFRelease(parentProps);
- CFRelease(diskProps);
- IOObjectRelease(parentEntry);
- IOObjectRelease(diskEntry);
- return -1;
- }
- CFNumberRef cfnum;
- if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) {
- CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->Reads);
- } else {
- info->Reads = 0;
- }
- if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) {
- CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->Writes);
- } else {
- info->Writes = 0;
- }
- if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) {
- CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->ReadBytes);
- } else {
- info->ReadBytes = 0;
- }
- if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) {
- CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->WriteBytes);
- } else {
- info->WriteBytes = 0;
- }
- if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) {
- CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->ReadTime);
- } else {
- info->ReadTime = 0;
- }
- if ((cfnum = (CFNumberRef)CFDictionaryGetValue(stats, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
- CFNumberGetValue(cfnum, kCFNumberSInt64Type, &info->WriteTime);
- } else {
- info->WriteTime = 0;
- }
- // note: read/write time are in ns, but we want ms.
- info->ReadTime = info->ReadTime / 1000 / 1000;
- info->WriteTime = info->WriteTime / 1000 / 1000;
- CFRelease(parentProps);
- CFRelease(diskProps);
- IOObjectRelease(parentEntry);
- IOObjectRelease(diskEntry);
- return 0;
- }
|