From 92258e99e639795f4119a86a1c44d5015b29ffdc Mon Sep 17 00:00:00 2001 From: Ross Williams Date: Sat, 6 Jul 2019 04:27:00 +0000 Subject: 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(-) (limited to 'freebsd') diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 9fef324a..26019b68 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; -- cgit v1.2.3 From a93edde1a21e533472b5d443002032260b5bd066 Mon Sep 17 00:00:00 2001 From: Ross Williams Date: Sat, 6 Jul 2019 04:27:49 +0000 Subject: 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. --- freebsd/FreeBSDProcessList.c | 48 ++++++++++++++++++++++++++++++++++++++++++-- freebsd/FreeBSDProcessList.h | 6 ++++++ freebsd/Platform.c | 19 ++++++++++++++++++ freebsd/Platform.h | 2 ++ 4 files changed, 73 insertions(+), 2 deletions(-) (limited to 'freebsd') diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 26019b68..94cbaa19 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 af343fb0..cf96a702 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 5dd6ca41..d8d2ed06 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 1735e7e3..3dc7ebf2 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); -- cgit v1.2.3 From a88d2e313df7f5f2b781d5b14ffe0e7710018c10 Mon Sep 17 00:00:00 2001 From: Ross Williams Date: Sun, 7 Jul 2019 23:27:00 +0000 Subject: Refactor common OpenZFS sysctl access Darwin and FreeBSD export zfs kstats through the same APIs, so moving functions into a common file. --- freebsd/FreeBSDProcessList.c | 77 +++++++------------------------------------- freebsd/FreeBSDProcessList.h | 14 +++----- freebsd/Platform.c | 14 ++++---- 3 files changed, 22 insertions(+), 83 deletions(-) (limited to 'freebsd') diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 94cbaa19..1cbfdaab 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 #include @@ -21,6 +23,8 @@ in the source distribution for its full text. /*{ +#include "zfs/ZfsArcStats.h" + #include #include #include @@ -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 cf96a702..7c1b7ad4 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 #include #include @@ -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 d8d2ed06..05c0e922 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) { -- cgit v1.2.3 From e450b586368750e771746ef3e2f5a070962dfd28 Mon Sep 17 00:00:00 2001 From: Ross Williams Date: Tue, 3 Sep 2019 18:21:33 +0000 Subject: 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. --- freebsd/FreeBSDProcessList.c | 2 +- freebsd/Platform.c | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) (limited to 'freebsd') diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 1cbfdaab..fd694198 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 05c0e922..b08a508e 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) { -- cgit v1.2.3 From 613556faebd16325da8c9057c81f39a2410d803f Mon Sep 17 00:00:00 2001 From: Ross Williams Date: Tue, 3 Sep 2019 18:26:02 +0000 Subject: Support for ZFS Compressed ARC statistics --- freebsd/Platform.c | 8 ++++++++ freebsd/Platform.h | 2 ++ 2 files changed, 10 insertions(+) (limited to 'freebsd') diff --git a/freebsd/Platform.c b/freebsd/Platform.c index b08a508e..0986a3dd 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 3dc7ebf2..0268f2c6 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); -- cgit v1.2.3