about summary refs log tree commit diff
path: root/users/multi/pkgs/htop/zfs-arc-stats/0003-ZFS-arcstats-for-Linux.patch
diff options
context:
space:
mode:
Diffstat (limited to 'users/multi/pkgs/htop/zfs-arc-stats/0003-ZFS-arcstats-for-Linux.patch')
-rw-r--r--users/multi/pkgs/htop/zfs-arc-stats/0003-ZFS-arcstats-for-Linux.patch287
1 files changed, 287 insertions, 0 deletions
diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0003-ZFS-arcstats-for-Linux.patch b/users/multi/pkgs/htop/zfs-arc-stats/0003-ZFS-arcstats-for-Linux.patch
new file mode 100644
index 0000000000..f232f5e87d
--- /dev/null
+++ b/users/multi/pkgs/htop/zfs-arc-stats/0003-ZFS-arcstats-for-Linux.patch
@@ -0,0 +1,287 @@
+From 070fe90461182743fabb029415fc1bc59be14f3f Mon Sep 17 00:00:00 2001
+From: Ross Williams <ross@ross-williams.net>
+Date: Sun, 7 Jul 2019 02:37:02 +0000
+Subject: [PATCH 3/9] 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".
+---
+ Makefile.am              |  6 ++--
+ linux/LinuxProcessList.c | 66 ++++++++++++++++++++++++++++++++++++++++
+ linux/LinuxProcessList.h | 13 ++++++++
+ linux/Platform.c         | 19 ++++++++++++
+ linux/Platform.h         |  2 ++
+ zfs/ZfsArcMeter.c        | 47 +++++++++++++++-------------
+ 6 files changed, 130 insertions(+), 23 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index ad23d19..b850815 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -52,14 +52,16 @@ linux_platform_headers = \
+ 	linux/LinuxProcess.h \
+ 	linux/LinuxProcessList.h \
+ 	linux/LinuxCRT.h \
+-	linux/Battery.h
++	linux/Battery.h \
++	$(zfs_platform_headers)
+ 
+ all_platform_headers += $(linux_platform_headers)
+ 
+ if HTOP_LINUX
+ AM_CFLAGS += -rdynamic
+ myhtopplatsources = linux/Platform.c linux/IOPriorityPanel.c linux/IOPriority.c \
+-linux/LinuxProcess.c linux/LinuxProcessList.c linux/LinuxCRT.c linux/Battery.c
++linux/LinuxProcess.c linux/LinuxProcessList.c linux/LinuxCRT.c linux/Battery.c \
++$(zfs_platform_sources)
+ 
+ myhtopplatheaders = $(linux_platform_headers)
+ endif
+diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
+index 5f38540..4d19185 100644
+--- a/linux/LinuxProcessList.c
++++ b/linux/LinuxProcessList.c
+@@ -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;
+diff --git a/linux/LinuxProcessList.h b/linux/LinuxProcessList.h
+index f30b487..749231e 100644
+--- a/linux/LinuxProcessList.h
++++ b/linux/LinuxProcessList.h
+@@ -67,6 +67,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
+@@ -81,6 +90,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
+diff --git a/linux/Platform.c b/linux/Platform.c
+index ab90ca7..4e73c61 100644
+--- a/linux/Platform.c
++++ b/linux/Platform.c
+@@ -21,6 +21,7 @@ in the source distribution for its full text.
+ #include "UptimeMeter.h"
+ #include "ClockMeter.h"
+ #include "HostnameMeter.h"
++#include "zfs/ZfsArcMeter.h"
+ #include "LinuxProcess.h"
+ 
+ #include <math.h>
+@@ -126,6 +127,7 @@ MeterClass* Platform_meterTypes[] = {
+    &LeftCPUs2Meter_class,
+    &RightCPUs2Meter_class,
+    &BlankMeter_class,
++   &ZfsArcMeter_class,
+    NULL
+ };
+ 
+@@ -213,6 +215,23 @@ void Platform_setSwapValues(Meter* this) {
+    this->values[0] = pl->usedSwap;
+ }
+ 
++void Platform_setZfsArcValues(Meter* this) {
++   LinuxProcessList* lpl = (LinuxProcessList*) this->pl;
++
++   this->total = lpl->zfsArcMax;
++   this->values[0] = lpl->zfsArcMFU;
++   this->values[1] = lpl->zfsArcMRU;
++   this->values[2] = lpl->zfsArcAnon;
++   this->values[3] = lpl->zfsArcHeader;
++   this->values[4] = lpl->zfsArcOther;
++
++   // "Hide" the last value so it can
++   // only be accessed by index and is not
++   // displayed by the Bar or Graph style
++   Meter_setItems(this, 5);
++   this->values[5] = lpl->memZfsArc;
++}
++
+ char* Platform_getProcessEnv(pid_t pid) {
+    char procname[32+1];
+    xSnprintf(procname, 32, "/proc/%d/environ", pid);
+diff --git a/linux/Platform.h b/linux/Platform.h
+index b0456e5..e775181 100644
+--- a/linux/Platform.h
++++ b/linux/Platform.h
+@@ -43,6 +43,8 @@ void Platform_setMemoryValues(Meter* this);
+ 
+ void Platform_setSwapValues(Meter* this);
+ 
++void Platform_setZfsArcValues(Meter* this);
++
+ char* Platform_getProcessEnv(pid_t pid);
+ 
+ #endif
+diff --git a/zfs/ZfsArcMeter.c b/zfs/ZfsArcMeter.c
+index e12c46e..ebd8099 100644
+--- a/zfs/ZfsArcMeter.c
++++ b/zfs/ZfsArcMeter.c
+@@ -41,27 +41,32 @@ static void ZfsArcMeter_display(Object* cast, RichString* out) {
+    char buffer[50];
+    Meter* this = (Meter*)cast;
+ 
+-   RichString_write(out, CRT_colors[METER_TEXT], ":");
+-   Meter_humanUnit(buffer, this->total, 50);
+-   RichString_append(out, CRT_colors[METER_VALUE], buffer);
+-   Meter_humanUnit(buffer, this->values[5], 50);
+-   RichString_append(out, CRT_colors[METER_TEXT], " Used:");
+-   RichString_append(out, CRT_colors[METER_VALUE], buffer);
+-   Meter_humanUnit(buffer, this->values[0], 50);
+-   RichString_append(out, CRT_colors[METER_TEXT], " MFU:");
+-   RichString_append(out, CRT_colors[ZFS_MFU], buffer);
+-   Meter_humanUnit(buffer, this->values[1], 50);
+-   RichString_append(out, CRT_colors[METER_TEXT], " MRU:");
+-   RichString_append(out, CRT_colors[ZFS_MRU], buffer);
+-   Meter_humanUnit(buffer, this->values[2], 50);
+-   RichString_append(out, CRT_colors[METER_TEXT], " Anon:");
+-   RichString_append(out, CRT_colors[ZFS_ANON], buffer);
+-   Meter_humanUnit(buffer, this->values[3], 50);
+-   RichString_append(out, CRT_colors[METER_TEXT], " Hdr:");
+-   RichString_append(out, CRT_colors[ZFS_HEADER], buffer);
+-   Meter_humanUnit(buffer, this->values[4], 50);
+-   RichString_append(out, CRT_colors[METER_TEXT], " Oth:");
+-   RichString_append(out, CRT_colors[ZFS_OTHER], buffer);
++   if (this->values[5] > 0) {
++      RichString_write(out, CRT_colors[METER_TEXT], ":");
++      Meter_humanUnit(buffer, this->total, 50);
++      RichString_append(out, CRT_colors[METER_VALUE], buffer);
++      Meter_humanUnit(buffer, this->values[5], 50);
++      RichString_append(out, CRT_colors[METER_TEXT], " Used:");
++      RichString_append(out, CRT_colors[METER_VALUE], buffer);
++      Meter_humanUnit(buffer, this->values[0], 50);
++      RichString_append(out, CRT_colors[METER_TEXT], " MFU:");
++      RichString_append(out, CRT_colors[ZFS_MFU], buffer);
++      Meter_humanUnit(buffer, this->values[1], 50);
++      RichString_append(out, CRT_colors[METER_TEXT], " MRU:");
++      RichString_append(out, CRT_colors[ZFS_MRU], buffer);
++      Meter_humanUnit(buffer, this->values[2], 50);
++      RichString_append(out, CRT_colors[METER_TEXT], " Anon:");
++      RichString_append(out, CRT_colors[ZFS_ANON], buffer);
++      Meter_humanUnit(buffer, this->values[3], 50);
++      RichString_append(out, CRT_colors[METER_TEXT], " Hdr:");
++      RichString_append(out, CRT_colors[ZFS_HEADER], buffer);
++      Meter_humanUnit(buffer, this->values[4], 50);
++      RichString_append(out, CRT_colors[METER_TEXT], " Oth:");
++      RichString_append(out, CRT_colors[ZFS_OTHER], buffer);
++   } else {
++      RichString_write(out, CRT_colors[METER_TEXT], " ");
++      RichString_append(out, CRT_colors[FAILED_SEARCH], "Unavailable");
++   }
+ }
+ 
+ MeterClass ZfsArcMeter_class = {
+-- 
+2.20.1
+