#pragma once /* * diskstats.h -- sum the sector counters of the physical disks listed in * /proc/diskstats (node_information.c's io metric). */ #include #include #include /* A whole physical disk has /sys/block//device (a link to its * hardware). Partitions are not in /sys/block, and loop, ram, zram, dm- * and md devices have no `device` -- counting dm/md would also count the * same I/O twice, once more through their member disks. */ static inline int diskstats_is_physical(const char* sysblock, const char* name) { char path[512]; struct stat st; if (strchr(name, '/') != NULL || name[0] == '.') { return 0; } snprintf(path, sizeof(path), "%s/%s/device", sysblock, name); return stat(path, &st) == 0; } /* Sum sectors read/written over the physical disks in `fp` (a * /proc/diskstats stream). `sysblock` is the /sys/block directory. * Returns the number of disks counted. * * bug-1872: this used to guess from the name (skip names ending in a digit * or containing 'p'), which dropped every NVMe disk (nvme0n1), mmc disks * (mmcblk0) and even sdp. */ static inline int diskstats_sum_physical(FILE* fp, const char* sysblock, unsigned long long* sectors_read, unsigned long long* sectors_written) { char line[512]; int ndisks = 0; *sectors_read = 0; *sectors_written = 0; while (fgets(line, sizeof(line), fp)) { int major, minor; char name[64]; unsigned long long rc, rm, rd, rt, wc, wm, wr, wt, inprog, iot, wiot; if (sscanf(line, "%d %d %63s %llu %llu %llu %llu %llu %llu %llu %llu %llu " "%llu %llu", &major, &minor, name, &rc, &rm, &rd, &rt, &wc, &wm, &wr, &wt, &inprog, &iot, &wiot) < 14) { continue; } if (!diskstats_is_physical(sysblock, name)) { continue; } *sectors_read += rd; *sectors_written += wr; ndisks++; } return ndisks; }