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