[Devel,RFC] slub: add "pages" attribute

Submitted by Stanislav Kinsburskiy on July 27, 2017, 4:11 p.m.

Details

Message ID 20170727161111.5593.60334.stgit@localhost.localdomain
State New
Series "slub: add "pages" attribute"
Headers show

Commit Message

Stanislav Kinsburskiy July 27, 2017, 4:11 p.m.
It prints page addresses in slub.
Useful for search of leaked objects (say, I found leaked dentry with this after CT stop).

Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
---
 mm/slub.c |   35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/mm/slub.c b/mm/slub.c
index 96a7aba..91a4de1 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -4559,7 +4559,8 @@  enum slab_stat_type {
 	SL_PARTIAL,		/* Only partially allocated slabs */
 	SL_CPU,			/* Only slabs used for cpu caches */
 	SL_OBJECTS,		/* Determine allocated objects not slabs */
-	SL_TOTAL		/* Determine object capacity not slabs */
+	SL_TOTAL,		/* Determine object capacity not slabs */
+	SL_PAGES
 };
 
 #define SO_ALL		(1 << SL_ALL)
@@ -4567,6 +4568,20 @@  enum slab_stat_type {
 #define SO_CPU		(1 << SL_CPU)
 #define SO_OBJECTS	(1 << SL_OBJECTS)
 #define SO_TOTAL	(1 << SL_TOTAL)
+#define SO_PAGES	(1 << SL_PAGES)
+
+static unsigned long print_pages(struct kmem_cache_node *n, char *buf)
+{
+	unsigned long flags;
+	unsigned long x = 0;
+	struct page *page;
+
+	spin_lock_irqsave(&n->list_lock, flags);
+	list_for_each_entry(page, &n->partial, lru)
+		x += sprintf(buf + x, "%p\n", page_address(page));
+	spin_unlock_irqrestore(&n->list_lock, flags);
+	return x;
+}
 
 static ssize_t show_slab_objects(struct kmem_cache *s,
 			    char *buf, unsigned long flags)
@@ -4582,6 +4597,17 @@  static ssize_t show_slab_objects(struct kmem_cache *s,
 		return -ENOMEM;
 	per_cpu = nodes + nr_node_ids;
 
+	if (flags & SO_PAGES) {
+		x = 0;
+		for_each_node_state(node, N_NORMAL_MEMORY) {
+			struct kmem_cache_node *n = get_node(s, node);
+
+			x += print_pages(n, buf + x);
+		}
+		kfree(nodes);
+		return x;
+	}
+
 	if (flags & SO_CPU) {
 		int cpu;
 
@@ -4831,6 +4857,12 @@  static ssize_t objects_partial_show(struct kmem_cache *s, char *buf)
 }
 SLAB_ATTR_RO(objects_partial);
 
+static ssize_t pages_show(struct kmem_cache *s, char *buf)
+{
+	return show_slab_objects(s, buf, SO_PAGES);
+}
+SLAB_ATTR_RO(pages);
+
 static ssize_t slabs_cpu_partial_show(struct kmem_cache *s, char *buf)
 {
 	int objects = 0;
@@ -5257,6 +5289,7 @@  static struct attribute *slab_attrs[] = {
 	&failslab_attr.attr,
 #endif
 
+	&pages_attr.attr,
 	NULL
 };