github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/system/disk/iostat_darwin.c (about)

     1  // https://github.com/lufia/iostat/blob/9f7362b77ad333b26c01c99de52a11bdb650ded2/iostat_darwin.c
     2  #include <stdint.h>
     3  #include <CoreFoundation/CoreFoundation.h>
     4  #include "iostat_darwin.h"
     5  
     6  #define IOKIT	1	/* to get io_name_t in device_types.h */
     7  
     8  #include <IOKit/IOKitLib.h>
     9  #include <IOKit/storage/IOBlockStorageDriver.h>
    10  #include <IOKit/storage/IOMedia.h>
    11  #include <IOKit/IOBSD.h>
    12  
    13  #include <mach/mach_host.h>
    14  
    15  static int getdrivestat(io_registry_entry_t d, DriveStats *stat);
    16  static int fillstat(io_registry_entry_t d, DriveStats *stat);
    17  
    18  int
    19  readdrivestat(DriveStats a[], int n)
    20  {
    21  	mach_port_t port;
    22  	CFMutableDictionaryRef match;
    23  	io_iterator_t drives;
    24  	io_registry_entry_t d;
    25  	kern_return_t status;
    26  	int na, rv;
    27  
    28  	IOMasterPort(bootstrap_port, &port);
    29  	match = IOServiceMatching("IOMedia");
    30  	CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue);
    31  	status = IOServiceGetMatchingServices(port, match, &drives);
    32  	if(status != KERN_SUCCESS)
    33  		return -1;
    34  
    35  	na = 0;
    36  	while(na < n && (d=IOIteratorNext(drives)) > 0){
    37  		rv = getdrivestat(d, &a[na]);
    38  		if(rv < 0)
    39  			return -1;
    40  		if(rv > 0)
    41  			na++;
    42  		IOObjectRelease(d);
    43  	}
    44  	IOObjectRelease(drives);
    45  	return na;
    46  }
    47  
    48  static int
    49  getdrivestat(io_registry_entry_t d, DriveStats *stat)
    50  {
    51  	io_registry_entry_t parent;
    52  	kern_return_t status;
    53  	CFDictionaryRef props;
    54  	CFStringRef name;
    55  	CFNumberRef num;
    56  	int rv;
    57  
    58  	memset(stat, 0, sizeof *stat);
    59  	status = IORegistryEntryGetParentEntry(d, kIOServicePlane, &parent);
    60  	if(status != KERN_SUCCESS)
    61  		return -1;
    62  	if(!IOObjectConformsTo(parent, "IOBlockStorageDriver")){
    63  		IOObjectRelease(parent);
    64  		return 0;
    65  	}
    66  
    67  	status = IORegistryEntryCreateCFProperties(d, (CFMutableDictionaryRef *)&props, kCFAllocatorDefault, kNilOptions);
    68  	if(status != KERN_SUCCESS){
    69  		IOObjectRelease(parent);
    70  		return -1;
    71  	}
    72  	name = (CFStringRef)CFDictionaryGetValue(props, CFSTR(kIOBSDNameKey));
    73  	CFStringGetCString(name, stat->name, NAMELEN, CFStringGetSystemEncoding());
    74  	num = (CFNumberRef)CFDictionaryGetValue(props, CFSTR(kIOMediaSizeKey));
    75  	CFNumberGetValue(num, kCFNumberSInt64Type, &stat->size);
    76  	num = (CFNumberRef)CFDictionaryGetValue(props, CFSTR(kIOMediaPreferredBlockSizeKey));
    77  	CFNumberGetValue(num, kCFNumberSInt64Type, &stat->blocksize);
    78  	CFRelease(props);
    79  
    80  	rv = fillstat(parent, stat);
    81  	IOObjectRelease(parent);
    82  	if(rv < 0)
    83  		return -1;
    84  	return 1;
    85  }
    86  
    87  static struct {
    88  	char *key;
    89  	size_t off;
    90  } statstab[] = {
    91  	{kIOBlockStorageDriverStatisticsBytesReadKey, offsetof(DriveStats, read)},
    92  	{kIOBlockStorageDriverStatisticsBytesWrittenKey, offsetof(DriveStats, written)},
    93  	{kIOBlockStorageDriverStatisticsReadsKey, offsetof(DriveStats, nread)},
    94  	{kIOBlockStorageDriverStatisticsWritesKey, offsetof(DriveStats, nwrite)},
    95  	{kIOBlockStorageDriverStatisticsTotalReadTimeKey, offsetof(DriveStats, readtime)},
    96  	{kIOBlockStorageDriverStatisticsTotalWriteTimeKey, offsetof(DriveStats, writetime)},
    97  	{kIOBlockStorageDriverStatisticsLatentReadTimeKey, offsetof(DriveStats, readlat)},
    98  	{kIOBlockStorageDriverStatisticsLatentWriteTimeKey, offsetof(DriveStats, writelat)},
    99  };
   100  
   101  static int
   102  fillstat(io_registry_entry_t d, DriveStats *stat)
   103  {
   104  	CFDictionaryRef props, v;
   105  	CFNumberRef num;
   106  	kern_return_t status;
   107  	typeof(statstab[0]) *bp, *ep;
   108  
   109  	status = IORegistryEntryCreateCFProperties(d, (CFMutableDictionaryRef *)&props, kCFAllocatorDefault, kNilOptions);
   110  	if(status != KERN_SUCCESS)
   111  		return -1;
   112  	v = (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOBlockStorageDriverStatisticsKey));
   113  	if(v == NULL){
   114  		CFRelease(props);
   115  		return -1;
   116  	}
   117  
   118  	ep = &statstab[sizeof(statstab)/sizeof(statstab[0])];
   119  	for(bp = &statstab[0]; bp < ep; bp++){
   120  		CFStringRef s;
   121  
   122  		s = CFStringCreateWithCString(kCFAllocatorDefault, bp->key, CFStringGetSystemEncoding());
   123  		num = (CFNumberRef)CFDictionaryGetValue(v, s);
   124  		if(num)
   125  			CFNumberGetValue(num, kCFNumberSInt64Type, ((char*)stat)+bp->off);
   126  		CFRelease(s);
   127  	}
   128  
   129  	CFRelease(props);
   130  	return 0;
   131  }