Dave Anderson <anderson(a)redhat.com> writes:
Right, but the question is whether it makes more sense to display
the
full slab object address containing the red-zone buffer or not. When
debugging slab corruption for example, I would argue it's more relevant
to show the full object address. For example, if you want to follow
that linked list from kmem_cache_cpu.freelist pointer, if I'm not mistaken
the next pointer in each object will be located in the first word of the
object. Anyway, that is more in line with the original intent of kmem -S
command, even in the case when slub debug is turned on.
On the other hand, in your example above, you are presuming the address
shown should be what the kmalloc() or kmem_cache_alloc() caller receives,
which I agree has merit. But consider that you can enter any address
within an object, and get the same result.
I wonder whether there can be a compromise, such that in the case of slub
debug, there could be extra information in the output display that indicates
that the object contains a red zone buffer?
I see. Then how about this? Adding additional information "(data %lx)".
With red_left_zone (object addr < data addr),
crash> kmem ffffea0004de2c00
CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE
ffff88013a719900 ext4_inode_cache 2200 730 742 53 32k
SLAB MEMORY NODE TOTAL ALLOCATED FREE
ffffea0004de2c00 ffff8801378b0000 0 14 2 12
FREE / [ALLOCATED]
ffff8801378b0000 (data ffff8801378b0008, cpu 0 cache)
[ffff8801378b08b8] (data ffff8801378b08c0)
Without red_left_zone (object addr == data addr),
crash> kmem ffffea0004e5be00
CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE
ffff88013a6f2f00 ext4_inode_cache 2200 730 742 53 32k
SLAB MEMORY NODE TOTAL ALLOCATED FREE
ffffea0004e5be00 ffff8801396f8000 0 14 2 12
FREE / [ALLOCATED]
ffff8801396f8000 (cpu 0 cache)
[ffff8801396f88a0]
Thanks.
---
Fix for "kmem <addr>" for kernels configured with CONFIG_SLUB and
SLAB_RED_ZONE.
If SLAB_RED_ZONE is enabled, slub adds guard zone of sizeof(void *)
onto left of object on v4.6 or later.
Without this fix, like following SUPERBLK and [allocate addr] has
difference.
crash> mount
MOUNT SUPERBLK TYPE DEVNAME DIRNAME
ffff88013ae58040 ffff88013ac35698 rootfs rootfs /
[...]
crash> kmem ffff88013ac35698
CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE
ffff88013ac05bc0 kmalloc-4096 4096 118 126 18 32k
SLAB MEMORY NODE TOTAL ALLOCATED FREE
ffffea0004eb0c00 ffff88013ac30000 0 7 7 0
FREE / [ALLOCATED]
[ffff88013ac35690]
[...]
This left pad for RED_ZONE may confuses the user, so this adds
additional information, like following if data_start != object_start.
crash> kmem ffffea0004de2c00
CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE
ffff88013a719900 ext4_inode_cache 2200 730 742 53 32k
SLAB MEMORY NODE TOTAL ALLOCATED FREE
ffffea0004de2c00 ffff8801378b0000 0 14 2 12
FREE / [ALLOCATED]
ffff8801378b0000 (data ffff8801378b0008, cpu 0 cache)
[ffff8801378b08b8] (data ffff8801378b08c0)
---
defs.h | 1 +
memory.c | 28 ++++++++++++++++++++++++----
symbols.c | 2 ++
3 files changed, 27 insertions(+), 4 deletions(-)
diff -puN memory.c~slub-red_zone-fix memory.c
--- crash-64/memory.c~slub-red_zone-fix 2017-02-02 13:01:54.263337316 +0900
+++ crash-64-hirofumi/memory.c 2017-02-03 04:48:24.692595383 +0900
@@ -723,6 +723,7 @@ vm_init(void)
MEMBER_OFFSET_INIT(kmem_cache_node, "kmem_cache", "node");
MEMBER_OFFSET_INIT(kmem_cache_cpu_slab, "kmem_cache", "cpu_slab");
MEMBER_OFFSET_INIT(kmem_cache_list, "kmem_cache", "list");
+ MEMBER_OFFSET_INIT(kmem_cache_red_left_pad, "kmem_cache",
"red_left_pad");
MEMBER_OFFSET_INIT(kmem_cache_name, "kmem_cache", "name");
MEMBER_OFFSET_INIT(kmem_cache_flags, "kmem_cache", "flags");
MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu",
"freelist");
@@ -18354,7 +18355,7 @@ do_slab_slub(struct meminfo *si, int ver
physaddr_t paddr;
ulong vaddr;
ushort inuse, objects;
- ulong freelist, cpu_freelist, cpu_slab_ptr;
+ ulong freelist, cpu_freelist, cpu_slab_ptr, red_left_pad;
int i, free_objects, cpu_slab, is_free, node;
ulong p, q;
@@ -18442,6 +18443,13 @@ do_slab_slub(struct meminfo *si, int ver
fprintf(fp, "< SLUB: free list END (%d found) >\n", i);
}
+ red_left_pad = 0;
+ if (VALID_MEMBER(kmem_cache_red_left_pad)) {
+#define SLAB_RED_ZONE 0x00000400UL
+ ulong flags = ULONG(si->cache_buf + OFFSET(kmem_cache_flags));
+ if (flags & SLAB_RED_ZONE)
+ red_left_pad = ULONG(si->cache_buf + OFFSET(kmem_cache_red_left_pad));
+ }
for (p = vaddr; p < vaddr + objects * si->size; p += si->size) {
hq_open();
is_free = FALSE;
@@ -18482,9 +18490,21 @@ do_slab_slub(struct meminfo *si, int ver
fprintf(fp, " %s%lx%s",
is_free ? " " : "[",
- p, is_free ? " " : "]");
- if (is_free && (cpu_slab >= 0))
- fprintf(fp, "(cpu %d cache)", cpu_slab);
+ p, is_free ? " " : "]");
+ if (red_left_pad || (is_free && (cpu_slab >= 0))) {
+ int need_comma = 0;
+ fprintf(fp, " (");
+ if (red_left_pad) {
+ fprintf(fp, "data %lx", p + red_left_pad);
+ need_comma = 1;
+ }
+ if (is_free && (cpu_slab >= 0)) {
+ if (need_comma)
+ fprintf(fp, ", ");
+ fprintf(fp, "cpu %d cache", cpu_slab);
+ }
+ fprintf(fp, ")");
+ }
fprintf(fp, "\n");
}
diff -puN defs.h~slub-red_zone-fix defs.h
--- crash-64/defs.h~slub-red_zone-fix 2017-02-02 13:01:54.264337322 +0900
+++ crash-64-hirofumi/defs.h 2017-02-03 03:26:39.211648619 +0900
@@ -1696,6 +1696,7 @@ struct offset_table {
long kmem_cache_align;
long kmem_cache_name;
long kmem_cache_list;
+ long kmem_cache_red_left_pad;
long kmem_cache_node;
long kmem_cache_cpu_slab;
long page_inuse;
diff -puN symbols.c~slub-red_zone-fix symbols.c
--- crash-64/symbols.c~slub-red_zone-fix 2017-02-02 13:01:54.264337322 +0900
+++ crash-64-hirofumi/symbols.c 2017-02-03 03:26:39.213648633 +0900
@@ -9330,6 +9330,8 @@ dump_offset_table(char *spec, ulong make
OFFSET(kmem_cache_name));
fprintf(fp, " kmem_cache_list: %ld\n",
OFFSET(kmem_cache_list));
+ fprintf(fp, " kmem_cache_red_left_pad: %ld\n",
+ OFFSET(kmem_cache_red_left_pad));
fprintf(fp, " kmem_cache_node: %ld\n",
OFFSET(kmem_cache_node));
fprintf(fp, " kmem_cache_cpu_slab: %ld\n",
_
--
OGAWA Hirofumi <hirofumi(a)mail.parknet.co.jp>