[PATCH 09/10] mm/oom_debug: Add Enhanced Slab Print Information

Edward Chron
2019-08-26T19:37:20Z

Add OOM Debug code that prints additional detailed information about each
slab entry that has been selected for printing. The information is
displayed for each slab enrty selected for print. The extra information
is helpful for root cause identification and problem analysis.

Configuring Enhanced Process Print Information
----------------------------------------------
The Kernel configuration option that defines this option is
DEBUG_OOM_ENHANCED_SLAB_PRINT. This additional code is dependent on the
OOM Debug option DEBUG_OOM_SLAB_SELECT_PRINT which adds code to allow
processes that are considered for OOM kill to be selectively printed,
only printing processes that use a specified minimum amount of memory.

The kernel configuration entry for this option can be found in the
config file at: Kernel hacking, Memory Debugging, Debug OOM,
Debug OOM Process Selection, Debug OOM Enhanced Process Print.
Both Debug OOM Process Selection and Debug OOM Enhanced Process Print
entries must be selected.

Dynamic disable or re-enable this OOM Debug option
--------------------------------------------------
This option may be disabled or re-enabled using the debugfs entry for
this OOM debug option. The debugfs file to enable this entry is found at:
/sys/kernel/debug/oom/process_enhanced_print_enabled where the enabled
file's value determines whether the facility is enabled or disabled.
A value of 1 is enabled (default) and a value of 0 is disabled.
When configured the default setting is set to enabled.

Content and format of slab entry messages
-----------------------------------------
In addition to the Used and Total space (in KiB) fields that are
displayed by the standard Linux OOM slab reporting code the enhanced
entries include: active objects, total objects, object and align size
(both in bytes), objects per slab, pages per slab, active slabs,
total slabs and the slab name (located at the end, easier to read).

Sample Output
-------------
Sample oom report message header and output slab entry message:

Aug 13 18:52:47 mysrvr kernel: UsedKiB TotalKiB ActiveObj TotalObj
ObjSize AlignSize Objs/Slab Pgs/Slab ActiveSlab TotalSlab Slab_Name

Aug 13 18:52:47 mysrvr kernel: 403 412 1613 1648
224 256 16 1 103 103 skbuff_head..

Signed-off-by: Edward Chron <echron@arista.com>
---
mm/Kconfig.debug | 15 +++++++++++++++
mm/oom_kill_debug.c | 15 +++++++++++++++
mm/oom_kill_debug.h | 3 +++
mm/slab_common.c | 29 +++++++++++++++++++++++++++++
4 files changed, 62 insertions(+)

diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
index 68873e26afe1..4414e46f72c6 100644
--- a/mm/Kconfig.debug
+++ b/mm/Kconfig.debug
@@ -244,6 +244,21 @@ config DEBUG_OOM_SLAB_SELECT_ALWAYS_PRINT

If unsure, say N.

+config DEBUG_OOM_ENHANCED_SLAB_PRINT
+ bool "Debug OOM Enhanced Slab Print"
+ depends on DEBUG_OOM_SLAB_SELECT_PRINT
+ help
+ Each OOM slab entry printed includes slab entry information
+ about it's memory usage. Memory usage is specified in KiB (KB)
+ and includes the following fields:
+
+ If the option is configured it is enabled/disabled by setting
+ the value of the file entry in the debugfs OOM interface at:
+ /sys/kernel/debug/oom/process_enhanced_print_enabled
+ A value of 1 is enabled (default) and a value of 0 is disabled.
+
+ If unsure, say N.
+
config DEBUG_OOM_VMALLOC_SELECT_PRINT
bool "Debug OOM Select Vmallocs Print"
depends on DEBUG_OOM
diff --git a/mm/oom_kill_debug.c b/mm/oom_kill_debug.c
index 13f1d1c25a67..ad937b3d59f3 100644
--- a/mm/oom_kill_debug.c
+++ b/mm/oom_kill_debug.c
@@ -244,6 +244,12 @@ static struct oom_debug_option oom_debug_options_table[] = {
.option_name = "slab_select_always_print_",
.support_tpercent = false,
},
+#endif
+#ifdef CONFIG_DEBUG_OOM_ENHANCED_SLAB_PRINT
+ {
+ .option_name = "slab_enhanced_print_",
+ .support_tpercent = false,
+ },
#endif
{}
};
@@ -273,6 +279,9 @@ enum oom_debug_options_index {
#endif
#ifdef CONFIG_DEBUG_OOM_SLAB_SELECT_ALWAYS_PRINT
SLAB_ALWAYS_STATE,
+#endif
+#ifdef CONFIG_DEBUG_OOM_ENHANCED_SLAB_PRINT
+ ENHANCED_SLAB_STATE,
#endif
OUT_OF_BOUNDS
};
@@ -350,6 +359,12 @@ bool oom_kill_debug_select_slabs_always_print_enabled(void)
return oom_kill_debug_enabled(SLAB_ALWAYS_STATE);
}
#endif
+#ifdef CONFIG_DEBUG_OOM_ENHANCED_SLAB_PRINT
+bool oom_kill_debug_enhanced_slab_print_information_enabled(void)
+{
+ return oom_kill_debug_enabled(ENHANCED_SLAB_STATE);
+}
+#endif

#ifdef CONFIG_DEBUG_OOM_SYSTEM_STATE
/*
diff --git a/mm/oom_kill_debug.h b/mm/oom_kill_debug.h
index bce740573063..a39bc275980e 100644
--- a/mm/oom_kill_debug.h
+++ b/mm/oom_kill_debug.h
@@ -18,6 +18,9 @@ extern bool oom_kill_debug_unreclaimable_slabs_print(void);
#ifdef CONFIG_DEBUG_OOM_SLAB_SELECT_ALWAYS_PRINT
extern bool oom_kill_debug_select_slabs_always_print_enabled(void);
#endif
+#ifdef CONFIG_DEBUG_OOM_ENHANCED_SLAB_PRINT
+extern bool oom_kill_debug_enhanced_slab_print_information_enabled(void);
+#endif

extern u32 oom_kill_debug_oom_event_is(void);
extern u32 oom_kill_debug_event(void);
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 9ddc95040b60..c6e17e5c6c9d 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -28,6 +28,10 @@

#include "slab.h"

+#ifdef CONFIG_DEBUG_OOM_ENHANCED_SLAB_PRINT
+#include "oom_kill_debug.h"
+#endif
+
enum slab_state slab_state;
LIST_HEAD(slab_caches);
DEFINE_MUTEX(slab_mutex);
@@ -1450,15 +1454,40 @@ void dump_unreclaimable_slab(void)
mutex_unlock(&slab_mutex);
}

+#ifdef CONFIG_DEBUG_OOM_ENHANCED_SLAB_PRINT
+static void oom_debug_slab_enhanced_print(struct slabinfo *psi,
+ struct kmem_cache *pkc)
+{
+ pr_info("%10lu %10lu %10lu %10lu %9u %9u %9u %8u %10lu %10lu %s\n",
+ (psi->active_objs * pkc->size) / 1024,
+ (psi->num_objs * pkc->size) / 1024, psi->active_objs,
+ psi->num_objs, pkc->object_size, pkc->size,
+ psi->objects_per_slab, (1 << psi->cache_order),
+ psi->active_slabs, psi->num_slabs, cache_name(pkc));
+}
+#endif
+
#ifdef CONFIG_DEBUG_OOM_SLAB_SELECT_PRINT
static void oom_debug_slab_header_print(void)
{
pr_info("Unreclaimable slab info:\n");
+#ifdef CONFIG_DEBUG_OOM_ENHANCED_SLAB_PRINT
+ if (oom_kill_debug_enhanced_slab_print_information_enabled()) {
+ pr_info(" UsedKiB TotalKiB ActiveObj TotalObj ObjSize AlignSize Objs/Slab Pgs/Slab ActiveSlab TotalSlab Slab_Name");
+ return;
+ }
+#endif
pr_info("Name Used Total\n");
}

static void oom_debug_slab_print(struct slabinfo *psi, struct kmem_cache *pkc)
{
+#ifdef CONFIG_DEBUG_OOM_ENHANCED_SLAB_PRINT
+ if (oom_kill_debug_enhanced_slab_print_information_enabled()) {
+ oom_debug_slab_enhanced_print(psi, pkc);
+ return;
+ }
+#endif
pr_info("%-17s %10luKB %10luKB\n", cache_name(pkc),
(psi->active_objs * pkc->size) / 1024,
(psi->num_objs * pkc->size) / 1024);
--
2.20.1