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
|
#include "diskio.h"
#include "common/time.h"
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options);
static FFlist ioCounters1;
static uint64_t time1;
void ffPrepareDiskIO(FFDiskIOOptions* options) {
if (options->detectTotal) {
return;
}
if (time1 != 0) {
return; // Already prepared
}
ffListInit(&ioCounters1);
ffDiskIOGetIoCounters(&ioCounters1, options);
time1 = ffTimeGetNow();
}
const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options) {
const char* error = NULL;
if (options->detectTotal) {
error = ffDiskIOGetIoCounters(result, options);
if (error) {
return error;
}
return NULL;
}
if (time1 == 0) {
ffListInit(&ioCounters1);
error = ffDiskIOGetIoCounters(&ioCounters1, options);
if (error) {
return error;
}
time1 = ffTimeGetNow();
}
if (ioCounters1.length == 0) {
return "No physical disk found";
}
uint64_t time2 = ffTimeGetNow();
while (time2 - time1 < options->waitTime) {
ffTimeSleep((uint32_t) (options->waitTime - (time2 - time1)));
time2 = ffTimeGetNow();
}
error = ffDiskIOGetIoCounters(result, options);
if (error) {
return error;
}
if (result->length != ioCounters1.length) {
return "Different number of physical disks. Hardware change?";
}
for (uint32_t i = 0; i < result->length; ++i) {
FFDiskIOResult* icPrev = FF_LIST_GET(FFDiskIOResult, ioCounters1, i);
FFDiskIOResult* icCurr = FF_LIST_GET(FFDiskIOResult, *result, i);
if (!ffStrbufEqual(&icPrev->devPath, &icCurr->devPath)) {
return "Physical disk device path changed";
}
static_assert(sizeof(FFDiskIOResult) - offsetof(FFDiskIOResult, bytesRead) == sizeof(uint64_t) * 4, "Unexpected struct FFDiskIOResult layout");
for (size_t off = offsetof(FFDiskIOResult, bytesRead); off < sizeof(FFDiskIOResult); off += sizeof(uint64_t)) {
uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off);
uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off);
uint64_t temp = *currValue;
*currValue -= *prevValue;
*currValue /= (time2 - time1) / 1000 /* seconds */;
// For next function call
*prevValue = temp;
}
}
// For next function call
time1 = time2;
// Leak ioCounters1 here
return NULL;
}
|