ZFS arcstats for Linux

If no pools are imported (ARC size == 0) or the
ZFS module is not in the kernel (/proc/spl/kstat/zfs/arcstats
does not exist), then the Meter reports "Unavailable".
This commit is contained in:
Ross Williams
2019-07-07 02:37:02 +00:00
parent a93edde1a2
commit 070fe90461
6 changed files with 130 additions and 23 deletions

View File

@ -94,6 +94,15 @@ typedef struct LinuxProcessList_ {
struct nl_sock *netlink_socket;
int netlink_family;
#endif
int zfsArcEnabled;
unsigned long long int memZfsArc;
unsigned long long int zfsArcMax;
unsigned long long int zfsArcMFU;
unsigned long long int zfsArcMRU;
unsigned long long int zfsArcAnon;
unsigned long long int zfsArcHeader;
unsigned long long int zfsArcOther;
} LinuxProcessList;
#ifndef PROCDIR
@ -108,6 +117,10 @@ typedef struct LinuxProcessList_ {
#define PROCMEMINFOFILE PROCDIR "/meminfo"
#endif
#ifndef PROCARCSTATSFILE
#define PROCARCSTATSFILE PROCDIR "/spl/kstat/zfs/arcstats"
#endif
#ifndef PROCTTYDRIVERSFILE
#define PROCTTYDRIVERSFILE PROCDIR "/tty/drivers"
#endif
@ -964,6 +977,58 @@ static inline void LinuxProcessList_scanMemoryInfo(ProcessList* this) {
fclose(file);
}
static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) {
unsigned long long int dbufSize;
unsigned long long int dnodeSize;
unsigned long long int bonusSize;
FILE* file = fopen(PROCARCSTATSFILE, "r");
if (file == NULL) {
lpl->zfsArcEnabled = 0;
return;
}
char buffer[128];
while (fgets(buffer, 128, file)) {
#define tryRead(label, variable) do { if (String_startsWith(buffer, label) && sscanf(buffer + strlen(label), " %*2u %32llu", variable)) { break; } } while(0)
switch (buffer[0]) {
case 'c':
tryRead("c_max", &lpl->zfsArcMax);
break;
case 's':
tryRead("size", &lpl->memZfsArc);
break;
case 'h':
tryRead("hdr_size", &lpl->zfsArcHeader);
break;
case 'd':
tryRead("dbuf_size", &dbufSize);
tryRead("dnode_size", &dnodeSize);
break;
case 'b':
tryRead("bonus_size", &bonusSize);
break;
case 'a':
tryRead("anon_size", &lpl->zfsArcAnon);
break;
case 'm':
tryRead("mfu_size", &lpl->zfsArcMFU);
tryRead("mru_size", &lpl->zfsArcMRU);
break;
}
#undef tryRead
}
fclose(file);
lpl->zfsArcEnabled = (lpl->memZfsArc > 0 ? 1 : 0);
lpl->memZfsArc /= 1024;
lpl->zfsArcMax /= 1024;
lpl->zfsArcMFU /= 1024;
lpl->zfsArcMRU /= 1024;
lpl->zfsArcAnon /= 1024;
lpl->zfsArcHeader /= 1024;
lpl->zfsArcOther = (dbufSize + dnodeSize + bonusSize) / 1024;
}
static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) {
FILE* file = fopen(PROCSTATFILE, "r");
@ -1038,6 +1103,7 @@ void ProcessList_goThroughEntries(ProcessList* super) {
LinuxProcessList* this = (LinuxProcessList*) super;
LinuxProcessList_scanMemoryInfo(super);
LinuxProcessList_scanZfsArcstats(this);
double period = LinuxProcessList_scanCPUTime(this);
struct timeval tv;