[Crash-utility] [PATCH] Add support for SLAB OBJFREELIST_SLAB.

Thomas Garnier thgarnie at google.com
Thu Dec 1 22:14:11 UTC 2016


In this mode, the freelist can be an object and if the slab is full,
there is no freelist. On the next free, an object is recycled to be used
as the freelist but not clean-up. This change will go through only
known freed objects to prevent errors of wrong/corrupt freelist entries.

Related to the linux kernel commit: b03a017bebc403d40aa53a092e79b3020786537d.
---
 memory.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/memory.c b/memory.c
index 4eac413..774d090 100644
--- a/memory.c
+++ b/memory.c
@@ -9880,6 +9880,7 @@ ignore_cache(struct meminfo *si, char *name)
 #define SLAB_MAGIC_DESTROYED    0xB2F23C5AUL    /* slab has been destroyed */
 
 #define SLAB_CFLGS_BUFCTL       0x020000UL      /* bufctls in own cache */
+#define SLAB_CFLGS_OBJFREELIST  0x40000000UL    /* Freelist as an object */
 
 #define KMEM_SLAB_ADDR          (1)
 #define KMEM_BUFCTL_ADDR        (2)
@@ -12439,11 +12440,13 @@ gather_slab_free_list_percpu(struct meminfo *si)
 static void
 gather_slab_free_list_slab_overload_page(struct meminfo *si)
 {
-	int i, active;
+	int i, active, start_offset;
 	ulong obj, objnr, cnt, freelist;
 	unsigned char *ucharptr;
 	unsigned short *ushortptr;
 	unsigned int *uintptr;
+	unsigned int cache_flags, overload_active;
+	ulong slab_overload_page;
 
 	if (CRASHDEBUG(1))
 		fprintf(fp, "slab page: %lx active: %ld si->c_num: %ld\n", 
@@ -12452,12 +12455,19 @@ gather_slab_free_list_slab_overload_page(struct meminfo *si)
 	if (si->s_inuse == si->c_num )
 		return;
 
-	readmem(si->slab - OFFSET(page_lru) + OFFSET(page_freelist),
+	slab_overload_page = si->slab - OFFSET(page_lru);
+	readmem(slab_overload_page + OFFSET(page_freelist),
 		KVADDR, &freelist, sizeof(void *), "page freelist",
 		FAULT_ON_ERROR);
         readmem(freelist, KVADDR, si->freelist, 
 		si->freelist_index_size * si->c_num,
                 "freelist array", FAULT_ON_ERROR);
+	readmem(si->cache+OFFSET(kmem_cache_s_flags),
+		KVADDR, &cache_flags, sizeof(uint),
+		"kmem_cache_s flags", FAULT_ON_ERROR);
+        readmem(slab_overload_page + OFFSET(page_active),
+                KVADDR, &overload_active, sizeof(uint),
+                "active", FAULT_ON_ERROR);
 
 	BNEG(si->addrlist, sizeof(ulong) * (si->c_num+1));
 	cnt = objnr = 0;
@@ -12466,14 +12476,22 @@ gather_slab_free_list_slab_overload_page(struct meminfo *si)
 	uintptr = NULL;
 	active = si->s_inuse;
 
+	/*
+	 * On an OBJFREELIST slab, the object might have been recycled
+	 * and everything before the active count can be random data.
+	 */
+	start_offset = 0;
+	if (cache_flags & SLAB_CFLGS_OBJFREELIST)
+		start_offset = overload_active;
+
 	switch (si->freelist_index_size)
 	{
-	case 1: ucharptr = (unsigned char *)si->freelist; break;
-	case 2: ushortptr = (unsigned short *)si->freelist; break;
-	case 4: uintptr = (unsigned int *)si->freelist; break;
+	case 1: ucharptr = (unsigned char *)si->freelist + start_offset; break;
+	case 2: ushortptr = (unsigned short *)si->freelist + start_offset; break;
+	case 4: uintptr = (unsigned int *)si->freelist + start_offset; break;
 	}
 
-	for (i = 0; i < si->c_num; i++) {
+	for (i = start_offset; i < si->c_num; i++) {
 		switch (si->freelist_index_size)
 		{
 		case 1: objnr = (ulong)*ucharptr++; break;
-- 
2.8.0.rc3.226.g39d4020




More information about the Crash-utility mailing list