diff options
Diffstat (limited to 'users/multi/pkgs/htop/zfs-arc-stats')
9 files changed, 2940 insertions, 0 deletions
diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0001-Specify-correct-MIB-length.patch b/users/multi/pkgs/htop/zfs-arc-stats/0001-Specify-correct-MIB-length.patch new file mode 100644 index 000000000000..5bd4d5edfa5b --- /dev/null +++ b/users/multi/pkgs/htop/zfs-arc-stats/0001-Specify-correct-MIB-length.patch @@ -0,0 +1,27 @@ +From 92258e99e639795f4119a86a1c44d5015b29ffdc Mon Sep 17 00:00:00 2001 +From: Ross Williams <ross@ross-williams.net> +Date: Sat, 6 Jul 2019 04:27:00 +0000 +Subject: [PATCH 1/9] Specify correct MIB length + +Could have resulted in a buffer overflow if the +FreeBSD kernel returned more bytes than expected. +--- + freebsd/FreeBSDProcessList.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c +index 9fef324..26019b6 100644 +--- a/freebsd/FreeBSDProcessList.c ++++ b/freebsd/FreeBSDProcessList.c +@@ -121,7 +121,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui + len = sizeof(fpl->memZfsArc); + if (sysctlbyname("kstat.zfs.misc.arcstats.size", &fpl->memZfsArc, &len, + NULL, 0) == 0 && fpl->memZfsArc != 0) { +- sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); ++ len = 5; sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); + fpl->zfsArcEnabled = 1; + } else { + fpl->zfsArcEnabled = 0; +-- +2.20.1 + diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0002-Support-ZFS-ARC-stats-on-FreeBSD.patch b/users/multi/pkgs/htop/zfs-arc-stats/0002-Support-ZFS-ARC-stats-on-FreeBSD.patch new file mode 100644 index 000000000000..0bc362adeeb0 --- /dev/null +++ b/users/multi/pkgs/htop/zfs-arc-stats/0002-Support-ZFS-ARC-stats-on-FreeBSD.patch @@ -0,0 +1,438 @@ +From a93edde1a21e533472b5d443002032260b5bd066 Mon Sep 17 00:00:00 2001 +From: Ross Williams <ross@ross-williams.net> +Date: Sat, 6 Jul 2019 04:27:49 +0000 +Subject: [PATCH 2/9] Support ZFS ARC stats on FreeBSD + +New meter displays same ARC stats as FreeBSD top(1). +Can be extended to other platforms that support ZFS. + +Pulling kstat.zfs.misc.arcstats.c_max as the meter +total, so the meter has a meaningful value to work +up to. + +The Text meter displays, first, the maximum +ARC size (Meter.total), then second, the total +ARC used, using the difference between Meter.maxItems +and Meter.curItems to "hide" the used value from the +Bar and Graph drawing functions by using an index +in Meter.values[] that is beyond curItems - 1, but +less than maxItems - 1. +--- + CRT.c | 35 ++++++++++++++++ + CRT.h | 5 +++ + Makefile.am | 10 ++++- + freebsd/FreeBSDProcessList.c | 48 ++++++++++++++++++++- + freebsd/FreeBSDProcessList.h | 6 +++ + freebsd/Platform.c | 19 +++++++++ + freebsd/Platform.h | 2 + + zfs/ZfsArcMeter.c | 81 ++++++++++++++++++++++++++++++++++++ + zfs/ZfsArcMeter.h | 18 ++++++++ + 9 files changed, 220 insertions(+), 4 deletions(-) + create mode 100644 zfs/ZfsArcMeter.c + create mode 100644 zfs/ZfsArcMeter.h + +diff --git a/CRT.c b/CRT.c +index ca9a10d..b9017aa 100644 +--- a/CRT.c ++++ b/CRT.c +@@ -128,6 +128,11 @@ typedef enum ColorElements_ { + CPU_SOFTIRQ, + CPU_STEAL, + CPU_GUEST, ++ ZFS_MFU, ++ ZFS_MRU, ++ ZFS_ANON, ++ ZFS_HEADER, ++ ZFS_OTHER, + LAST_COLORELEMENT + } ColorElements; + +@@ -232,6 +237,11 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [CPU_SOFTIRQ] = ColorPair(Magenta,Black), + [CPU_STEAL] = ColorPair(Cyan,Black), + [CPU_GUEST] = ColorPair(Cyan,Black), ++ [ZFS_MFU] = ColorPair(Blue,Black), ++ [ZFS_MRU] = ColorPair(Yellow,Black), ++ [ZFS_ANON] = ColorPair(Magenta,Black), ++ [ZFS_HEADER] = ColorPair(Cyan,Black), ++ [ZFS_OTHER] = ColorPair(Magenta,Black), + }, + [COLORSCHEME_MONOCHROME] = { + [RESET_COLOR] = A_NORMAL, +@@ -291,6 +301,11 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [CPU_SOFTIRQ] = A_BOLD, + [CPU_STEAL] = A_REVERSE, + [CPU_GUEST] = A_REVERSE, ++ [ZFS_MFU] = A_NORMAL, ++ [ZFS_MRU] = A_NORMAL, ++ [ZFS_ANON] = A_DIM, ++ [ZFS_HEADER] = A_BOLD, ++ [ZFS_OTHER] = A_DIM, + }, + [COLORSCHEME_BLACKONWHITE] = { + [RESET_COLOR] = ColorPair(Black,White), +@@ -350,6 +365,11 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [CPU_SOFTIRQ] = ColorPair(Blue,White), + [CPU_STEAL] = ColorPair(Cyan,White), + [CPU_GUEST] = ColorPair(Cyan,White), ++ [ZFS_MFU] = ColorPair(Cyan,White), ++ [ZFS_MRU] = ColorPair(Yellow,White), ++ [ZFS_ANON] = ColorPair(Magenta,White), ++ [ZFS_HEADER] = ColorPair(Yellow,White), ++ [ZFS_OTHER] = ColorPair(Magenta,White), + }, + [COLORSCHEME_LIGHTTERMINAL] = { + [RESET_COLOR] = ColorPair(Black,Black), +@@ -409,6 +429,11 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [CPU_SOFTIRQ] = ColorPair(Blue,Black), + [CPU_STEAL] = ColorPair(Black,Black), + [CPU_GUEST] = ColorPair(Black,Black), ++ [ZFS_MFU] = ColorPair(Cyan,Black), ++ [ZFS_MRU] = ColorPair(Yellow,Black), ++ [ZFS_ANON] = A_BOLD | ColorPair(Magenta,Black), ++ [ZFS_HEADER] = ColorPair(Black,Black), ++ [ZFS_OTHER] = A_BOLD | ColorPair(Magenta,Black), + }, + [COLORSCHEME_MIDNIGHT] = { + [RESET_COLOR] = ColorPair(White,Blue), +@@ -468,6 +493,11 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [CPU_SOFTIRQ] = ColorPair(Black,Blue), + [CPU_STEAL] = ColorPair(White,Blue), + [CPU_GUEST] = ColorPair(White,Blue), ++ [ZFS_MFU] = A_BOLD | ColorPair(White,Blue), ++ [ZFS_MRU] = A_BOLD | ColorPair(Yellow,Blue), ++ [ZFS_ANON] = A_BOLD | ColorPair(Magenta,Blue), ++ [ZFS_HEADER] = A_BOLD | ColorPair(Yellow,Blue), ++ [ZFS_OTHER] = A_BOLD | ColorPair(Magenta,Blue), + }, + [COLORSCHEME_BLACKNIGHT] = { + [RESET_COLOR] = ColorPair(Cyan,Black), +@@ -527,6 +557,11 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [CPU_SOFTIRQ] = ColorPair(Blue,Black), + [CPU_STEAL] = ColorPair(Cyan,Black), + [CPU_GUEST] = ColorPair(Cyan,Black), ++ [ZFS_MFU] = ColorPair(Blue,Black), ++ [ZFS_MRU] = ColorPair(Yellow,Black), ++ [ZFS_ANON] = ColorPair(Magenta,Black), ++ [ZFS_HEADER] = ColorPair(Yellow,Black), ++ [ZFS_OTHER] = ColorPair(Magenta,Black), + }, + [COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated. + }; +diff --git a/CRT.h b/CRT.h +index 933fe06..2275349 100644 +--- a/CRT.h ++++ b/CRT.h +@@ -116,6 +116,11 @@ typedef enum ColorElements_ { + CPU_SOFTIRQ, + CPU_STEAL, + CPU_GUEST, ++ ZFS_MFU, ++ ZFS_MRU, ++ ZFS_ANON, ++ ZFS_HEADER, ++ ZFS_OTHER, + LAST_COLORELEMENT + } ColorElements; + +diff --git a/Makefile.am b/Makefile.am +index 7d19600..ad23d19 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -36,6 +36,10 @@ TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \ + AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \ + EnvScreen.h InfoScreen.h XAlloc.h + ++zfs_platform_sources = zfs/ZfsArcMeter.c ++ ++zfs_platform_headers = zfs/ZfsArcMeter.h ++ + all_platform_headers = + + # Linux +@@ -68,13 +72,15 @@ freebsd_platform_headers = \ + freebsd/FreeBSDProcessList.h \ + freebsd/FreeBSDProcess.h \ + freebsd/FreeBSDCRT.h \ +- freebsd/Battery.h ++ freebsd/Battery.h \ ++ $(zfs_platform_headers) + + all_platform_headers += $(freebsd_platform_headers) + + if HTOP_FREEBSD + myhtopplatsources = freebsd/Platform.c freebsd/FreeBSDProcessList.c \ +-freebsd/FreeBSDProcess.c freebsd/FreeBSDCRT.c freebsd/Battery.c ++freebsd/FreeBSDProcess.c freebsd/FreeBSDCRT.c freebsd/Battery.c \ ++$(zfs_platform_sources) + + myhtopplatheaders = $(freebsd_platform_headers) + endif +diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c +index 26019b6..94cbaa1 100644 +--- a/freebsd/FreeBSDProcessList.c ++++ b/freebsd/FreeBSDProcessList.c +@@ -53,6 +53,12 @@ typedef struct FreeBSDProcessList_ { + unsigned long long int memFree; + 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; + + CPUData* cpus; + +@@ -81,6 +87,12 @@ static int MIB_vm_stats_vm_v_free_count[4]; + static int MIB_vfs_bufspace[2]; + + static int MIB_kstat_zfs_misc_arcstats_size[5]; ++static int MIB_vfs_zfs_arc_max[3]; ++static int MIB_kstat_zfs_misc_arcstats_mfu_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_mru_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_anon_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_hdr_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_other_size[5]; + + static int MIB_kern_cp_time[2]; + static int MIB_kern_cp_times[2]; +@@ -123,6 +135,16 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui + NULL, 0) == 0 && fpl->memZfsArc != 0) { + len = 5; sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); + fpl->zfsArcEnabled = 1; ++ ++ len = 3; ++ sysctlnametomib("vfs.zfs.arc_max", MIB_vfs_zfs_arc_max, &len); ++ ++ len = 5; ++ sysctlnametomib("kstat.zfs.misc.arcstats.mfu_size", MIB_kstat_zfs_misc_arcstats_mfu_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.mru_size", MIB_kstat_zfs_misc_arcstats_mru_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); + } else { + fpl->zfsArcEnabled = 0; + } +@@ -323,8 +345,30 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { + fpl->memZfsArc /= 1024; + fpl->memWire -= fpl->memZfsArc; + pl->cachedMem += fpl->memZfsArc; +- // maybe when we learn how to make custom memory meter +- // we could do custom arc breakdown? ++ ++ len = sizeof(fpl->zfsArcMax); ++ sysctl(MIB_vfs_zfs_arc_max, 3, &(fpl->zfsArcMax), &len , NULL, 0); ++ fpl->zfsArcMax /= 1024; ++ ++ len = sizeof(fpl->zfsArcMFU); ++ sysctl(MIB_kstat_zfs_misc_arcstats_mfu_size, 5, &(fpl->zfsArcMFU), &len , NULL, 0); ++ fpl->zfsArcMFU /= 1024; ++ ++ len = sizeof(fpl->zfsArcMRU); ++ sysctl(MIB_kstat_zfs_misc_arcstats_mru_size, 5, &(fpl->zfsArcMRU), &len , NULL, 0); ++ fpl->zfsArcMRU /= 1024; ++ ++ len = sizeof(fpl->zfsArcAnon); ++ sysctl(MIB_kstat_zfs_misc_arcstats_anon_size, 5, &(fpl->zfsArcAnon), &len , NULL, 0); ++ fpl->zfsArcAnon /= 1024; ++ ++ len = sizeof(fpl->zfsArcHeader); ++ sysctl(MIB_kstat_zfs_misc_arcstats_hdr_size, 5, &(fpl->zfsArcHeader), &len , NULL, 0); ++ fpl->zfsArcHeader /= 1024; ++ ++ len = sizeof(fpl->zfsArcOther); ++ sysctl(MIB_kstat_zfs_misc_arcstats_other_size, 5, &(fpl->zfsArcOther), &len , NULL, 0); ++ fpl->zfsArcOther /= 1024; + } + + pl->usedMem = fpl->memActive + fpl->memWire; +diff --git a/freebsd/FreeBSDProcessList.h b/freebsd/FreeBSDProcessList.h +index af343fb..cf96a70 100644 +--- a/freebsd/FreeBSDProcessList.h ++++ b/freebsd/FreeBSDProcessList.h +@@ -42,6 +42,12 @@ typedef struct FreeBSDProcessList_ { + unsigned long long int memFree; + 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; + + CPUData* cpus; + +diff --git a/freebsd/Platform.c b/freebsd/Platform.c +index 5dd6ca4..d8d2ed0 100644 +--- a/freebsd/Platform.c ++++ b/freebsd/Platform.c +@@ -15,6 +15,7 @@ in the source distribution for its full text. + #include "UptimeMeter.h" + #include "ClockMeter.h" + #include "HostnameMeter.h" ++#include "zfs/ZfsArcMeter.h" + #include "FreeBSDProcess.h" + #include "FreeBSDProcessList.h" + +@@ -104,6 +105,7 @@ MeterClass* Platform_meterTypes[] = { + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &BlankMeter_class, ++ &ZfsArcMeter_class, + NULL + }; + +@@ -197,6 +199,23 @@ void Platform_setSwapValues(Meter* this) { + this->values[0] = pl->usedSwap; + } + ++void Platform_setZfsArcValues(Meter* this) { ++ FreeBSDProcessList* fpl = (FreeBSDProcessList*) this->pl; ++ ++ this->total = fpl->zfsArcMax; ++ this->values[0] = fpl->zfsArcMFU; ++ this->values[1] = fpl->zfsArcMRU; ++ this->values[2] = fpl->zfsArcAnon; ++ this->values[3] = fpl->zfsArcHeader; ++ this->values[4] = fpl->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] = fpl->memZfsArc; ++} ++ + void Platform_setTasksValues(Meter* this) { + // TODO + } +diff --git a/freebsd/Platform.h b/freebsd/Platform.h +index 1735e7e..3dc7ebf 100644 +--- a/freebsd/Platform.h ++++ b/freebsd/Platform.h +@@ -44,6 +44,8 @@ void Platform_setMemoryValues(Meter* this); + + void Platform_setSwapValues(Meter* this); + ++void Platform_setZfsArcValues(Meter* this); ++ + void Platform_setTasksValues(Meter* this); + + char* Platform_getProcessEnv(pid_t pid); +diff --git a/zfs/ZfsArcMeter.c b/zfs/ZfsArcMeter.c +new file mode 100644 +index 0000000..e12c46e +--- /dev/null ++++ b/zfs/ZfsArcMeter.c +@@ -0,0 +1,81 @@ ++/* ++htop - ZfsArcMeter.c ++(C) 2004-2011 Hisham H. Muhammad ++Released under the GNU GPL, see the COPYING file ++in the source distribution for its full text. ++*/ ++ ++#include "ZfsArcMeter.h" ++ ++#include "CRT.h" ++#include "Platform.h" ++ ++#include <stdlib.h> ++#include <string.h> ++#include <math.h> ++#include <sys/param.h> ++#include <assert.h> ++ ++/*{ ++#include "Meter.h" ++}*/ ++ ++int ZfsArcMeter_attributes[] = { ++ ZFS_MFU, ZFS_MRU, ZFS_ANON, ZFS_HEADER, ZFS_OTHER ++}; ++ ++static void ZfsArcMeter_updateValues(Meter* this, char* buffer, int size) { ++ int written; ++ Platform_setZfsArcValues(this); ++ ++ written = Meter_humanUnit(buffer, this->values[5], size); ++ buffer += written; ++ if ((size -= written) > 0) { ++ *buffer++ = '/'; ++ size--; ++ Meter_humanUnit(buffer, this->total, size); ++ } ++} ++ ++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); ++} ++ ++MeterClass ZfsArcMeter_class = { ++ .super = { ++ .extends = Class(Meter), ++ .delete = Meter_delete, ++ .display = ZfsArcMeter_display, ++ }, ++ .updateValues = ZfsArcMeter_updateValues, ++ .defaultMode = TEXT_METERMODE, ++ .maxItems = 6, ++ .total = 100.0, ++ .attributes = ZfsArcMeter_attributes, ++ .name = "ZFSARC", ++ .uiName = "ZFS ARC", ++ .caption = "ARC" ++}; +diff --git a/zfs/ZfsArcMeter.h b/zfs/ZfsArcMeter.h +new file mode 100644 +index 0000000..b89be22 +--- /dev/null ++++ b/zfs/ZfsArcMeter.h +@@ -0,0 +1,18 @@ ++/* Do not edit this file. It was automatically generated. */ ++ ++#ifndef HEADER_ZfsArcMeter ++#define HEADER_ZfsArcMeter ++/* ++htop - ZfsArcMeter.h ++(C) 2004-2011 Hisham H. Muhammad ++Released under the GNU GPL, see the COPYING file ++in the source distribution for its full text. ++*/ ++ ++#include "Meter.h" ++ ++extern int ZfsArcMeter_attributes[]; ++ ++extern MeterClass ZfsArcMeter_class; ++ ++#endif +-- +2.20.1 + 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 000000000000..f232f5e87db2 --- /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 + diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0004-ZFS-arcstats-for-Darwin-macOS-OS-X.patch b/users/multi/pkgs/htop/zfs-arc-stats/0004-ZFS-arcstats-for-Darwin-macOS-OS-X.patch new file mode 100644 index 000000000000..9dbc365ebeae --- /dev/null +++ b/users/multi/pkgs/htop/zfs-arc-stats/0004-ZFS-arcstats-for-Darwin-macOS-OS-X.patch @@ -0,0 +1,260 @@ +From fc8e9a2d3e25e35c0f9903baa345b1744b12b6cb Mon Sep 17 00:00:00 2001 +From: Ross Williams <ross@ross-williams.net> +Date: Sun, 7 Jul 2019 17:30:37 -0400 +Subject: [PATCH 4/9] ZFS arcstats for Darwin (macOS / OS X) + +--- + Makefile.am | 6 ++- + darwin/DarwinProcessList.c | 80 ++++++++++++++++++++++++++++++++++++++ + darwin/DarwinProcessList.h | 21 ++++++++++ + darwin/Platform.c | 19 +++++++++ + darwin/Platform.h | 2 + + 5 files changed, 126 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index b850815..b6d2117 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -134,14 +134,16 @@ darwin_platform_headers = \ + darwin/DarwinProcess.h \ + darwin/DarwinProcessList.h \ + darwin/DarwinCRT.h \ +- darwin/Battery.h ++ darwin/Battery.h \ ++ $(zfs_platform_headers) + + all_platform_headers += $(darwin_platform_headers) + + if HTOP_DARWIN + AM_LDFLAGS += -framework IOKit -framework CoreFoundation + myhtopplatsources = darwin/Platform.c darwin/DarwinProcess.c \ +-darwin/DarwinProcessList.c darwin/DarwinCRT.c darwin/Battery.c ++darwin/DarwinProcessList.c darwin/DarwinCRT.c darwin/Battery.c \ ++$(zfs_platform_sources) + + myhtopplatheaders = $(darwin_platform_headers) + endif +diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c +index 0988448..267e8e9 100644 +--- a/darwin/DarwinProcessList.c ++++ b/darwin/DarwinProcessList.c +@@ -54,6 +54,7 @@ int CompareKernelVersion(short int major, short int minor, short int component) + + /*{ + #include "ProcessList.h" ++#include "zfs/ZfsArcStats.h" + #include <mach/mach_host.h> + #include <sys/sysctl.h> + +@@ -67,10 +68,28 @@ typedef struct DarwinProcessList_ { + uint64_t kernel_threads; + uint64_t user_threads; + uint64_t global_diff; ++ ++ int zfsArcEnabled; ++ unsigned long long int zfsArcMax; ++ unsigned long long int zfsArcSize; ++ 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; ++ + } DarwinProcessList; + + }*/ + ++static int MIB_kstat_zfs_misc_arcstats_c_max[5]; ++static int MIB_kstat_zfs_misc_arcstats_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_mfu_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_mru_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_anon_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_hdr_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_other_size[5]; ++ + void ProcessList_getHostInfo(host_basic_info_data_t *p) { + mach_msg_type_number_t info_size = HOST_BASIC_INFO_COUNT; + +@@ -131,8 +150,50 @@ struct kinfo_proc *ProcessList_getKInfoProcs(size_t *count) { + return processes; + } + ++static inline void DarwinProcessList_scanZfsArcstats(DarwinProcessList* dpl) { ++ size_t len; ++ ++ if (dpl->zfsArcEnabled) { ++ len = sizeof(dpl->zfsArcSize); ++ sysctl(MIB_kstat_zfs_misc_arcstats_size, 5, &(dpl->zfsArcSize), &len , NULL, 0); ++ /* TODO: adjust reported memory in use to move ARC from wired to inactive ++ Like: ++ // In bytes ++ dpl->vm_stats.wire_count -= dpl->zfsArcSize / vm_page_size; ++ dpl->vm_stats.inactive_count += dpl->zfsArcSize / vm_page_size; ++ // Would purgable_count be more true? ++ // Then convert to KB: ++ */ ++ dpl->zfsArcSize /= 1024; ++ ++ len = sizeof(dpl->zfsArcMax); ++ sysctl(MIB_kstat_zfs_misc_arcstats_c_max, 5, &(dpl->zfsArcMax), &len , NULL, 0); ++ dpl->zfsArcMax /= 1024; ++ ++ len = sizeof(dpl->zfsArcMFU); ++ sysctl(MIB_kstat_zfs_misc_arcstats_mfu_size, 5, &(dpl->zfsArcMFU), &len , NULL, 0); ++ dpl->zfsArcMFU /= 1024; ++ ++ len = sizeof(dpl->zfsArcMRU); ++ sysctl(MIB_kstat_zfs_misc_arcstats_mru_size, 5, &(dpl->zfsArcMRU), &len , NULL, 0); ++ dpl->zfsArcMRU /= 1024; ++ ++ len = sizeof(dpl->zfsArcAnon); ++ sysctl(MIB_kstat_zfs_misc_arcstats_anon_size, 5, &(dpl->zfsArcAnon), &len , NULL, 0); ++ dpl->zfsArcAnon /= 1024; ++ ++ len = sizeof(dpl->zfsArcHeader); ++ sysctl(MIB_kstat_zfs_misc_arcstats_hdr_size, 5, &(dpl->zfsArcHeader), &len , NULL, 0); ++ dpl->zfsArcHeader /= 1024; ++ ++ len = sizeof(dpl->zfsArcOther); ++ sysctl(MIB_kstat_zfs_misc_arcstats_other_size, 5, &(dpl->zfsArcOther), &len , NULL, 0); ++ dpl->zfsArcOther /= 1024; ++ } ++} + + ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { ++ size_t len; + DarwinProcessList* this = xCalloc(1, sizeof(DarwinProcessList)); + + ProcessList_init(&this->super, Class(Process), usersTable, pidWhiteList, userId); +@@ -145,6 +206,24 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui + /* Initialize the VM statistics */ + ProcessList_getVMStats(&this->vm_stats); + ++ /* Initialize the ZFS kstats, if zfs.kext loaded */ ++ len = sizeof(this->zfsArcSize); ++ if (sysctlbyname("kstat.zfs.misc.arcstats.size", &this->zfsArcSize, &len, ++ NULL, 0) == 0 && this->zfsArcSize != 0) { ++ this->zfsArcEnabled = 1; ++ ++ len = 5; ++ sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.c_max", MIB_kstat_zfs_misc_arcstats_c_max, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.mfu_size", MIB_kstat_zfs_misc_arcstats_mfu_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.mru_size", MIB_kstat_zfs_misc_arcstats_mru_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); ++ } else { ++ this->zfsArcEnabled = 0; ++ } ++ + this->super.kernelThreads = 0; + this->super.userlandThreads = 0; + this->super.totalTasks = 0; +@@ -173,6 +252,7 @@ void ProcessList_goThroughEntries(ProcessList* super) { + dpl->prev_load = dpl->curr_load; + ProcessList_allocateCPULoadInfo(&dpl->curr_load); + ProcessList_getVMStats(&dpl->vm_stats); ++ DarwinProcessList_scanZfsArcstats(dpl); + + /* Get the time difference */ + dpl->global_diff = 0; +diff --git a/darwin/DarwinProcessList.h b/darwin/DarwinProcessList.h +index c216a80..6686d05 100644 +--- a/darwin/DarwinProcessList.h ++++ b/darwin/DarwinProcessList.h +@@ -9,6 +9,17 @@ Released under the GNU GPL, see the COPYING file + in the source distribution for its full text. + */ + ++struct kern; ++ ++void GetKernelVersion(struct kern *k); ++ ++/* compare the given os version with the one installed returns: ++0 if equals the installed version ++positive value if less than the installed version ++negative value if more than the installed version ++*/ ++int CompareKernelVersion(short int major, short int minor, short int component); ++ + #include "ProcessList.h" + #include <mach/mach_host.h> + #include <sys/sysctl.h> +@@ -23,6 +34,16 @@ typedef struct DarwinProcessList_ { + uint64_t kernel_threads; + uint64_t user_threads; + uint64_t global_diff; ++ ++ int zfsArcEnabled; ++ unsigned long long int zfsArcMax; ++ unsigned long long int zfsArcSize; ++ 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; ++ + } DarwinProcessList; + + +diff --git a/darwin/Platform.c b/darwin/Platform.c +index 1dce8b6..52d60a9 100644 +--- a/darwin/Platform.c ++++ b/darwin/Platform.c +@@ -15,6 +15,7 @@ in the source distribution for its full text. + #include "ClockMeter.h" + #include "HostnameMeter.h" + #include "UptimeMeter.h" ++#include "zfs/ZfsArcMeter.h" + #include "DarwinProcessList.h" + + #include <stdlib.h> +@@ -117,6 +118,7 @@ MeterClass* Platform_meterTypes[] = { + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, ++ &ZfsArcMeter_class, + &BlankMeter_class, + NULL + }; +@@ -241,6 +243,23 @@ void Platform_setSwapValues(Meter* mtr) { + mtr->values[0] = swapused.xsu_used / 1024; + } + ++void Platform_setZfsArcValues(Meter* this) { ++ DarwinProcessList* dpl = (DarwinProcessList*) this->pl; ++ ++ this->total = dpl->zfsArcMax; ++ this->values[0] = dpl->zfsArcMFU; ++ this->values[1] = dpl->zfsArcMRU; ++ this->values[2] = dpl->zfsArcAnon; ++ this->values[3] = dpl->zfsArcHeader; ++ this->values[4] = dpl->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] = dpl->zfsArcSize; ++} ++ + char* Platform_getProcessEnv(pid_t pid) { + char* env = NULL; + +diff --git a/darwin/Platform.h b/darwin/Platform.h +index 1231217..4acda2c 100644 +--- a/darwin/Platform.h ++++ b/darwin/Platform.h +@@ -48,6 +48,8 @@ void Platform_setMemoryValues(Meter* mtr); + + void Platform_setSwapValues(Meter* mtr); + ++void Platform_setZfsArcValues(Meter* mtr); ++ + char* Platform_getProcessEnv(pid_t pid); + + #endif +-- +2.20.1 + diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0005-Refactor-common-OpenZFS-sysctl-access.patch b/users/multi/pkgs/htop/zfs-arc-stats/0005-Refactor-common-OpenZFS-sysctl-access.patch new file mode 100644 index 000000000000..de81b1ceb647 --- /dev/null +++ b/users/multi/pkgs/htop/zfs-arc-stats/0005-Refactor-common-OpenZFS-sysctl-access.patch @@ -0,0 +1,817 @@ +From a88d2e313df7f5f2b781d5b14ffe0e7710018c10 Mon Sep 17 00:00:00 2001 +From: Ross Williams <ross@ross-williams.net> +Date: Sun, 7 Jul 2019 23:27:00 +0000 +Subject: [PATCH 5/9] Refactor common OpenZFS sysctl access + +Darwin and FreeBSD export zfs kstats through the +same APIs, so moving functions into a common file. +--- + Makefile.am | 21 ++++----- + darwin/DarwinProcessList.c | 82 +++--------------------------------- + darwin/DarwinProcessList.h | 11 +---- + darwin/Platform.c | 14 +++--- + darwin/Platform.h | 2 +- + freebsd/FreeBSDProcessList.c | 77 +++++---------------------------- + freebsd/FreeBSDProcessList.h | 14 ++---- + freebsd/Platform.c | 14 +++--- + linux/LinuxProcessList.c | 40 ++++++++---------- + linux/LinuxProcessList.h | 10 +---- + linux/Platform.c | 14 +++--- + zfs/ZfsArcStats.c | 19 +++++++++ + zfs/ZfsArcStats.h | 23 ++++++++++ + zfs/openzfs_sysctl.c | 81 +++++++++++++++++++++++++++++++++++ + zfs/openzfs_sysctl.h | 18 ++++++++ + 15 files changed, 216 insertions(+), 224 deletions(-) + create mode 100644 zfs/ZfsArcStats.c + create mode 100644 zfs/ZfsArcStats.h + create mode 100644 zfs/openzfs_sysctl.c + create mode 100644 zfs/openzfs_sysctl.h + +diff --git a/Makefile.am b/Makefile.am +index b6d2117..5eee631 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -36,10 +36,6 @@ TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \ + AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \ + EnvScreen.h InfoScreen.h XAlloc.h + +-zfs_platform_sources = zfs/ZfsArcMeter.c +- +-zfs_platform_headers = zfs/ZfsArcMeter.h +- + all_platform_headers = + + # Linux +@@ -53,7 +49,8 @@ linux_platform_headers = \ + linux/LinuxProcessList.h \ + linux/LinuxCRT.h \ + linux/Battery.h \ +- $(zfs_platform_headers) ++ zfs/ZfsArcMeter.h \ ++ zfs/ZfsArcStats.h + + all_platform_headers += $(linux_platform_headers) + +@@ -61,7 +58,7 @@ 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 \ +-$(zfs_platform_sources) ++zfs/ZfsArcMeter.c zfs/ZfsArcStats.c + + myhtopplatheaders = $(linux_platform_headers) + endif +@@ -75,14 +72,16 @@ freebsd_platform_headers = \ + freebsd/FreeBSDProcess.h \ + freebsd/FreeBSDCRT.h \ + freebsd/Battery.h \ +- $(zfs_platform_headers) ++ zfs/ZfsArcMeter.h \ ++ zfs/ZfsArcStats.h \ ++ zfs/openzfs_sysctl.h + + all_platform_headers += $(freebsd_platform_headers) + + if HTOP_FREEBSD + myhtopplatsources = freebsd/Platform.c freebsd/FreeBSDProcessList.c \ + freebsd/FreeBSDProcess.c freebsd/FreeBSDCRT.c freebsd/Battery.c \ +-$(zfs_platform_sources) ++zfs/ZfsArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c + + myhtopplatheaders = $(freebsd_platform_headers) + endif +@@ -135,7 +134,9 @@ darwin_platform_headers = \ + darwin/DarwinProcessList.h \ + darwin/DarwinCRT.h \ + darwin/Battery.h \ +- $(zfs_platform_headers) ++ zfs/ZfsArcMeter.h \ ++ zfs/ZfsArcStats.h \ ++ zfs/openzfs_sysctl.h + + all_platform_headers += $(darwin_platform_headers) + +@@ -143,7 +144,7 @@ if HTOP_DARWIN + AM_LDFLAGS += -framework IOKit -framework CoreFoundation + myhtopplatsources = darwin/Platform.c darwin/DarwinProcess.c \ + darwin/DarwinProcessList.c darwin/DarwinCRT.c darwin/Battery.c \ +-$(zfs_platform_sources) ++zfs/ZfsArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c + + myhtopplatheaders = $(darwin_platform_headers) + endif +diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c +index 267e8e9..122e018 100644 +--- a/darwin/DarwinProcessList.c ++++ b/darwin/DarwinProcessList.c +@@ -9,6 +9,8 @@ in the source distribution for its full text. + #include "DarwinProcess.h" + #include "DarwinProcessList.h" + #include "CRT.h" ++#include "zfs/ZfsArcStats.h" ++#include "zfs/openzfs_sysctl.h" + + #include <stdlib.h> + #include <string.h> +@@ -69,27 +71,11 @@ typedef struct DarwinProcessList_ { + uint64_t user_threads; + uint64_t global_diff; + +- int zfsArcEnabled; +- unsigned long long int zfsArcMax; +- unsigned long long int zfsArcSize; +- 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; +- ++ ZfsArcStats zfs; + } DarwinProcessList; + + }*/ + +-static int MIB_kstat_zfs_misc_arcstats_c_max[5]; +-static int MIB_kstat_zfs_misc_arcstats_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_mfu_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_mru_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_anon_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_hdr_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_other_size[5]; +- + void ProcessList_getHostInfo(host_basic_info_data_t *p) { + mach_msg_type_number_t info_size = HOST_BASIC_INFO_COUNT; + +@@ -150,48 +136,6 @@ struct kinfo_proc *ProcessList_getKInfoProcs(size_t *count) { + return processes; + } + +-static inline void DarwinProcessList_scanZfsArcstats(DarwinProcessList* dpl) { +- size_t len; +- +- if (dpl->zfsArcEnabled) { +- len = sizeof(dpl->zfsArcSize); +- sysctl(MIB_kstat_zfs_misc_arcstats_size, 5, &(dpl->zfsArcSize), &len , NULL, 0); +- /* TODO: adjust reported memory in use to move ARC from wired to inactive +- Like: +- // In bytes +- dpl->vm_stats.wire_count -= dpl->zfsArcSize / vm_page_size; +- dpl->vm_stats.inactive_count += dpl->zfsArcSize / vm_page_size; +- // Would purgable_count be more true? +- // Then convert to KB: +- */ +- dpl->zfsArcSize /= 1024; +- +- len = sizeof(dpl->zfsArcMax); +- sysctl(MIB_kstat_zfs_misc_arcstats_c_max, 5, &(dpl->zfsArcMax), &len , NULL, 0); +- dpl->zfsArcMax /= 1024; +- +- len = sizeof(dpl->zfsArcMFU); +- sysctl(MIB_kstat_zfs_misc_arcstats_mfu_size, 5, &(dpl->zfsArcMFU), &len , NULL, 0); +- dpl->zfsArcMFU /= 1024; +- +- len = sizeof(dpl->zfsArcMRU); +- sysctl(MIB_kstat_zfs_misc_arcstats_mru_size, 5, &(dpl->zfsArcMRU), &len , NULL, 0); +- dpl->zfsArcMRU /= 1024; +- +- len = sizeof(dpl->zfsArcAnon); +- sysctl(MIB_kstat_zfs_misc_arcstats_anon_size, 5, &(dpl->zfsArcAnon), &len , NULL, 0); +- dpl->zfsArcAnon /= 1024; +- +- len = sizeof(dpl->zfsArcHeader); +- sysctl(MIB_kstat_zfs_misc_arcstats_hdr_size, 5, &(dpl->zfsArcHeader), &len , NULL, 0); +- dpl->zfsArcHeader /= 1024; +- +- len = sizeof(dpl->zfsArcOther); +- sysctl(MIB_kstat_zfs_misc_arcstats_other_size, 5, &(dpl->zfsArcOther), &len , NULL, 0); +- dpl->zfsArcOther /= 1024; +- } +-} +- + ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { + size_t len; + DarwinProcessList* this = xCalloc(1, sizeof(DarwinProcessList)); +@@ -207,22 +151,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui + ProcessList_getVMStats(&this->vm_stats); + + /* Initialize the ZFS kstats, if zfs.kext loaded */ +- len = sizeof(this->zfsArcSize); +- if (sysctlbyname("kstat.zfs.misc.arcstats.size", &this->zfsArcSize, &len, +- NULL, 0) == 0 && this->zfsArcSize != 0) { +- this->zfsArcEnabled = 1; +- +- len = 5; +- sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.c_max", MIB_kstat_zfs_misc_arcstats_c_max, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.mfu_size", MIB_kstat_zfs_misc_arcstats_mfu_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.mru_size", MIB_kstat_zfs_misc_arcstats_mru_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); +- } else { +- this->zfsArcEnabled = 0; +- } ++ this->zfs.enabled = openzfs_sysctl_init(); ++ openzfs_sysctl_updateArcStats(&this->zfs); + + this->super.kernelThreads = 0; + this->super.userlandThreads = 0; +@@ -252,7 +182,7 @@ void ProcessList_goThroughEntries(ProcessList* super) { + dpl->prev_load = dpl->curr_load; + ProcessList_allocateCPULoadInfo(&dpl->curr_load); + ProcessList_getVMStats(&dpl->vm_stats); +- DarwinProcessList_scanZfsArcstats(dpl); ++ openzfs_sysctl_updateArcStats(&dpl->zfs); + + /* Get the time difference */ + dpl->global_diff = 0; +diff --git a/darwin/DarwinProcessList.h b/darwin/DarwinProcessList.h +index 6686d05..73fbd34 100644 +--- a/darwin/DarwinProcessList.h ++++ b/darwin/DarwinProcessList.h +@@ -21,6 +21,7 @@ negative value if more than the installed version + int CompareKernelVersion(short int major, short int minor, short int component); + + #include "ProcessList.h" ++#include "zfs/ZfsArcStats.h" + #include <mach/mach_host.h> + #include <sys/sysctl.h> + +@@ -35,15 +36,7 @@ typedef struct DarwinProcessList_ { + uint64_t user_threads; + uint64_t global_diff; + +- int zfsArcEnabled; +- unsigned long long int zfsArcMax; +- unsigned long long int zfsArcSize; +- 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; +- ++ ZfsArcStats zfs; + } DarwinProcessList; + + +diff --git a/darwin/Platform.c b/darwin/Platform.c +index 52d60a9..8fbb9c9 100644 +--- a/darwin/Platform.c ++++ b/darwin/Platform.c +@@ -246,18 +246,18 @@ void Platform_setSwapValues(Meter* mtr) { + void Platform_setZfsArcValues(Meter* this) { + DarwinProcessList* dpl = (DarwinProcessList*) this->pl; + +- this->total = dpl->zfsArcMax; +- this->values[0] = dpl->zfsArcMFU; +- this->values[1] = dpl->zfsArcMRU; +- this->values[2] = dpl->zfsArcAnon; +- this->values[3] = dpl->zfsArcHeader; +- this->values[4] = dpl->zfsArcOther; ++ this->total = dpl->zfs.max; ++ this->values[0] = dpl->zfs.MFU; ++ this->values[1] = dpl->zfs.MRU; ++ this->values[2] = dpl->zfs.anon; ++ this->values[3] = dpl->zfs.header; ++ this->values[4] = dpl->zfs.other; + + // "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] = dpl->zfsArcSize; ++ this->values[5] = dpl->zfs.size; + } + + char* Platform_getProcessEnv(pid_t pid) { +diff --git a/darwin/Platform.h b/darwin/Platform.h +index 4acda2c..f836077 100644 +--- a/darwin/Platform.h ++++ b/darwin/Platform.h +@@ -48,7 +48,7 @@ void Platform_setMemoryValues(Meter* mtr); + + void Platform_setSwapValues(Meter* mtr); + +-void Platform_setZfsArcValues(Meter* mtr); ++void Platform_setZfsArcValues(Meter* this); + + char* Platform_getProcessEnv(pid_t pid); + +diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c +index 94cbaa1..1cbfdaa 100644 +--- a/freebsd/FreeBSDProcessList.c ++++ b/freebsd/FreeBSDProcessList.c +@@ -8,6 +8,8 @@ in the source distribution for its full text. + #include "ProcessList.h" + #include "FreeBSDProcessList.h" + #include "FreeBSDProcess.h" ++#include "zfs/ZfsArcStats.h" ++#include "zfs/openzfs_sysctl.h" + + #include <unistd.h> + #include <stdlib.h> +@@ -21,6 +23,8 @@ in the source distribution for its full text. + + /*{ + ++#include "zfs/ZfsArcStats.h" ++ + #include <kvm.h> + #include <sys/param.h> + #include <sys/jail.h> +@@ -45,20 +49,12 @@ typedef struct FreeBSDProcessList_ { + ProcessList super; + kvm_t* kd; + +- int zfsArcEnabled; +- + unsigned long long int memWire; + unsigned long long int memActive; + unsigned long long int memInactive; + unsigned long long int memFree; +- 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; ++ ZfsArcStats zfs; + + CPUData* cpus; + +@@ -86,14 +82,6 @@ static int MIB_vm_stats_vm_v_free_count[4]; + + static int MIB_vfs_bufspace[2]; + +-static int MIB_kstat_zfs_misc_arcstats_size[5]; +-static int MIB_vfs_zfs_arc_max[3]; +-static int MIB_kstat_zfs_misc_arcstats_mfu_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_mru_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_anon_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_hdr_size[5]; +-static int MIB_kstat_zfs_misc_arcstats_other_size[5]; +- + static int MIB_kern_cp_time[2]; + static int MIB_kern_cp_times[2]; + static int kernelFScale; +@@ -130,25 +118,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui + + len = 2; sysctlnametomib("vfs.bufspace", MIB_vfs_bufspace, &len); + +- len = sizeof(fpl->memZfsArc); +- if (sysctlbyname("kstat.zfs.misc.arcstats.size", &fpl->memZfsArc, &len, +- NULL, 0) == 0 && fpl->memZfsArc != 0) { +- len = 5; sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); +- fpl->zfsArcEnabled = 1; +- +- len = 3; +- sysctlnametomib("vfs.zfs.arc_max", MIB_vfs_zfs_arc_max, &len); +- +- len = 5; +- sysctlnametomib("kstat.zfs.misc.arcstats.mfu_size", MIB_kstat_zfs_misc_arcstats_mfu_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.mru_size", MIB_kstat_zfs_misc_arcstats_mru_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); +- sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); +- } else { +- fpl->zfsArcEnabled = 0; +- } +- ++ fpl->zfs.enabled = openzfs_sysctl_init(); ++ openzfs_sysctl_updateArcStats(&fpl->zfs); + + int smp = 0; + len = sizeof(smp); +@@ -339,36 +310,9 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { + sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(pl->cachedMem), &len, NULL, 0); + pl->cachedMem *= pageSizeKb; + +- if (fpl->zfsArcEnabled) { +- len = sizeof(fpl->memZfsArc); +- sysctl(MIB_kstat_zfs_misc_arcstats_size, 5, &(fpl->memZfsArc), &len , NULL, 0); +- fpl->memZfsArc /= 1024; +- fpl->memWire -= fpl->memZfsArc; +- pl->cachedMem += fpl->memZfsArc; +- +- len = sizeof(fpl->zfsArcMax); +- sysctl(MIB_vfs_zfs_arc_max, 3, &(fpl->zfsArcMax), &len , NULL, 0); +- fpl->zfsArcMax /= 1024; +- +- len = sizeof(fpl->zfsArcMFU); +- sysctl(MIB_kstat_zfs_misc_arcstats_mfu_size, 5, &(fpl->zfsArcMFU), &len , NULL, 0); +- fpl->zfsArcMFU /= 1024; +- +- len = sizeof(fpl->zfsArcMRU); +- sysctl(MIB_kstat_zfs_misc_arcstats_mru_size, 5, &(fpl->zfsArcMRU), &len , NULL, 0); +- fpl->zfsArcMRU /= 1024; +- +- len = sizeof(fpl->zfsArcAnon); +- sysctl(MIB_kstat_zfs_misc_arcstats_anon_size, 5, &(fpl->zfsArcAnon), &len , NULL, 0); +- fpl->zfsArcAnon /= 1024; +- +- len = sizeof(fpl->zfsArcHeader); +- sysctl(MIB_kstat_zfs_misc_arcstats_hdr_size, 5, &(fpl->zfsArcHeader), &len , NULL, 0); +- fpl->zfsArcHeader /= 1024; +- +- len = sizeof(fpl->zfsArcOther); +- sysctl(MIB_kstat_zfs_misc_arcstats_other_size, 5, &(fpl->zfsArcOther), &len , NULL, 0); +- fpl->zfsArcOther /= 1024; ++ if (fpl->zfs.enabled) { ++ fpl->memWire -= fpl->zfs.size; ++ pl->cachedMem += fpl->zfs.size; + } + + pl->usedMem = fpl->memActive + fpl->memWire; +@@ -466,6 +410,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { + bool hideKernelThreads = settings->hideKernelThreads; + bool hideUserlandThreads = settings->hideUserlandThreads; + ++ openzfs_sysctl_updateArcStats(&fpl->zfs); + FreeBSDProcessList_scanMemoryInfo(this); + FreeBSDProcessList_scanCPUTime(this); + +diff --git a/freebsd/FreeBSDProcessList.h b/freebsd/FreeBSDProcessList.h +index cf96a70..7c1b7ad 100644 +--- a/freebsd/FreeBSDProcessList.h ++++ b/freebsd/FreeBSDProcessList.h +@@ -10,6 +10,8 @@ in the source distribution for its full text. + */ + + ++#include "zfs/ZfsArcStats.h" ++ + #include <kvm.h> + #include <sys/param.h> + #include <sys/jail.h> +@@ -34,20 +36,12 @@ typedef struct FreeBSDProcessList_ { + ProcessList super; + kvm_t* kd; + +- int zfsArcEnabled; +- + unsigned long long int memWire; + unsigned long long int memActive; + unsigned long long int memInactive; + unsigned long long int memFree; +- 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; ++ ++ ZfsArcStats zfs; + + CPUData* cpus; + +diff --git a/freebsd/Platform.c b/freebsd/Platform.c +index d8d2ed0..05c0e92 100644 +--- a/freebsd/Platform.c ++++ b/freebsd/Platform.c +@@ -202,18 +202,18 @@ void Platform_setSwapValues(Meter* this) { + void Platform_setZfsArcValues(Meter* this) { + FreeBSDProcessList* fpl = (FreeBSDProcessList*) this->pl; + +- this->total = fpl->zfsArcMax; +- this->values[0] = fpl->zfsArcMFU; +- this->values[1] = fpl->zfsArcMRU; +- this->values[2] = fpl->zfsArcAnon; +- this->values[3] = fpl->zfsArcHeader; +- this->values[4] = fpl->zfsArcOther; ++ this->total = fpl->zfs.max; ++ this->values[0] = fpl->zfs.MFU; ++ this->values[1] = fpl->zfs.MRU; ++ this->values[2] = fpl->zfs.anon; ++ this->values[3] = fpl->zfs.header; ++ this->values[4] = fpl->zfs.other; + + // "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] = fpl->memZfsArc; ++ this->values[5] = fpl->zfs.size; + } + + void Platform_setTasksValues(Meter* this) { +diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c +index 4d19185..3e88910 100644 +--- a/linux/LinuxProcessList.c ++++ b/linux/LinuxProcessList.c +@@ -46,6 +46,7 @@ in the source distribution for its full text. + /*{ + + #include "ProcessList.h" ++#include "zfs/ZfsArcStats.h" + + extern long long btime; + +@@ -95,14 +96,7 @@ typedef struct LinuxProcessList_ { + 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; ++ ZfsArcStats zfs; + } LinuxProcessList; + + #ifndef PROCDIR +@@ -984,7 +978,7 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) { + + FILE* file = fopen(PROCARCSTATSFILE, "r"); + if (file == NULL) { +- lpl->zfsArcEnabled = 0; ++ lpl->zfs.enabled = 0; + return; + } + char buffer[128]; +@@ -992,13 +986,13 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) { + #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); ++ tryRead("c_max", &lpl->zfs.max); + break; + case 's': +- tryRead("size", &lpl->memZfsArc); ++ tryRead("size", &lpl->zfs.size); + break; + case 'h': +- tryRead("hdr_size", &lpl->zfsArcHeader); ++ tryRead("hdr_size", &lpl->zfs.header); + break; + case 'd': + tryRead("dbuf_size", &dbufSize); +@@ -1008,25 +1002,25 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) { + tryRead("bonus_size", &bonusSize); + break; + case 'a': +- tryRead("anon_size", &lpl->zfsArcAnon); ++ tryRead("anon_size", &lpl->zfs.anon); + break; + case 'm': +- tryRead("mfu_size", &lpl->zfsArcMFU); +- tryRead("mru_size", &lpl->zfsArcMRU); ++ tryRead("mfu_size", &lpl->zfs.MFU); ++ tryRead("mru_size", &lpl->zfs.MRU); + 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; ++ lpl->zfs.enabled = (lpl->zfs.size > 0 ? 1 : 0); ++ lpl->zfs.size /= 1024; ++ lpl->zfs.max /= 1024; ++ lpl->zfs.MFU /= 1024; ++ lpl->zfs.MRU /= 1024; ++ lpl->zfs.anon /= 1024; ++ lpl->zfs.header /= 1024; ++ lpl->zfs.other = (dbufSize + dnodeSize + bonusSize) / 1024; + } + + static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) { +diff --git a/linux/LinuxProcessList.h b/linux/LinuxProcessList.h +index 749231e..353fe60 100644 +--- a/linux/LinuxProcessList.h ++++ b/linux/LinuxProcessList.h +@@ -19,6 +19,7 @@ in the source distribution for its full text. + + + #include "ProcessList.h" ++#include "zfs/ZfsArcStats.h" + + extern long long btime; + +@@ -68,14 +69,7 @@ typedef struct LinuxProcessList_ { + 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; ++ ZfsArcStats zfs; + } LinuxProcessList; + + #ifndef PROCDIR +diff --git a/linux/Platform.c b/linux/Platform.c +index 4e73c61..e2a3c6d 100644 +--- a/linux/Platform.c ++++ b/linux/Platform.c +@@ -218,18 +218,18 @@ void Platform_setSwapValues(Meter* this) { + 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; ++ this->total = lpl->zfs.max; ++ this->values[0] = lpl->zfs.MFU; ++ this->values[1] = lpl->zfs.MRU; ++ this->values[2] = lpl->zfs.anon; ++ this->values[3] = lpl->zfs.header; ++ this->values[4] = lpl->zfs.other; + + // "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; ++ this->values[5] = lpl->zfs.size; + } + + char* Platform_getProcessEnv(pid_t pid) { +diff --git a/zfs/ZfsArcStats.c b/zfs/ZfsArcStats.c +new file mode 100644 +index 0000000..c33076a +--- /dev/null ++++ b/zfs/ZfsArcStats.c +@@ -0,0 +1,19 @@ ++/* ++htop - ZfsArcStats.c ++(C) 2014 Hisham H. Muhammad ++Released under the GNU GPL, see the COPYING file ++in the source distribution for its full text. ++*/ ++ ++/*{ ++typedef struct ZfsArcStats_ { ++ int enabled; ++ unsigned long long int max; ++ unsigned long long int size; ++ unsigned long long int MFU; ++ unsigned long long int MRU; ++ unsigned long long int anon; ++ unsigned long long int header; ++ unsigned long long int other; ++} ZfsArcStats; ++}*/ +diff --git a/zfs/ZfsArcStats.h b/zfs/ZfsArcStats.h +new file mode 100644 +index 0000000..3697af2 +--- /dev/null ++++ b/zfs/ZfsArcStats.h +@@ -0,0 +1,23 @@ ++/* Do not edit this file. It was automatically generated. */ ++ ++#ifndef HEADER_ZfsArcStats ++#define HEADER_ZfsArcStats ++/* ++htop - ZfsArcStats.h ++(C) 2014 Hisham H. Muhammad ++Released under the GNU GPL, see the COPYING file ++in the source distribution for its full text. ++*/ ++ ++typedef struct ZfsArcStats_ { ++ int enabled; ++ unsigned long long int max; ++ unsigned long long int size; ++ unsigned long long int MFU; ++ unsigned long long int MRU; ++ unsigned long long int anon; ++ unsigned long long int header; ++ unsigned long long int other; ++} ZfsArcStats; ++ ++#endif +diff --git a/zfs/openzfs_sysctl.c b/zfs/openzfs_sysctl.c +new file mode 100644 +index 0000000..ce48f23 +--- /dev/null ++++ b/zfs/openzfs_sysctl.c +@@ -0,0 +1,81 @@ ++/* ++htop - zfs/openzfs_sysctl.c ++(C) 2014 Hisham H. Muhammad ++Released under the GNU GPL, see the COPYING file ++in the source distribution for its full text. ++*/ ++ ++#include "zfs/openzfs_sysctl.h" ++#include "zfs/ZfsArcStats.h" ++ ++#include <unistd.h> ++#include <stdlib.h> ++#include <sys/types.h> ++#include <sys/sysctl.h> ++ ++static int MIB_kstat_zfs_misc_arcstats_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_c_max[5]; ++static int MIB_kstat_zfs_misc_arcstats_mfu_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_mru_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_anon_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_hdr_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_other_size[5]; ++ ++/*{ ++#include "zfs/ZfsArcStats.h" ++}*/ ++ ++int openzfs_sysctl_init() { ++ size_t len; ++ unsigned long long int arcSize; ++ ++ len = sizeof(arcSize); ++ if (sysctlbyname("kstat.zfs.misc.arcstats.size", &arcSize, &len, ++ NULL, 0) == 0 && arcSize != 0) { ++ len = 5; sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); ++ ++ sysctlnametomib("kstat.zfs.misc.arcstats.c_max", MIB_kstat_zfs_misc_arcstats_c_max, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.mfu_size", MIB_kstat_zfs_misc_arcstats_mfu_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.mru_size", MIB_kstat_zfs_misc_arcstats_mru_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); ++ sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++void openzfs_sysctl_updateArcStats(ZfsArcStats *stats) { ++ size_t len; ++ ++ if (stats->enabled) { ++ len = sizeof(stats->size); ++ sysctl(MIB_kstat_zfs_misc_arcstats_size, 5, &(stats->size), &len , NULL, 0); ++ stats->size /= 1024; ++ ++ len = sizeof(stats->max); ++ sysctl(MIB_kstat_zfs_misc_arcstats_c_max, 5, &(stats->max), &len , NULL, 0); ++ stats->max /= 1024; ++ ++ len = sizeof(stats->MFU); ++ sysctl(MIB_kstat_zfs_misc_arcstats_mfu_size, 5, &(stats->MFU), &len , NULL, 0); ++ stats->MFU /= 1024; ++ ++ len = sizeof(stats->MRU); ++ sysctl(MIB_kstat_zfs_misc_arcstats_mru_size, 5, &(stats->MRU), &len , NULL, 0); ++ stats->MRU /= 1024; ++ ++ len = sizeof(stats->anon); ++ sysctl(MIB_kstat_zfs_misc_arcstats_anon_size, 5, &(stats->anon), &len , NULL, 0); ++ stats->anon /= 1024; ++ ++ len = sizeof(stats->header); ++ sysctl(MIB_kstat_zfs_misc_arcstats_hdr_size, 5, &(stats->header), &len , NULL, 0); ++ stats->header /= 1024; ++ ++ len = sizeof(stats->other); ++ sysctl(MIB_kstat_zfs_misc_arcstats_other_size, 5, &(stats->other), &len , NULL, 0); ++ stats->other /= 1024; ++ } ++} +diff --git a/zfs/openzfs_sysctl.h b/zfs/openzfs_sysctl.h +new file mode 100644 +index 0000000..7c04bd7 +--- /dev/null ++++ b/zfs/openzfs_sysctl.h +@@ -0,0 +1,18 @@ ++/* Do not edit this file. It was automatically generated. */ ++ ++#ifndef HEADER_openzfs ++#define HEADER_openzfs ++/* ++htop - zfs/openzfs_sysctl.h ++(C) 2014 Hisham H. Muhammad ++Released under the GNU GPL, see the COPYING file ++in the source distribution for its full text. ++*/ ++ ++#include "zfs/ZfsArcStats.h" ++ ++int openzfs_sysctl_init(); ++ ++void openzfs_sysctl_updateArcStats(ZfsArcStats *stats); ++ ++#endif +-- +2.20.1 + diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0006-ZFS-arcstats-for-Solaris.patch b/users/multi/pkgs/htop/zfs-arc-stats/0006-ZFS-arcstats-for-Solaris.patch new file mode 100644 index 000000000000..96f8d31591e8 --- /dev/null +++ b/users/multi/pkgs/htop/zfs-arc-stats/0006-ZFS-arcstats-for-Solaris.patch @@ -0,0 +1,187 @@ +From ff6914e4ad4b78749bcee5471a33ef206b0a7d03 Mon Sep 17 00:00:00 2001 +From: Ross Williams <ross@ross-williams.net> +Date: Mon, 8 Jul 2019 02:43:39 +0000 +Subject: [PATCH 6/9] ZFS arcstats for Solaris + +--- + Makefile.am | 7 +++++-- + solaris/Platform.c | 19 ++++++++++++++++++ + solaris/Platform.h | 2 ++ + solaris/SolarisProcessList.c | 37 ++++++++++++++++++++++++++++++++++++ + solaris/SolarisProcessList.h | 3 +++ + 5 files changed, 66 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 5eee631..204a8b7 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -157,14 +157,17 @@ solaris_platform_headers = \ + solaris/SolarisProcess.h \ + solaris/SolarisProcessList.h \ + solaris/SolarisCRT.h \ +- solaris/Battery.h ++ solaris/Battery.h \ ++ zfs/ZfsArcMeter.h \ ++ zfs/ZfsArcStats.h + + all_platform_headers += $(solaris_platform_headers) + + if HTOP_SOLARIS + myhtopplatsources = solaris/Platform.c \ + solaris/SolarisProcess.c solaris/SolarisProcessList.c \ +-solaris/SolarisCRT.c solaris/Battery.c ++solaris/SolarisCRT.c solaris/Battery.c \ ++zfs/ZfsArcMeter.c zfs/ZfsArcStats.c + + myhtopplatheaders = $(solaris_platform_headers) + endif +diff --git a/solaris/Platform.c b/solaris/Platform.c +index a29fcb4..8084d1f 100644 +--- a/solaris/Platform.c ++++ b/solaris/Platform.c +@@ -17,6 +17,7 @@ in the source distribution for its full text. + #include "ClockMeter.h" + #include "HostnameMeter.h" + #include "UptimeMeter.h" ++#include "zfs/ZfsArcMeter.h" + #include "SolarisProcess.h" + #include "SolarisProcessList.h" + +@@ -122,6 +123,7 @@ MeterClass* Platform_meterTypes[] = { + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, ++ &ZfsArcMeter_class, + &BlankMeter_class, + NULL + }; +@@ -220,6 +222,23 @@ void Platform_setSwapValues(Meter* this) { + this->values[0] = pl->usedSwap; + } + ++void Platform_setZfsArcValues(Meter* this) { ++ SolarisProcessList* spl = (SolarisProcessList*) this->pl; ++ ++ this->total = spl->zfs.max; ++ this->values[0] = spl->zfs.MFU; ++ this->values[1] = spl->zfs.MRU; ++ this->values[2] = spl->zfs.anon; ++ this->values[3] = spl->zfs.header; ++ this->values[4] = spl->zfs.other; ++ ++ // "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] = spl->zfs.size; ++} ++ + static int Platform_buildenv(void *accum, struct ps_prochandle *Phandle, uintptr_t addr, const char *str) { + envAccum *accump = accum; + (void) Phandle; +diff --git a/solaris/Platform.h b/solaris/Platform.h +index f961b91..62757ff 100644 +--- a/solaris/Platform.h ++++ b/solaris/Platform.h +@@ -60,6 +60,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/solaris/SolarisProcessList.c b/solaris/SolarisProcessList.c +index 2c68185..b6bc6f5 100644 +--- a/solaris/SolarisProcessList.c ++++ b/solaris/SolarisProcessList.c +@@ -27,6 +27,8 @@ in the source distribution for its full text. + + /*{ + ++#include "zfs/ZfsArcStats.h" ++ + #include <kstat.h> + #include <sys/param.h> + #include <sys/uio.h> +@@ -55,6 +57,7 @@ typedef struct SolarisProcessList_ { + ProcessList super; + kstat_ctl_t* kd; + CPUData* cpus; ++ ZfsArcStats zfs; + } SolarisProcessList; + + }*/ +@@ -230,6 +233,39 @@ static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) { + pl->usedSwap = pl->totalSwap - (totalfree * PAGE_SIZE_KB); + } + ++static inline void SolarisProcessList_scanZfsArcstats(ProcessList* pl) { ++ SolarisProcessList* spl = (SolarisProcessList*) pl; ++ kstat_t *arcstats = NULL; ++ int ksrphyserr = -1; ++ kstat_named_t *cur_kstat = NULL; ++ ++ if (spl->kd != NULL) { arcstats = kstat_lookup(spl->kd,"zfs",0,"arcstats"); } ++ if (arcstats != NULL) { ksrphyserr = kstat_read(spl->kd,arcstats,NULL); } ++ if (ksrphyserr != -1) { ++ cur_kstat = kstat_data_lookup( arcstats, "size" ); ++ spl->zfs.size = cur_kstat->value.ui64 / 1024; ++ spl->zfs.enabled = spl->zfs.size > 0 ? 1 : 0; ++ ++ cur_kstat = kstat_data_lookup( arcstats, "c_max" ); ++ spl->zfs.max = cur_kstat->value.ui64 / 1024; ++ ++ cur_kstat = kstat_data_lookup( arcstats, "mfu_size" ); ++ spl->zfs.MFU = cur_kstat->value.ui64 / 1024; ++ ++ cur_kstat = kstat_data_lookup( arcstats, "mru_size" ); ++ spl->zfs.MRU = cur_kstat->value.ui64 / 1024; ++ ++ cur_kstat = kstat_data_lookup( arcstats, "anon_size" ); ++ spl->zfs.anon = cur_kstat->value.ui64 / 1024; ++ ++ cur_kstat = kstat_data_lookup( arcstats, "hdr_size" ); ++ spl->zfs.header = cur_kstat->value.ui64 / 1024; ++ ++ cur_kstat = kstat_data_lookup( arcstats, "other_size" ); ++ spl->zfs.other = cur_kstat->value.ui64 / 1024; ++ } ++} ++ + void ProcessList_delete(ProcessList* pl) { + SolarisProcessList* spl = (SolarisProcessList*) pl; + ProcessList_done(pl); +@@ -367,6 +403,7 @@ int SolarisProcessList_walkproc(psinfo_t *_psinfo, lwpsinfo_t *_lwpsinfo, void * + void ProcessList_goThroughEntries(ProcessList* this) { + SolarisProcessList_scanCPUTime(this); + SolarisProcessList_scanMemoryInfo(this); ++ SolarisProcessList_scanZfsArcstats(this); + this->kernelThreads = 1; + proc_walk(&SolarisProcessList_walkproc, this, PR_WALK_LWP); + } +diff --git a/solaris/SolarisProcessList.h b/solaris/SolarisProcessList.h +index a5f2fbc..26bf449 100644 +--- a/solaris/SolarisProcessList.h ++++ b/solaris/SolarisProcessList.h +@@ -13,6 +13,8 @@ in the source distribution for its full text. + #define MAXCMDLINE 255 + + ++#include "zfs/ZfsArcStats.h" ++ + #include <kstat.h> + #include <sys/param.h> + #include <sys/uio.h> +@@ -41,6 +43,7 @@ typedef struct SolarisProcessList_ { + ProcessList super; + kstat_ctl_t* kd; + CPUData* cpus; ++ ZfsArcStats zfs; + } SolarisProcessList; + + +-- +2.20.1 + diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0007-Refactor-openzfs_sysctl_init-and-ZfsArcMeter.patch b/users/multi/pkgs/htop/zfs-arc-stats/0007-Refactor-openzfs_sysctl_init-and-ZfsArcMeter.patch new file mode 100644 index 000000000000..61c99a716144 --- /dev/null +++ b/users/multi/pkgs/htop/zfs-arc-stats/0007-Refactor-openzfs_sysctl_init-and-ZfsArcMeter.patch @@ -0,0 +1,267 @@ +From e450b586368750e771746ef3e2f5a070962dfd28 Mon Sep 17 00:00:00 2001 +From: Ross Williams <ross@ross-williams.net> +Date: Tue, 3 Sep 2019 18:21:33 +0000 +Subject: [PATCH 7/9] Refactor openzfs_sysctl_init() and ZfsArcMeter... + +openzfs_sysctl_init() now returns void instead of int. +The ZfsArcStats->enabled flag is set inside the init function +now, instead of having to be set from its return value. +Preparation for more flag setting in Compressed ARC commit. + +ZfsArcMeter_readStats() added and all Meter->values[] setting +moved to it, eliminating duplicated code in +{darwin,freebsd,linux,solaris}/Platform.c. +--- + darwin/DarwinProcessList.c | 2 +- + darwin/Platform.c | 13 +------------ + freebsd/FreeBSDProcessList.c | 2 +- + freebsd/Platform.c | 13 +------------ + linux/Platform.c | 13 +------------ + solaris/Platform.c | 13 +------------ + zfs/ZfsArcMeter.c | 18 ++++++++++++++++++ + zfs/ZfsArcMeter.h | 4 ++++ + zfs/openzfs_sysctl.c | 6 +++--- + zfs/openzfs_sysctl.h | 6 +++--- + 10 files changed, 34 insertions(+), 56 deletions(-) + +diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c +index 122e018..9b4ba11 100644 +--- a/darwin/DarwinProcessList.c ++++ b/darwin/DarwinProcessList.c +@@ -151,7 +151,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui + ProcessList_getVMStats(&this->vm_stats); + + /* Initialize the ZFS kstats, if zfs.kext loaded */ +- this->zfs.enabled = openzfs_sysctl_init(); ++ openzfs_sysctl_init(&this->zfs); + openzfs_sysctl_updateArcStats(&this->zfs); + + this->super.kernelThreads = 0; +diff --git a/darwin/Platform.c b/darwin/Platform.c +index 8fbb9c9..f9f09b5 100644 +--- a/darwin/Platform.c ++++ b/darwin/Platform.c +@@ -246,18 +246,7 @@ void Platform_setSwapValues(Meter* mtr) { + void Platform_setZfsArcValues(Meter* this) { + DarwinProcessList* dpl = (DarwinProcessList*) this->pl; + +- this->total = dpl->zfs.max; +- this->values[0] = dpl->zfs.MFU; +- this->values[1] = dpl->zfs.MRU; +- this->values[2] = dpl->zfs.anon; +- this->values[3] = dpl->zfs.header; +- this->values[4] = dpl->zfs.other; +- +- // "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] = dpl->zfs.size; ++ ZfsArcMeter_readStats(this, &(dpl->zfs)); + } + + char* Platform_getProcessEnv(pid_t pid) { +diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c +index 1cbfdaa..fd69419 100644 +--- a/freebsd/FreeBSDProcessList.c ++++ b/freebsd/FreeBSDProcessList.c +@@ -118,7 +118,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui + + len = 2; sysctlnametomib("vfs.bufspace", MIB_vfs_bufspace, &len); + +- fpl->zfs.enabled = openzfs_sysctl_init(); ++ openzfs_sysctl_init(&fpl->zfs); + openzfs_sysctl_updateArcStats(&fpl->zfs); + + int smp = 0; +diff --git a/freebsd/Platform.c b/freebsd/Platform.c +index 05c0e92..b08a508 100644 +--- a/freebsd/Platform.c ++++ b/freebsd/Platform.c +@@ -202,18 +202,7 @@ void Platform_setSwapValues(Meter* this) { + void Platform_setZfsArcValues(Meter* this) { + FreeBSDProcessList* fpl = (FreeBSDProcessList*) this->pl; + +- this->total = fpl->zfs.max; +- this->values[0] = fpl->zfs.MFU; +- this->values[1] = fpl->zfs.MRU; +- this->values[2] = fpl->zfs.anon; +- this->values[3] = fpl->zfs.header; +- this->values[4] = fpl->zfs.other; +- +- // "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] = fpl->zfs.size; ++ ZfsArcMeter_readStats(this, &(fpl->zfs)); + } + + void Platform_setTasksValues(Meter* this) { +diff --git a/linux/Platform.c b/linux/Platform.c +index e2a3c6d..69f6688 100644 +--- a/linux/Platform.c ++++ b/linux/Platform.c +@@ -218,18 +218,7 @@ void Platform_setSwapValues(Meter* this) { + void Platform_setZfsArcValues(Meter* this) { + LinuxProcessList* lpl = (LinuxProcessList*) this->pl; + +- this->total = lpl->zfs.max; +- this->values[0] = lpl->zfs.MFU; +- this->values[1] = lpl->zfs.MRU; +- this->values[2] = lpl->zfs.anon; +- this->values[3] = lpl->zfs.header; +- this->values[4] = lpl->zfs.other; +- +- // "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->zfs.size; ++ ZfsArcMeter_readStats(this, &(lpl->zfs)); + } + + char* Platform_getProcessEnv(pid_t pid) { +diff --git a/solaris/Platform.c b/solaris/Platform.c +index 8084d1f..74ae14e 100644 +--- a/solaris/Platform.c ++++ b/solaris/Platform.c +@@ -225,18 +225,7 @@ void Platform_setSwapValues(Meter* this) { + void Platform_setZfsArcValues(Meter* this) { + SolarisProcessList* spl = (SolarisProcessList*) this->pl; + +- this->total = spl->zfs.max; +- this->values[0] = spl->zfs.MFU; +- this->values[1] = spl->zfs.MRU; +- this->values[2] = spl->zfs.anon; +- this->values[3] = spl->zfs.header; +- this->values[4] = spl->zfs.other; +- +- // "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] = spl->zfs.size; ++ ZfsArcMeter_readStats(this, &(spl->zfs)); + } + + static int Platform_buildenv(void *accum, struct ps_prochandle *Phandle, uintptr_t addr, const char *str) { +diff --git a/zfs/ZfsArcMeter.c b/zfs/ZfsArcMeter.c +index ebd8099..9f7028b 100644 +--- a/zfs/ZfsArcMeter.c ++++ b/zfs/ZfsArcMeter.c +@@ -6,6 +6,7 @@ in the source distribution for its full text. + */ + + #include "ZfsArcMeter.h" ++#include "ZfsArcStats.h" + + #include "CRT.h" + #include "Platform.h" +@@ -17,6 +18,8 @@ in the source distribution for its full text. + #include <assert.h> + + /*{ ++#include "ZfsArcStats.h" ++ + #include "Meter.h" + }*/ + +@@ -24,6 +27,21 @@ int ZfsArcMeter_attributes[] = { + ZFS_MFU, ZFS_MRU, ZFS_ANON, ZFS_HEADER, ZFS_OTHER + }; + ++void ZfsArcMeter_readStats(Meter* this, ZfsArcStats* stats) { ++ this->total = stats->max; ++ this->values[0] = stats->MFU; ++ this->values[1] = stats->MRU; ++ this->values[2] = stats->anon; ++ this->values[3] = stats->header; ++ this->values[4] = stats->other; ++ ++ // "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] = stats->size; ++} ++ + static void ZfsArcMeter_updateValues(Meter* this, char* buffer, int size) { + int written; + Platform_setZfsArcValues(this); +diff --git a/zfs/ZfsArcMeter.h b/zfs/ZfsArcMeter.h +index b89be22..c52083d 100644 +--- a/zfs/ZfsArcMeter.h ++++ b/zfs/ZfsArcMeter.h +@@ -9,10 +9,14 @@ Released under the GNU GPL, see the COPYING file + in the source distribution for its full text. + */ + ++#include "ZfsArcStats.h" ++ + #include "Meter.h" + + extern int ZfsArcMeter_attributes[]; + ++void ZfsArcMeter_readStats(Meter* this, ZfsArcStats* stats); ++ + extern MeterClass ZfsArcMeter_class; + + #endif +diff --git a/zfs/openzfs_sysctl.c b/zfs/openzfs_sysctl.c +index ce48f23..ceee4d1 100644 +--- a/zfs/openzfs_sysctl.c ++++ b/zfs/openzfs_sysctl.c +@@ -25,13 +25,14 @@ static int MIB_kstat_zfs_misc_arcstats_other_size[5]; + #include "zfs/ZfsArcStats.h" + }*/ + +-int openzfs_sysctl_init() { ++void openzfs_sysctl_init(ZfsArcStats *stats) { + size_t len; + unsigned long long int arcSize; + + len = sizeof(arcSize); + if (sysctlbyname("kstat.zfs.misc.arcstats.size", &arcSize, &len, + NULL, 0) == 0 && arcSize != 0) { ++ stats->enabled = 1; + len = 5; sysctlnametomib("kstat.zfs.misc.arcstats.size", MIB_kstat_zfs_misc_arcstats_size, &len); + + sysctlnametomib("kstat.zfs.misc.arcstats.c_max", MIB_kstat_zfs_misc_arcstats_c_max, &len); +@@ -40,9 +41,8 @@ int openzfs_sysctl_init() { + sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); +- return 1; + } else { +- return 0; ++ stats->enabled = 0; + } + } + +diff --git a/zfs/openzfs_sysctl.h b/zfs/openzfs_sysctl.h +index 7c04bd7..6e44ac3 100644 +--- a/zfs/openzfs_sysctl.h ++++ b/zfs/openzfs_sysctl.h +@@ -1,7 +1,7 @@ + /* Do not edit this file. It was automatically generated. */ + +-#ifndef HEADER_openzfs +-#define HEADER_openzfs ++#ifndef HEADER_openzfs_sysctl ++#define HEADER_openzfs_sysctl + /* + htop - zfs/openzfs_sysctl.h + (C) 2014 Hisham H. Muhammad +@@ -11,7 +11,7 @@ in the source distribution for its full text. + + #include "zfs/ZfsArcStats.h" + +-int openzfs_sysctl_init(); ++void openzfs_sysctl_init(ZfsArcStats *stats); + + void openzfs_sysctl_updateArcStats(ZfsArcStats *stats); + +-- +2.20.1 + diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0008-Support-for-ZFS-Compressed-ARC-statistics.patch b/users/multi/pkgs/htop/zfs-arc-stats/0008-Support-for-ZFS-Compressed-ARC-statistics.patch new file mode 100644 index 000000000000..14bc83d8665c --- /dev/null +++ b/users/multi/pkgs/htop/zfs-arc-stats/0008-Support-for-ZFS-Compressed-ARC-statistics.patch @@ -0,0 +1,628 @@ +From 613556faebd16325da8c9057c81f39a2410d803f Mon Sep 17 00:00:00 2001 +From: Ross Williams <ross@ross-williams.net> +Date: Tue, 3 Sep 2019 18:26:02 +0000 +Subject: [PATCH 8/9] Support for ZFS Compressed ARC statistics + +--- + CRT.c | 14 ++++++ + CRT.h | 2 + + Makefile.am | 12 +++-- + darwin/Platform.c | 8 ++++ + darwin/Platform.h | 2 + + freebsd/Platform.c | 8 ++++ + freebsd/Platform.h | 2 + + linux/LinuxProcessList.c | 10 +++++ + linux/Platform.c | 7 +++ + linux/Platform.h | 2 + + solaris/Platform.c | 8 ++++ + solaris/Platform.h | 2 + + solaris/SolarisProcessList.c | 10 +++++ + zfs/ZfsArcStats.c | 3 ++ + zfs/ZfsArcStats.h | 3 ++ + zfs/ZfsCompressedArcMeter.c | 86 ++++++++++++++++++++++++++++++++++++ + zfs/ZfsCompressedArcMeter.h | 22 +++++++++ + zfs/openzfs_sysctl.c | 18 ++++++++ + 18 files changed, 215 insertions(+), 4 deletions(-) + create mode 100644 zfs/ZfsCompressedArcMeter.c + create mode 100644 zfs/ZfsCompressedArcMeter.h + +diff --git a/CRT.c b/CRT.c +index b9017aa..cb36b6c 100644 +--- a/CRT.c ++++ b/CRT.c +@@ -133,6 +133,8 @@ typedef enum ColorElements_ { + ZFS_ANON, + ZFS_HEADER, + ZFS_OTHER, ++ ZFS_COMPRESSED, ++ ZFS_RATIO, + LAST_COLORELEMENT + } ColorElements; + +@@ -242,6 +244,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [ZFS_ANON] = ColorPair(Magenta,Black), + [ZFS_HEADER] = ColorPair(Cyan,Black), + [ZFS_OTHER] = ColorPair(Magenta,Black), ++ [ZFS_COMPRESSED] = ColorPair(Blue,Black), ++ [ZFS_RATIO] = ColorPair(Magenta,Black), + }, + [COLORSCHEME_MONOCHROME] = { + [RESET_COLOR] = A_NORMAL, +@@ -306,6 +310,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [ZFS_ANON] = A_DIM, + [ZFS_HEADER] = A_BOLD, + [ZFS_OTHER] = A_DIM, ++ [ZFS_COMPRESSED] = A_BOLD, ++ [ZFS_RATIO] = A_BOLD, + }, + [COLORSCHEME_BLACKONWHITE] = { + [RESET_COLOR] = ColorPair(Black,White), +@@ -370,6 +376,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [ZFS_ANON] = ColorPair(Magenta,White), + [ZFS_HEADER] = ColorPair(Yellow,White), + [ZFS_OTHER] = ColorPair(Magenta,White), ++ [ZFS_COMPRESSED] = ColorPair(Cyan,White), ++ [ZFS_RATIO] = ColorPair(Magenta,White), + }, + [COLORSCHEME_LIGHTTERMINAL] = { + [RESET_COLOR] = ColorPair(Black,Black), +@@ -434,6 +442,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [ZFS_ANON] = A_BOLD | ColorPair(Magenta,Black), + [ZFS_HEADER] = ColorPair(Black,Black), + [ZFS_OTHER] = A_BOLD | ColorPair(Magenta,Black), ++ [ZFS_COMPRESSED] = ColorPair(Cyan,Black), ++ [ZFS_RATIO] = A_BOLD | ColorPair(Magenta,Black), + }, + [COLORSCHEME_MIDNIGHT] = { + [RESET_COLOR] = ColorPair(White,Blue), +@@ -498,6 +508,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [ZFS_ANON] = A_BOLD | ColorPair(Magenta,Blue), + [ZFS_HEADER] = A_BOLD | ColorPair(Yellow,Blue), + [ZFS_OTHER] = A_BOLD | ColorPair(Magenta,Blue), ++ [ZFS_COMPRESSED] = A_BOLD | ColorPair(White,Blue), ++ [ZFS_RATIO] = A_BOLD | ColorPair(Magenta,Blue), + }, + [COLORSCHEME_BLACKNIGHT] = { + [RESET_COLOR] = ColorPair(Cyan,Black), +@@ -562,6 +574,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { + [ZFS_ANON] = ColorPair(Magenta,Black), + [ZFS_HEADER] = ColorPair(Yellow,Black), + [ZFS_OTHER] = ColorPair(Magenta,Black), ++ [ZFS_COMPRESSED] = ColorPair(Blue,Black), ++ [ZFS_RATIO] = ColorPair(Magenta,Black), + }, + [COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated. + }; +diff --git a/CRT.h b/CRT.h +index 2275349..d9eba55 100644 +--- a/CRT.h ++++ b/CRT.h +@@ -121,6 +121,8 @@ typedef enum ColorElements_ { + ZFS_ANON, + ZFS_HEADER, + ZFS_OTHER, ++ ZFS_COMPRESSED, ++ ZFS_RATIO, + LAST_COLORELEMENT + } ColorElements; + +diff --git a/Makefile.am b/Makefile.am +index 204a8b7..2d159f0 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -50,6 +50,7 @@ linux_platform_headers = \ + linux/LinuxCRT.h \ + linux/Battery.h \ + zfs/ZfsArcMeter.h \ ++ zfs/ZfsCompressedArcMeter.h \ + zfs/ZfsArcStats.h + + all_platform_headers += $(linux_platform_headers) +@@ -58,7 +59,7 @@ 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 \ +-zfs/ZfsArcMeter.c zfs/ZfsArcStats.c ++zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c + + myhtopplatheaders = $(linux_platform_headers) + endif +@@ -73,6 +74,7 @@ freebsd_platform_headers = \ + freebsd/FreeBSDCRT.h \ + freebsd/Battery.h \ + zfs/ZfsArcMeter.h \ ++ zfs/ZfsCompressedArcMeter.h \ + zfs/ZfsArcStats.h \ + zfs/openzfs_sysctl.h + +@@ -81,7 +83,7 @@ all_platform_headers += $(freebsd_platform_headers) + if HTOP_FREEBSD + myhtopplatsources = freebsd/Platform.c freebsd/FreeBSDProcessList.c \ + freebsd/FreeBSDProcess.c freebsd/FreeBSDCRT.c freebsd/Battery.c \ +-zfs/ZfsArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c ++zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c + + myhtopplatheaders = $(freebsd_platform_headers) + endif +@@ -135,6 +137,7 @@ darwin_platform_headers = \ + darwin/DarwinCRT.h \ + darwin/Battery.h \ + zfs/ZfsArcMeter.h \ ++ zfs/ZfsCompressedArcMeter.h \ + zfs/ZfsArcStats.h \ + zfs/openzfs_sysctl.h + +@@ -144,7 +147,7 @@ if HTOP_DARWIN + AM_LDFLAGS += -framework IOKit -framework CoreFoundation + myhtopplatsources = darwin/Platform.c darwin/DarwinProcess.c \ + darwin/DarwinProcessList.c darwin/DarwinCRT.c darwin/Battery.c \ +-zfs/ZfsArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c ++zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c zfs/openzfs_sysctl.c + + myhtopplatheaders = $(darwin_platform_headers) + endif +@@ -159,6 +162,7 @@ solaris_platform_headers = \ + solaris/SolarisCRT.h \ + solaris/Battery.h \ + zfs/ZfsArcMeter.h \ ++ zfs/ZfsCompressedArcMeter.h \ + zfs/ZfsArcStats.h + + all_platform_headers += $(solaris_platform_headers) +@@ -167,7 +171,7 @@ if HTOP_SOLARIS + myhtopplatsources = solaris/Platform.c \ + solaris/SolarisProcess.c solaris/SolarisProcessList.c \ + solaris/SolarisCRT.c solaris/Battery.c \ +-zfs/ZfsArcMeter.c zfs/ZfsArcStats.c ++zfs/ZfsArcMeter.c zfs/ZfsCompressedArcMeter.c zfs/ZfsArcStats.c + + myhtopplatheaders = $(solaris_platform_headers) + endif +diff --git a/darwin/Platform.c b/darwin/Platform.c +index f9f09b5..286ff16 100644 +--- a/darwin/Platform.c ++++ b/darwin/Platform.c +@@ -16,6 +16,7 @@ in the source distribution for its full text. + #include "HostnameMeter.h" + #include "UptimeMeter.h" + #include "zfs/ZfsArcMeter.h" ++#include "zfs/ZfsCompressedArcMeter.h" + #include "DarwinProcessList.h" + + #include <stdlib.h> +@@ -119,6 +120,7 @@ MeterClass* Platform_meterTypes[] = { + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &ZfsArcMeter_class, ++ &ZfsCompressedArcMeter_class, + &BlankMeter_class, + NULL + }; +@@ -249,6 +251,12 @@ void Platform_setZfsArcValues(Meter* this) { + ZfsArcMeter_readStats(this, &(dpl->zfs)); + } + ++void Platform_setZfsCompressedArcValues(Meter* this) { ++ DarwinProcessList* dpl = (DarwinProcessList*) this->pl; ++ ++ ZfsCompressedArcMeter_readStats(this, &(dpl->zfs)); ++} ++ + char* Platform_getProcessEnv(pid_t pid) { + char* env = NULL; + +diff --git a/darwin/Platform.h b/darwin/Platform.h +index f836077..e17661d 100644 +--- a/darwin/Platform.h ++++ b/darwin/Platform.h +@@ -50,6 +50,8 @@ void Platform_setSwapValues(Meter* mtr); + + void Platform_setZfsArcValues(Meter* this); + ++void Platform_setZfsCompressedArcValues(Meter* this); ++ + char* Platform_getProcessEnv(pid_t pid); + + #endif +diff --git a/freebsd/Platform.c b/freebsd/Platform.c +index b08a508..0986a3d 100644 +--- a/freebsd/Platform.c ++++ b/freebsd/Platform.c +@@ -16,6 +16,7 @@ in the source distribution for its full text. + #include "ClockMeter.h" + #include "HostnameMeter.h" + #include "zfs/ZfsArcMeter.h" ++#include "zfs/ZfsCompressedArcMeter.h" + #include "FreeBSDProcess.h" + #include "FreeBSDProcessList.h" + +@@ -106,6 +107,7 @@ MeterClass* Platform_meterTypes[] = { + &RightCPUs2Meter_class, + &BlankMeter_class, + &ZfsArcMeter_class, ++ &ZfsCompressedArcMeter_class, + NULL + }; + +@@ -205,6 +207,12 @@ void Platform_setZfsArcValues(Meter* this) { + ZfsArcMeter_readStats(this, &(fpl->zfs)); + } + ++void Platform_setZfsCompressedArcValues(Meter* this) { ++ FreeBSDProcessList* fpl = (FreeBSDProcessList*) this->pl; ++ ++ ZfsCompressedArcMeter_readStats(this, &(fpl->zfs)); ++} ++ + void Platform_setTasksValues(Meter* this) { + // TODO + } +diff --git a/freebsd/Platform.h b/freebsd/Platform.h +index 3dc7ebf..0268f2c 100644 +--- a/freebsd/Platform.h ++++ b/freebsd/Platform.h +@@ -46,6 +46,8 @@ void Platform_setSwapValues(Meter* this); + + void Platform_setZfsArcValues(Meter* this); + ++void Platform_setZfsCompressedArcValues(Meter* this); ++ + void Platform_setTasksValues(Meter* this); + + char* Platform_getProcessEnv(pid_t pid); +diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c +index 3e88910..4596c3b 100644 +--- a/linux/LinuxProcessList.c ++++ b/linux/LinuxProcessList.c +@@ -984,9 +984,14 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) { + 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) ++ #define tryReadFlag(label, variable, flag) do { if (String_startsWith(buffer, label) && sscanf(buffer + strlen(label), " %*2u %32llu", variable)) { flag = 1; break; } else { flag = 0; } } while(0) + switch (buffer[0]) { + case 'c': + tryRead("c_max", &lpl->zfs.max); ++ tryReadFlag("compressed", &lpl->zfs.compressed, &lpl->zfs.isCompressed); ++ break; ++ case 'u': ++ tryRead("uncompressed", &lpl->zfs.uncompressed); + break; + case 's': + tryRead("size", &lpl->zfs.size); +@@ -1010,6 +1015,7 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) { + break; + } + #undef tryRead ++ #undef tryReadFlag + } + fclose(file); + +@@ -1021,6 +1027,10 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) { + lpl->zfs.anon /= 1024; + lpl->zfs.header /= 1024; + lpl->zfs.other = (dbufSize + dnodeSize + bonusSize) / 1024; ++ if ( lpl->zfs.isCompressed ) { ++ lpl->zfs.compressed /= 1024; ++ lpl->zfs.uncompressed /= 1024; ++ } + } + + static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) { +diff --git a/linux/Platform.c b/linux/Platform.c +index 69f6688..f7088cf 100644 +--- a/linux/Platform.c ++++ b/linux/Platform.c +@@ -22,6 +22,7 @@ in the source distribution for its full text. + #include "ClockMeter.h" + #include "HostnameMeter.h" + #include "zfs/ZfsArcMeter.h" ++#include "zfs/ZfsCompressedArcMeter.h" + #include "LinuxProcess.h" + + #include <math.h> +@@ -128,6 +129,7 @@ MeterClass* Platform_meterTypes[] = { + &RightCPUs2Meter_class, + &BlankMeter_class, + &ZfsArcMeter_class, ++ &ZfsCompressedArcMeter_class, + NULL + }; + +@@ -221,6 +223,11 @@ void Platform_setZfsArcValues(Meter* this) { + ZfsArcMeter_readStats(this, &(lpl->zfs)); + } + ++void Platform_setZfsCompressedArcValues(Meter* this) { ++ LinuxProcessList* lpl = (LinuxProcessList*) this->pl; ++ ++ ZfsCompressedArcMeter_readStats(this, &(lpl->zfs)); ++} + 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 e775181..5d85eb3 100644 +--- a/linux/Platform.h ++++ b/linux/Platform.h +@@ -45,6 +45,8 @@ void Platform_setSwapValues(Meter* this); + + void Platform_setZfsArcValues(Meter* this); + ++void Platform_setZfsCompressedArcValues(Meter* this); ++ + char* Platform_getProcessEnv(pid_t pid); + + #endif +diff --git a/solaris/Platform.c b/solaris/Platform.c +index 74ae14e..7dcfe32 100644 +--- a/solaris/Platform.c ++++ b/solaris/Platform.c +@@ -18,6 +18,7 @@ in the source distribution for its full text. + #include "HostnameMeter.h" + #include "UptimeMeter.h" + #include "zfs/ZfsArcMeter.h" ++#include "zfs/ZfsCompressedArcMeter.h" + #include "SolarisProcess.h" + #include "SolarisProcessList.h" + +@@ -124,6 +125,7 @@ MeterClass* Platform_meterTypes[] = { + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &ZfsArcMeter_class, ++ &ZfsCompressedArcMeter_class, + &BlankMeter_class, + NULL + }; +@@ -228,6 +230,12 @@ void Platform_setZfsArcValues(Meter* this) { + ZfsArcMeter_readStats(this, &(spl->zfs)); + } + ++void Platform_setZfsCompressedArcValues(Meter* this) { ++ SolarisProcessList* spl = (SolarisProcessList*) this->pl; ++ ++ ZfsCompressedArcMeter_readStats(this, &(spl->zfs)); ++} ++ + static int Platform_buildenv(void *accum, struct ps_prochandle *Phandle, uintptr_t addr, const char *str) { + envAccum *accump = accum; + (void) Phandle; +diff --git a/solaris/Platform.h b/solaris/Platform.h +index 62757ff..3b5aef8 100644 +--- a/solaris/Platform.h ++++ b/solaris/Platform.h +@@ -62,6 +62,8 @@ void Platform_setSwapValues(Meter* this); + + void Platform_setZfsArcValues(Meter* this); + ++void Platform_setZfsCompressedArcValues(Meter* this); ++ + char* Platform_getProcessEnv(pid_t pid); + + #endif +diff --git a/solaris/SolarisProcessList.c b/solaris/SolarisProcessList.c +index b6bc6f5..d62ea1d 100644 +--- a/solaris/SolarisProcessList.c ++++ b/solaris/SolarisProcessList.c +@@ -263,6 +263,16 @@ static inline void SolarisProcessList_scanZfsArcstats(ProcessList* pl) { + + cur_kstat = kstat_data_lookup( arcstats, "other_size" ); + spl->zfs.other = cur_kstat->value.ui64 / 1024; ++ ++ if ((cur_kstat = kstat_data_lookup( arcstats, "compressed_size" )) != NULL) { ++ spl->zfs.compressed = cur_kstat->value.ui64 / 1024; ++ spl->zfs.isCompressed = 1; ++ ++ cur_kstat = kstat_data_lookup( arcstats, "uncompressed_size" ); ++ spl->zfs.uncompressed = cur_kstat->value.ui64 / 1024; ++ } else { ++ spl->zfs.isCompressed = 0; ++ } + } + } + +diff --git a/zfs/ZfsArcStats.c b/zfs/ZfsArcStats.c +index c33076a..1bfaf47 100644 +--- a/zfs/ZfsArcStats.c ++++ b/zfs/ZfsArcStats.c +@@ -8,6 +8,7 @@ in the source distribution for its full text. + /*{ + typedef struct ZfsArcStats_ { + int enabled; ++ int isCompressed; + unsigned long long int max; + unsigned long long int size; + unsigned long long int MFU; +@@ -15,5 +16,7 @@ typedef struct ZfsArcStats_ { + unsigned long long int anon; + unsigned long long int header; + unsigned long long int other; ++ unsigned long long int compressed; ++ unsigned long long int uncompressed; + } ZfsArcStats; + }*/ +diff --git a/zfs/ZfsArcStats.h b/zfs/ZfsArcStats.h +index 3697af2..ee5d0ed 100644 +--- a/zfs/ZfsArcStats.h ++++ b/zfs/ZfsArcStats.h +@@ -11,6 +11,7 @@ in the source distribution for its full text. + + typedef struct ZfsArcStats_ { + int enabled; ++ int isCompressed; + unsigned long long int max; + unsigned long long int size; + unsigned long long int MFU; +@@ -18,6 +19,8 @@ typedef struct ZfsArcStats_ { + unsigned long long int anon; + unsigned long long int header; + unsigned long long int other; ++ unsigned long long int compressed; ++ unsigned long long int uncompressed; + } ZfsArcStats; + + #endif +diff --git a/zfs/ZfsCompressedArcMeter.c b/zfs/ZfsCompressedArcMeter.c +new file mode 100644 +index 0000000..ac3944d +--- /dev/null ++++ b/zfs/ZfsCompressedArcMeter.c +@@ -0,0 +1,86 @@ ++/* ++htop - ZfsCompressedArcMeter.c ++(C) 2004-2011 Hisham H. Muhammad ++Released under the GNU GPL, see the COPYING file ++in the source distribution for its full text. ++*/ ++ ++#include "ZfsCompressedArcMeter.h" ++#include "ZfsArcStats.h" ++ ++#include "CRT.h" ++#include "Platform.h" ++ ++#include <stdlib.h> ++#include <string.h> ++#include <math.h> ++#include <sys/param.h> ++#include <assert.h> ++ ++/*{ ++#include "ZfsArcStats.h" ++ ++#include "Meter.h" ++}*/ ++ ++int ZfsCompressedArcMeter_attributes[] = { ++ ZFS_COMPRESSED ++}; ++ ++void ZfsCompressedArcMeter_readStats(Meter* this, ZfsArcStats* stats) { ++ if ( stats->isCompressed ) { ++ this->total = stats->uncompressed; ++ this->values[0] = stats->compressed; ++ } else { ++ // For uncompressed ARC, report 1:1 ratio ++ this->total = stats->size; ++ this->values[0] = stats->size; ++ } ++} ++ ++static void ZfsCompressedArcMeter_printRatioString(Meter* this, char* buffer, int size) { ++ xSnprintf(buffer, size, "%.2f:1", this->total/this->values[0]); ++} ++ ++static void ZfsCompressedArcMeter_updateValues(Meter* this, char* buffer, int size) { ++ Platform_setZfsCompressedArcValues(this); ++ ++ ZfsCompressedArcMeter_printRatioString(this, buffer, size); ++} ++ ++static void ZfsCompressedArcMeter_display(Object* cast, RichString* out) { ++ char buffer[50]; ++ Meter* this = (Meter*)cast; ++ ++ if (this->values[0] > 0) { ++ Meter_humanUnit(buffer, this->total, 50); ++ RichString_append(out, CRT_colors[METER_VALUE], buffer); ++ RichString_append(out, CRT_colors[METER_TEXT], " Uncompressed, "); ++ Meter_humanUnit(buffer, this->values[0], 50); ++ RichString_append(out, CRT_colors[METER_VALUE], buffer); ++ RichString_append(out, CRT_colors[METER_TEXT], " Compressed, "); ++ ZfsCompressedArcMeter_printRatioString(this, buffer, 50); ++ RichString_append(out, CRT_colors[METER_VALUE], buffer); ++ RichString_append(out, CRT_colors[METER_TEXT], " Ratio"); ++ } else { ++ RichString_write(out, CRT_colors[METER_TEXT], " "); ++ RichString_append(out, CRT_colors[FAILED_SEARCH], "Compression Unavailable"); ++ } ++} ++ ++MeterClass ZfsCompressedArcMeter_class = { ++ .super = { ++ .extends = Class(Meter), ++ .delete = Meter_delete, ++ .display = ZfsCompressedArcMeter_display, ++ }, ++ .updateValues = ZfsCompressedArcMeter_updateValues, ++ .defaultMode = TEXT_METERMODE, ++ .maxItems = 1, ++ .total = 100.0, ++ .attributes = ZfsCompressedArcMeter_attributes, ++ .name = "ZFSCARC", ++ .uiName = "ZFS CARC", ++ .description = "ZFS CARC: Compressed ARC statistics", ++ .caption = "ARC: " ++}; +diff --git a/zfs/ZfsCompressedArcMeter.h b/zfs/ZfsCompressedArcMeter.h +new file mode 100644 +index 0000000..5afcc99 +--- /dev/null ++++ b/zfs/ZfsCompressedArcMeter.h +@@ -0,0 +1,22 @@ ++/* Do not edit this file. It was automatically generated. */ ++ ++#ifndef HEADER_ZfsCompressedArcMeter ++#define HEADER_ZfsCompressedArcMeter ++/* ++htop - ZfsCompressedArcMeter.h ++(C) 2004-2011 Hisham H. Muhammad ++Released under the GNU GPL, see the COPYING file ++in the source distribution for its full text. ++*/ ++ ++#include "ZfsArcStats.h" ++ ++#include "Meter.h" ++ ++extern int ZfsCompressedArcMeter_attributes[]; ++ ++void ZfsCompressedArcMeter_readStats(Meter* this, ZfsArcStats* stats); ++ ++extern MeterClass ZfsCompressedArcMeter_class; ++ ++#endif +diff --git a/zfs/openzfs_sysctl.c b/zfs/openzfs_sysctl.c +index ceee4d1..c1ab223 100644 +--- a/zfs/openzfs_sysctl.c ++++ b/zfs/openzfs_sysctl.c +@@ -20,6 +20,8 @@ static int MIB_kstat_zfs_misc_arcstats_mru_size[5]; + static int MIB_kstat_zfs_misc_arcstats_anon_size[5]; + static int MIB_kstat_zfs_misc_arcstats_hdr_size[5]; + static int MIB_kstat_zfs_misc_arcstats_other_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_compressed_size[5]; ++static int MIB_kstat_zfs_misc_arcstats_uncompressed_size[5]; + + /*{ + #include "zfs/ZfsArcStats.h" +@@ -41,6 +43,12 @@ void openzfs_sysctl_init(ZfsArcStats *stats) { + sysctlnametomib("kstat.zfs.misc.arcstats.anon_size", MIB_kstat_zfs_misc_arcstats_anon_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.hdr_size", MIB_kstat_zfs_misc_arcstats_hdr_size, &len); + sysctlnametomib("kstat.zfs.misc.arcstats.other_size", MIB_kstat_zfs_misc_arcstats_other_size, &len); ++ if (sysctlnametomib("kstat.zfs.misc.arcstats.compressed_size", MIB_kstat_zfs_misc_arcstats_compressed_size, &len) == 0) { ++ stats->isCompressed = 1; ++ sysctlnametomib("kstat.zfs.misc.arcstats.uncompressed_size", MIB_kstat_zfs_misc_arcstats_uncompressed_size, &len); ++ } else { ++ stats->isCompressed = 0; ++ } + } else { + stats->enabled = 0; + } +@@ -77,5 +85,15 @@ void openzfs_sysctl_updateArcStats(ZfsArcStats *stats) { + len = sizeof(stats->other); + sysctl(MIB_kstat_zfs_misc_arcstats_other_size, 5, &(stats->other), &len , NULL, 0); + stats->other /= 1024; ++ ++ if (stats->isCompressed) { ++ len = sizeof(stats->compressed); ++ sysctl(MIB_kstat_zfs_misc_arcstats_compressed_size, 5, &(stats->compressed), &len , NULL, 0); ++ stats->compressed /= 1024; ++ ++ len = sizeof(stats->uncompressed); ++ sysctl(MIB_kstat_zfs_misc_arcstats_uncompressed_size, 5, &(stats->uncompressed), &len , NULL, 0); ++ stats->uncompressed /= 1024; ++ } + } + } +-- +2.20.1 + diff --git a/users/multi/pkgs/htop/zfs-arc-stats/0009-Linux-fixes.patch b/users/multi/pkgs/htop/zfs-arc-stats/0009-Linux-fixes.patch new file mode 100644 index 000000000000..368b60279018 --- /dev/null +++ b/users/multi/pkgs/htop/zfs-arc-stats/0009-Linux-fixes.patch @@ -0,0 +1,29 @@ +From a267003f2f38df5d52ae3f07658c1bbd20b5fb5e Mon Sep 17 00:00:00 2001 +From: Ross Williams <ross@ross-williams.net> +Date: Tue, 3 Sep 2019 19:56:38 +0000 +Subject: [PATCH 9/9] Linux fixes + +--- + linux/LinuxProcessList.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c +index 4596c3b..1d5700e 100644 +--- a/linux/LinuxProcessList.c ++++ b/linux/LinuxProcessList.c +@@ -988,10 +988,10 @@ static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) { + switch (buffer[0]) { + case 'c': + tryRead("c_max", &lpl->zfs.max); +- tryReadFlag("compressed", &lpl->zfs.compressed, &lpl->zfs.isCompressed); ++ tryReadFlag("compressed_size", &lpl->zfs.compressed, lpl->zfs.isCompressed); + break; + case 'u': +- tryRead("uncompressed", &lpl->zfs.uncompressed); ++ tryRead("uncompressed_size", &lpl->zfs.uncompressed); + break; + case 's': + tryRead("size", &lpl->zfs.size); +-- +2.20.1 + |