----- Original Message -----
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)
---
That's kind of cluttered -- I was thinking of something like this:
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 RED_ZONE
ffffea0004de2c00 ffff8801378b0000 0 14 2 12 8
FREE / [ALLOCATED]
ffff8801378b0000 (cpu 0 cache)
[ffff8801378b08b8]
or better yet, this:
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] SLAB_RED_ZONE: 8
ffff8801378b0000 (cpu 0 cache)
[ffff8801378b08b8]
Dave
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>