summaryrefslogtreecommitdiffstats
path: root/src/detection/diskio/diskio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/detection/diskio/diskio.c')
-rw-r--r--src/detection/diskio/diskio.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/detection/diskio/diskio.c b/src/detection/diskio/diskio.c
new file mode 100644
index 0000000..6ff66be
--- /dev/null
+++ b/src/detection/diskio/diskio.c
@@ -0,0 +1,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;
+}