[PATCH] mm: introduce clear all vm events counters

From: Pintu Kumar
Date: Mon Mar 01 2021 - 05:52:03 EST


At times there is a need to regularly monitor vm counters while we
reproduce some issue, or it could be as simple as gathering some system
statistics when we run some scenario and every time we like to start from
beginning.
The current steps are:
Dump /proc/vmstat
Run some scenario
Dump /proc/vmstat again
Generate some data or graph
reboot and repeat again

So, each time we wanted to capture fresh data a reboot is required.

Thus, in this patch I introduce a way to clear/reset all vm counters to 0
without rebooting the system.
With this patch the steps can be:
Dump /proc/vmstat
Run some scenario
Dump /proc/vmstat again
Generate some data or graph
Do: echo 1 > /proc/sys/vm/clear_all_vm_events
Then repeat again

Thus, when 1 is written to this file, it resets all the vm counters present
under /proc/vmstat to its default value or zero.
The next time when you read /proc/vmstat, each node is filled with default
or current value.

There could be few other use cases where this can be useful.

Signed-off-by: Pintu Kumar <pintu@xxxxxxxxxxxxxx>
Signed-off-by: Pintu Agarwal <ping.ping@xxxxxxxxx>
---
Documentation/admin-guide/sysctl/vm.rst | 8 ++++++++
include/linux/vmstat.h | 7 +++++++
kernel/sysctl.c | 9 +++++++++
mm/vmstat.c | 26 ++++++++++++++++++++++++++
4 files changed, 50 insertions(+)

diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst
index e35a3f2..54382ab 100644
--- a/Documentation/admin-guide/sysctl/vm.rst
+++ b/Documentation/admin-guide/sysctl/vm.rst
@@ -26,6 +26,7 @@ Currently, these files are in /proc/sys/vm:

- admin_reserve_kbytes
- block_dump
+- clear_all_vm_events
- compact_memory
- compaction_proactiveness
- compact_unevictable_allowed
@@ -112,6 +113,13 @@ block_dump
block_dump enables block I/O debugging when set to a nonzero value. More
information on block I/O debugging is in Documentation/admin-guide/laptops/laptop-mode.rst.

+clear_all_vm_events
+===================
+
+When 1 is written to this file, it resets all the vm counters present under
+/proc/vmstat to its default value or zeros.
+The next time when you read /proc/vmstat, each node is filled with default or
+current value.

compact_memory
==============
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 773135f..8ab9be5 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -11,6 +11,8 @@
#include <linux/mmdebug.h>

extern int sysctl_stat_interval;
+extern int sysctl_clearvmevents_handler(struct ctl_table *table, int write,
+ void __user *buffer, size_t *length, loff_t *ppos);

#ifdef CONFIG_NUMA
#define ENABLE_NUMA_STAT 1
@@ -83,6 +85,8 @@ static inline void count_vm_events(enum vm_event_item item, long delta)

extern void all_vm_events(unsigned long *);

+extern void clear_all_vm_events(void);
+
extern void vm_events_fold_cpu(int cpu);

#else
@@ -103,6 +107,9 @@ static inline void __count_vm_events(enum vm_event_item item, long delta)
static inline void all_vm_events(unsigned long *ret)
{
}
+static inline void clear_all_vm_events(void)
+{
+}
static inline void vm_events_fold_cpu(int cpu)
{
}
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c9fbdd8..25299a4 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -200,6 +200,8 @@ static int min_extfrag_threshold;
static int max_extfrag_threshold = 1000;
#endif

+static int sysctl_clear_vm_events;
+
#endif /* CONFIG_SYSCTL */

#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_SYSCTL)
@@ -2891,6 +2893,13 @@ static struct ctl_table vm_table[] = {

#endif /* CONFIG_COMPACTION */
{
+ .procname = "clear_all_vm_events",
+ .data = &sysctl_clear_vm_events,
+ .maxlen = sizeof(int),
+ .mode = 0200,
+ .proc_handler = sysctl_clearvmevents_handler,
+ },
+ {
.procname = "min_free_kbytes",
.data = &min_free_kbytes,
.maxlen = sizeof(min_free_kbytes),
diff --git a/mm/vmstat.c b/mm/vmstat.c
index f894216..26b8f81 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -136,6 +136,32 @@ void all_vm_events(unsigned long *ret)
}
EXPORT_SYMBOL_GPL(all_vm_events);

+void clear_all_vm_events(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ struct vm_event_state *this = &per_cpu(vm_event_states, cpu);
+ int sz = NR_VM_EVENT_ITEMS * sizeof(unsigned long);
+
+ memset(this->event, 0, sz);
+ }
+}
+EXPORT_SYMBOL_GPL(clear_all_vm_events);
+
+/*
+ * This is the node to reset all vm events in /proc/vmstat
+ * via /proc/sys/vm/clear_all_vm_events
+ */
+int sysctl_clearvmevents_handler(struct ctl_table *table, int write,
+ void __user *buffer, size_t *length, loff_t *ppos)
+{
+ if (write)
+ clear_all_vm_events();
+
+ return 0;
+}
+
/*
* Fold the foreign cpu events into our own.
*
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.