Skip to content

Instantly share code, notes, and snippets.

@edef1c
Last active May 20, 2020 14:09
Show Gist options
  • Save edef1c/73cc02efcdad39fbcc15f577dbc1922a to your computer and use it in GitHub Desktop.
Save edef1c/73cc02efcdad39fbcc15f577dbc1922a to your computer and use it in GitHub Desktop.
ZFS on Linux ARC support patch for htop (multi's revised version)
From 78ade158ed480a6958fd6d477ee90f2bd2d1f668 Mon Sep 17 00:00:00 2001
From: multiplexd <[email protected]>
Date: Sat, 9 May 2020 20:31:35 +0100
Subject: [PATCH v2] Linux: consider ZFS ARC to be cache
This patch adds an arcSize member to the ProcessList struct, and then
adjusts the usedMem and cachedMem values when the memory usage meter is
initialised in Platform_setMemoryValues(), and not earlier.
---
ProcessList.c | 1 +
ProcessList.h | 1 +
linux/LinuxProcessList.c | 27 +++++++++++++++++++++++++++
linux/LinuxProcessList.h | 4 ++++
linux/Platform.c | 5 +++--
5 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/ProcessList.c b/ProcessList.c
index 7482b03..7083957 100644
--- a/ProcessList.c
+++ b/ProcessList.c
@@ -67,6 +67,7 @@ typedef struct ProcessList_ {
unsigned long long int totalSwap;
unsigned long long int usedSwap;
unsigned long long int freeSwap;
+ unsigned long long int arcSize;
int cpuCount;
diff --git a/ProcessList.h b/ProcessList.h
index 572d484..65029f1 100644
--- a/ProcessList.h
+++ b/ProcessList.h
@@ -61,6 +61,7 @@ typedef struct ProcessList_ {
unsigned long long int totalSwap;
unsigned long long int usedSwap;
unsigned long long int freeSwap;
+ unsigned long long int arcSize;
int cpuCount;
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
index 2edd042..ed2f5c5 100644
--- a/linux/LinuxProcessList.c
+++ b/linux/LinuxProcessList.c
@@ -102,6 +102,10 @@ typedef struct LinuxProcessList_ {
#define PROCSTATFILE PROCDIR "/stat"
#endif
+#ifndef ARCSTATFILE
+#define ARCSTATFILE PROCDIR "/spl/kstat/zfs/arcstats"
+#endif
+
#ifndef PROCMEMINFOFILE
#define PROCMEMINFOFILE PROCDIR "/meminfo"
#endif
@@ -960,6 +964,29 @@ static inline void LinuxProcessList_scanMemoryInfo(ProcessList* this) {
this->cachedMem = this->cachedMem + sreclaimable - shmem;
this->usedSwap = this->totalSwap - swapFree;
fclose(file);
+
+ file = fopen(ARCSTATFILE, "r");
+ if (file == NULL && errno != ENOENT) {
+ CRT_fatalError("Cannot open " ARCSTATFILE);
+ }
+
+ if (file != NULL) {
+ // skip the first two lines
+ fgets(buffer, sizeof buffer, file);
+ fgets(buffer, sizeof buffer, file);
+
+ unsigned long long int arcsize = 0;
+ while (fgets(buffer, sizeof buffer, file)) {
+ #define tryRead(label, variable) do { if (String_startsWith(buffer, label) && sscanf(buffer + strlen(label), " %*d %llu", variable)) { break; } } while(0)
+ if (buffer[0] == 's') tryRead("size", &arcsize);
+ }
+
+ this->arcSize = arcsize / 1024;
+
+ fclose(file);
+ } else {
+ this->arcSize = 0;
+ }
}
static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) {
diff --git a/linux/LinuxProcessList.h b/linux/LinuxProcessList.h
index 0851a10..259941f 100644
--- a/linux/LinuxProcessList.h
+++ b/linux/LinuxProcessList.h
@@ -75,6 +75,10 @@ typedef struct LinuxProcessList_ {
#define PROCSTATFILE PROCDIR "/stat"
#endif
+#ifndef ARCSTATFILE
+#define ARCSTATFILE PROCDIR "/spl/kstat/zfs/arcstats"
+#endif
+
#ifndef PROCMEMINFOFILE
#define PROCMEMINFOFILE PROCDIR "/meminfo"
#endif
diff --git a/linux/Platform.c b/linux/Platform.c
index ab90ca7..fb78c4c 100644
--- a/linux/Platform.c
+++ b/linux/Platform.c
@@ -200,11 +200,12 @@ void Platform_setMemoryValues(Meter* this) {
long int usedMem = pl->usedMem;
long int buffersMem = pl->buffersMem;
long int cachedMem = pl->cachedMem;
- usedMem -= buffersMem + cachedMem;
+ long int arcSize = pl->arcSize;
+ usedMem -= buffersMem + cachedMem + arcSize;
this->total = pl->totalMem;
this->values[0] = usedMem;
this->values[1] = buffersMem;
- this->values[2] = cachedMem;
+ this->values[2] = cachedMem + arcSize;
}
void Platform_setSwapValues(Meter* this) {
--
2.25.1
@edef1c
Copy link
Author

edef1c commented May 20, 2020

This is a revised version of a patch similar in spirit to hishamhm/htop#976.

edef's patch had an underflow condition in Platform_setMemoryValues() in linux/Platform.c, as the ARC usage is deducted from the amount of used memory twice: once in LinuxProcessList_scanMemoryInfo() when the ARC statistics file in /proc is read, and once in Platform_setMemoryValues(), as cachedMem is deducted from usedMem. Note that cachedMem had the ARC size added and usedMem had the ARC size deducted already in Platform_setMemoryValues().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment