ohmu
·
2026-10-15
1#include "diskio.h"
2#include "common/debug.h"
3#include "common/io.h"
4#include "common/strutil.h"
5#include "common/mallocHelper.h"
6
7#include <errno.h>
8#include <string.h>
9
10#include <sys/iostat.h>
11#include <sys/sysctl.h>
12
13const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) {
14 int mib[] = { CTL_HW, HW_IOSTATS, sizeof(struct io_sysctl) };
15 size_t len;
16 if (sysctl(mib, ARRAY_SIZE(mib), nullptr, &len, nullptr, 0) < 0) {
17 FF_DEBUG("sysctl({HW_IOSTATS}, nullptr) failed: %s", strerror(errno));
18 return "sysctl({HW_IOSTATS}, nullptr) failed";
19 }
20 uint32_t nDrive = (uint32_t) (len / sizeof(struct io_sysctl));
21
22 FF_AUTO_FREE struct io_sysctl* stats = malloc(len);
23
24 if (sysctl(mib, ARRAY_SIZE(mib), stats, &len, nullptr, 0) < 0) {
25 FF_DEBUG("sysctl({HW_IOSTATS}, stats) failed: %s", strerror(errno));
26 return "sysctl({HW_IOSTATS}, stats) failed";
27 }
28
29 char path[64] = "/dev/";
30
31 for (uint32_t i = 0; i < nDrive; ++i) {
32 struct io_sysctl* st = &stats[i];
33
34 if (options->namePrefix.length && strncmp(st->name, options->namePrefix.chars, options->namePrefix.length) != 0) {
35 continue;
36 }
37
38 // Skip partitions
39 char* end = ffStrCopy(&path[5], st->name, ARRAY_SIZE(path) - 8);
40 *end++ = 'c';
41 *end = '\0';
42 if (!ffPathExists(path, FF_PATHTYPE_ANY)) {
43 continue;
44 }
45
46 FFDiskIOResult* device = FF_LIST_ADD(FFDiskIOResult, *result);
47 ffStrbufInitNS(&device->devPath, (uint32_t) (end - path), path);
48 ffStrbufInitS(&device->name, st->name);
49 device->bytesRead = st->rbytes;
50 device->readCount = st->rxfer;
51 device->bytesWritten = st->wbytes;
52 device->writeCount = st->wxfer;
53 }
54
55 return nullptr;
56}