----- Original Message -----
Dave Anderson <anderson(a)redhat.com> writes:
>> I see what you say. However, my usual usage of kmem is to get the data
>> address of object (I was thinking the most users are same usage).
>>
>> crash> kmem <pointer in stack>
>> info for data address
>>
>> copy & paste <data address>
>> crash> p *(struct inode *)<data address>
>
> Why not copy-and-paste the address from <pointer in stack>? Or use "bt
> -FF"
> to get the kmem cache type, and skip using "kmem" entirely? ;-)
Yes, bt -FF helps much. However, the pointer in stack is address in
middle of object data in many times.
E.g. for ext4_inode_cache, "struct address_space *" is in stack. But
actual slab object is inode->i_mapping == ext4_inode_info.vfs_inode.i_data.
Or functions takes member of object, e.g., &object->list. for (p = vaddr; p
< vaddr + objects * si->size; p += si->size) {
hq_open();
is_free = FALSE;
/* Search an object on both of freelist and cpu_freelist */
ulong lists[] = { freelist, cpu_freelist, };
for (i = 0; i < sizeof(lists) / sizeof(lists[0]); i++) {
for (is_free = 0, q = lists[i]; q;
q = get_freepointer(si, (void *)q)) {
if (q == BADADDR) {
hq_close();
return FALSE;
}
if (q & PAGE_MAPPING_ANON)
break;
if (p == q) {
is_free = TRUE;
goto found_object;
}
if (!hq_enter(q)) {
hq_close();
error(INFO, "%s: slab: %lx duplicate freelist
object: %lx\n",
si->curname, si->slab, q);
return FALSE;
}
}
}
found_object:
If there is easy way to get the object address from the field of object
address, it would be what I want.
OK, I understand. Let me work on a new "set redzone on/off" environment
variable that can be toggled on-and-off during runtime.
But I believe I see a problem in do_slab_slub(). When it is checking for free
objects to display as FREE / [ALLOCATED], it will never find it in 4.6+ kernels
with a red_left_pad. Note below, when it checks whether (p == q), the "q"
address
is the "shifted" address seen by the kmalloc() caller, and will never match the
base object address "p", so "is_free" never gets set:
for (p = vaddr; p < vaddr + objects * si->size; p += si->size) {
hq_open();
is_free = FALSE;
/* Search an object on both of freelist and cpu_freelist */
ulong lists[] = { freelist, cpu_freelist, };
for (i = 0; i < sizeof(lists) / sizeof(lists[0]); i++) {
for (is_free = 0, q = lists[i]; q;
q = get_freepointer(si, (void *)q)) {
if (q == BADADDR) {
hq_close();
return FALSE;
}
if (q & PAGE_MAPPING_ANON)
break;
=== never can match ===> if (p == q) {
is_free = TRUE;
goto found_object;
}
if (!hq_enter(q)) {
hq_close();
error(INFO, "%s: slab: %lx duplicate freelist
object: %lx\n",
si->curname, si->slab, q);
return FALSE;
}
}
}
found_object:
...
Do you agree?
Dave