Ming Zhang wrote:
On Wed, 2008-03-05 at 15:57 -0500, Dave Anderson wrote:
Ming Zhang wrote:
Hi All
I wonder if it possible to have this feature - user defined symbol.
for example, define inode1 = 0x1234
then in all place has this 0x1234 in bt or rd command, show inode1
instead of numeric value,
This should be very helpful when these value pop up in a haystack of
numeric values...
Thanks
Why not just pipe the relevant command to grep to pin-point the
locations of the value you're tracking?
I know it's tempting, but creating a crash command/option for
specific kernel-debug cases would soon become overwhelming.
So I'm not particulary excited about this suggestion; maybe
others would be...
understood.
BTW, as you requested earler, I've got the "kmem -s <address>"
output changed such that the base address of the object is shown
instead of the <address> argument which may be offset into the
slab object. With CONFIG_SLUB kernels, that's how it currently
works, although I'm also fixing "kmem -S" and "kmem -s address"
failures to handle some 2.6.25 kernel changes to SLUB object
free-list tracking. And there still appears to be more
SLUB-related churn being proposed on LKML on the horizon.
cool. where i can get this updated code?
Dave
Remove the previous patch I sent you and apply the attached one.
Dave
Index: memory.c
===================================================================
RCS file: /nfs/projects/cvs/crash/memory.c,v
retrieving revision 1.167
retrieving revision 1.170
diff -u -r1.167 -r1.170
--- memory.c 11 Jan 2008 16:59:46 -0000 1.167
+++ memory.c 5 Mar 2008 20:32:33 -0000 1.170
@@ -68,6 +68,7 @@
ulong addr;
ulong size;
} *vmlist;
+ ulong container;
};
static char *memtype_string(int, int);
@@ -96,8 +97,8 @@
static void dump_kmem_cache_slub(struct meminfo *);
static void dump_kmem_cache_info_v2(struct meminfo *);
static void kmem_cache_list_slub(void);
-static ulong get_cpu_slab_ptr(struct meminfo *, int);
-static char *vaddr_to_kmem_cache(ulong, char *);
+static ulong get_cpu_slab_ptr(struct meminfo *, int, ulong *);
+static char *vaddr_to_kmem_cache(ulong, char *, int);
static ulong vaddr_to_slab(ulong);
static void do_slab_chain(int, struct meminfo *);
static void do_slab_chain_percpu_v1(long, struct meminfo *);
@@ -177,6 +178,7 @@
static ulong compound_head(ulong);
static long count_partial(ulong);
static ulong get_freepointer(struct meminfo *, void *);
+static int count_free_objects(struct meminfo *, ulong);
char *is_slab_page(struct meminfo *, char *);
static void do_node_lists_slub(struct meminfo *, ulong, int);
@@ -195,6 +197,7 @@
#define UDECIMAL (0x200)
#define ASCII_ENDLINE (0x400)
#define NO_ASCII (0x800)
+#define SLAB_CACHE (0x1000)
static ulong DISPLAY_DEFAULT;
@@ -869,7 +872,7 @@
memtype = KVADDR;
count = -1;
- while ((c = getopt(argcnt, args, "xme:pfudDuso:81:3:6:")) != EOF) {
+ while ((c = getopt(argcnt, args, "xme:pfudDusSo:81:3:6:")) != EOF) {
switch(c)
{
case '8':
@@ -915,9 +918,12 @@
break;
case 's':
- if (flag & DISPLAY_DEFAULT)
+ case 'S':
+ if (flag & DISPLAY_DEFAULT) {
flag |= SYMBOLIC;
- else {
+ if (c == 'S')
+ flag |= SLAB_CACHE;
+ } else {
error(INFO,
"-s only allowed with %d-bit display\n",
DISPLAY_DEFAULT == DISPLAY_64 ?
@@ -1086,6 +1092,7 @@
char ch;
int linelen;
char buf[BUFSIZE];
+ char slab[BUFSIZE];
int ascii_start;
char *hex_64_fmt = BITS32() ? "%.*llx " : "%.*lx ";
char *dec_64_fmt = BITS32() ? "%12lld " : "%15ld ";
@@ -1185,6 +1192,14 @@
linelen += strlen(buf)+1;
break;
}
+ if ((flag & SLAB_CACHE) &&
+ vaddr_to_kmem_cache(mem.u64, slab,
+ !VERBOSE)) {
+ sprintf(buf, "[%s]", slab);
+ fprintf(fp, "%-16s ", buf);
+ linelen += strlen(buf)+1;
+ break;
+ }
}
if (flag & HEXADECIMAL) {
fprintf(fp, hex_64_fmt, LONG_LONG_PRLEN,
@@ -1211,6 +1226,15 @@
linelen += strlen(buf)+1;
break;
}
+ if ((flag & SLAB_CACHE) &&
+ vaddr_to_kmem_cache(mem.u32, slab,
+ !VERBOSE)) {
+ sprintf(buf, "[%s]", slab);
+ fprintf(fp, INT_PRLEN == 16 ?
+ "%-16s " : "%-8s ", buf);
+ linelen += strlen(buf)+1;
+ break;
+ }
}
if (flag & HEXADECIMAL) {
fprintf(fp, "%.*x ", INT_PRLEN, mem.u32 );
@@ -7141,22 +7165,25 @@
* name of the cache to which it belongs.
*/
static char *
-vaddr_to_kmem_cache(ulong vaddr, char *buf)
+vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose)
{
physaddr_t paddr;
ulong page;
ulong cache;
if (!kvtop(NULL, vaddr, &paddr, 0)) {
- error(WARNING,
- "cannot make virtual-to-physical translation: %lx\n",
- vaddr);
+ if (verbose)
+ error(WARNING,
+ "cannot make virtual-to-physical translation: %lx\n",
+ vaddr);
return NULL;
}
if (!phys_to_page(paddr, &page)) {
- error(WARNING, "cannot find mem_map page for address: %lx\n",
- vaddr);
+ if (verbose)
+ error(WARNING,
+ "cannot find mem_map page for address: %lx\n",
+ vaddr);
return NULL;
}
@@ -7665,7 +7692,7 @@
si->cache = cache_cache = symbol_value("cache_cache");
if (si->flags & ADDRESS_SPECIFIED) {
- if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf))) {
+ if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) {
error(INFO,
"address is not allocated in slab subsystem: %lx\n",
si->spec_addr);
@@ -7791,12 +7818,14 @@
case KMEM_OBJECT_ADDR_FREE:
fprintf(fp, free_inuse_hdr);
fprintf(fp, " %lx\n",
+ si->container ? si->container :
(ulong)si->spec_addr);
break;
case KMEM_OBJECT_ADDR_INUSE:
fprintf(fp, free_inuse_hdr);
fprintf(fp, " [%lx]\n",
+ si->container ? si->container :
(ulong)si->spec_addr);
break;
}
@@ -7869,7 +7898,7 @@
si->cache = cache_cache = symbol_value("cache_cache");
if (si->flags & ADDRESS_SPECIFIED) {
- if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf))) {
+ if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) {
error(INFO,
"address is not allocated in slab subsystem: %lx\n",
si->spec_addr);
@@ -7996,12 +8025,14 @@
case KMEM_OBJECT_ADDR_FREE:
fprintf(fp, free_inuse_hdr);
fprintf(fp, " %lx\n",
+ si->container ? si->container :
(ulong)si->spec_addr);
break;
case KMEM_OBJECT_ADDR_INUSE:
fprintf(fp, free_inuse_hdr);
- fprintf(fp, " [%lx]\n",
+ fprintf(fp, " [%lx]\n",
+ si->container ? si->container :
(ulong)si->spec_addr);
break;
@@ -8009,6 +8040,7 @@
fprintf(fp, free_inuse_hdr);
fprintf(fp,
" %lx (cpu %d cache)\n",
+ si->container ? si->container :
(ulong)si->spec_addr, si->cpu);
break;
}
@@ -8091,7 +8123,7 @@
cache_end = symbol_value("cache_chain");
if (si->flags & ADDRESS_SPECIFIED) {
- if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf))) {
+ if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf, VERBOSE))) {
error(INFO,
"address is not allocated in slab subsystem: %lx\n",
si->spec_addr);
@@ -8225,12 +8257,14 @@
case KMEM_OBJECT_ADDR_FREE:
fprintf(fp, free_inuse_hdr);
fprintf(fp, " %lx\n",
+ si->container ? si->container :
(ulong)si->spec_addr);
break;
case KMEM_OBJECT_ADDR_INUSE:
fprintf(fp, free_inuse_hdr);
fprintf(fp, " [%lx]\n",
+ si->container ? si->container :
(ulong)si->spec_addr);
break;
@@ -8238,6 +8272,7 @@
fprintf(fp, free_inuse_hdr);
fprintf(fp,
" %lx (cpu %d cache)\n",
+ si->container ? si->container :
(ulong)si->spec_addr, si->cpu);
break;
@@ -8245,6 +8280,7 @@
fprintf(fp, free_inuse_hdr);
fprintf(fp,
" %lx (shared cache)\n",
+ si->container ? si->container :
(ulong)si->spec_addr);
break;
}
@@ -9638,6 +9674,7 @@
if (INOBJECT(si->spec_addr, obj)) { \
si->found = \
KMEM_OBJECT_ADDR_FREE; \
+ si->container = obj; \
return; \
} \
} \
@@ -9649,6 +9686,7 @@
if (INOBJECT(si->spec_addr, obj)) { \
si->found = \
KMEM_OBJECT_ADDR_INUSE; \
+ si->container = obj; \
return; \
} \
} \
@@ -9670,6 +9708,7 @@
cnt = 0;
expected = si->s_inuse;
+ si->container = 0;
if (CRASHDEBUG(1))
for (i = 0; i < si->c_num; i++) {
@@ -9745,6 +9784,7 @@
cnt = 0;
expected = si->s_inuse;
+ si->container = 0;
if (CRASHDEBUG(1))
for (i = 0; i < si->c_num; i++) {
@@ -9796,6 +9836,7 @@
if (INOBJECT(si->spec_addr, obj)) {
si->found =
KMEM_OBJECT_ADDR_FREE;
+ si->container = obj;
return;
}
}
@@ -9808,6 +9849,7 @@
if (INOBJECT(si->spec_addr, obj)) {
si->found =
KMEM_OBJECT_ADDR_CACHED;
+ si->container = obj;
return;
}
}
@@ -9819,6 +9861,7 @@
if (INOBJECT(si->spec_addr, obj)) {
si->found =
KMEM_OBJECT_ADDR_SHARED;
+ si->container = obj;
return;
}
}
@@ -9830,6 +9873,7 @@
if (INOBJECT(si->spec_addr, obj)) {
si->found =
KMEM_OBJECT_ADDR_INUSE;
+ si->container = obj;
return;
}
}
@@ -10270,7 +10314,7 @@
*/
mi->flags = orig_flags;
mi->retval = 0;
- if ((vaddr != BADADDR) && vaddr_to_kmem_cache(vaddr, buf)) {
+ if ((vaddr != BADADDR) && vaddr_to_kmem_cache(vaddr, buf, VERBOSE)) {
BZERO(&tmp_meminfo, sizeof(struct meminfo));
tmp_meminfo.spec_addr = vaddr;
tmp_meminfo.memtype = KVADDR;
@@ -13353,7 +13397,8 @@
if ((p1 = is_slab_page(si, kbuf))) {
si->flags |= VERBOSE;
si->slab = (ulong)si->spec_addr;
- } else if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf))) {
+ } else if (!(p1 = vaddr_to_kmem_cache(si->spec_addr, kbuf,
+ VERBOSE))) {
error(INFO,
"address is not allocated in slab subsystem: %lx\n",
si->spec_addr);
@@ -13453,7 +13498,7 @@
total_slabs = total_objects = 0;
for (i = 0; i < kt->cpus; i++) {
- cpu_slab_ptr = get_cpu_slab_ptr(si, i);
+ cpu_slab_ptr = get_cpu_slab_ptr(si, i, NULL);
if (!cpu_slab_ptr)
continue;
@@ -13558,7 +13603,7 @@
per_cpu = (ulong *)GETBUF(sizeof(ulong) * vt->numnodes);
for (i = 0; i < kt->cpus; i++) {
- cpu_slab_ptr = get_cpu_slab_ptr(si, i);
+ cpu_slab_ptr = get_cpu_slab_ptr(si, i, NULL);
fprintf(fp, "CPU %d SLAB:\n%s", i,
cpu_slab_ptr ? "" : " (empty)\n");
@@ -13626,7 +13671,7 @@
physaddr_t paddr;
ulong vaddr;
ushort inuse;
- ulong freelist, cpu_slab_ptr;
+ ulong freelist, cpu_freelist, cpu_slab_ptr;
int i, cpu_slab, is_free, node;
ulong p, q;
@@ -13657,30 +13702,63 @@
sizeof(void *), "page.freelist", RETURN_ON_ERROR))
return;
- DUMP_SLAB_INFO_SLUB();
-
- if (!verbose)
+ if (!verbose) {
+ DUMP_SLAB_INFO_SLUB();
return;
+ }
for (i = 0, cpu_slab = -1; i < kt->cpus; i++) {
- cpu_slab_ptr = get_cpu_slab_ptr(si, i);
+ cpu_slab_ptr = get_cpu_slab_ptr(si, i, &cpu_freelist);
if (!cpu_slab_ptr)
continue;
if (cpu_slab_ptr == si->slab) {
cpu_slab = i;
+ /*
+ * Later slub scheme uses the per-cpu freelist
+ * and keeps page->inuse maxed out, so count
+ * the free objects by hand.
+ */
+ if (cpu_freelist)
+ freelist = cpu_freelist;
+ if ((si->objects - inuse) == 0)
+ inuse = si->objects -
+ count_free_objects(si, freelist);
break;
}
}
+ DUMP_SLAB_INFO_SLUB();
+
fprintf(fp, " %s", free_inuse_hdr);
+#define PAGE_MAPPING_ANON 1
+
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "< SLUB: free list START: >\n");
+ i = 0;
+ for (q = freelist; q; q = get_freepointer(si, (void *)q)) {
+ if (q & PAGE_MAPPING_ANON) {
+ fprintf(fp,
+ "< SLUB: free list END: %lx (%d found) >\n",
+ q, i);
+ break;
+ }
+ fprintf(fp, " %lx\n", q);
+ i++;
+ }
+ if (!q)
+ fprintf(fp, "< SLUB: free list END (%d found) >\n", i);
+ }
+
for (p = vaddr; p < vaddr + si->objects * si->size; p += si->size) {
is_free = FALSE;
for (is_free = 0, q = freelist; q;
q = get_freepointer(si, (void *)q)) {
if (q == BADADDR)
return;
+ if (q & PAGE_MAPPING_ANON)
+ break;
if (p == q) {
is_free = TRUE;
break;
@@ -13705,6 +13783,23 @@
}
}
+static int
+count_free_objects(struct meminfo *si, ulong freelist)
+{
+ int c;
+ ulong q;
+
+ c = 0;
+ for (q = freelist; q; q = get_freepointer(si, (void *)q)) {
+ if (q & PAGE_MAPPING_ANON)
+ break;
+ c++;
+ }
+
+ return c;
+}
+
+
static ulong
get_freepointer(struct meminfo *si, void *object)
{
@@ -13938,7 +14033,7 @@
RETURN_ON_ERROR|QUIET))
return NULL;
- if (!(page_flags & vt->PG_slab))
+ if (!(page_flags & (1 << vt->PG_slab)))
return NULL;
if (!readmem(si->spec_addr + OFFSET(page_slab), KVADDR,
@@ -13976,12 +14071,16 @@
/*
* Figure out which of the kmem_cache.cpu_slab declarations
* is used by this kernel, and return a pointer to the slab
- * page being used.
+ * page being used. Return the kmem_cache_cpu.freelist pointer
+ * if requested.
*/
static ulong
-get_cpu_slab_ptr(struct meminfo *si, int cpu)
+get_cpu_slab_ptr(struct meminfo *si, int cpu, ulong *cpu_freelist)
{
- ulong cpu_slab_ptr, page;
+ ulong cpu_slab_ptr, page, freelist;
+
+ if (cpu_freelist)
+ *cpu_freelist = 0;
switch (vt->cpu_slab_type)
{
@@ -13989,11 +14088,23 @@
cpu_slab_ptr = ULONG(si->cache_buf +
OFFSET(kmem_cache_cpu_slab) +
OFFSET(kmem_cache_cpu_page));
+ if (cpu_freelist && VALID_MEMBER(kmem_cache_cpu_freelist))
+ *cpu_freelist = ULONG(si->cache_buf +
+ OFFSET(kmem_cache_cpu_slab) +
+ OFFSET(kmem_cache_cpu_freelist));
break;
case TYPE_CODE_ARRAY:
cpu_slab_ptr = ULONG(si->cache_buf +
OFFSET(kmem_cache_cpu_slab) + (sizeof(void *)*cpu));
+
+ if (cpu_slab_ptr && cpu_freelist &&
+ VALID_MEMBER(kmem_cache_cpu_freelist)) {
+ if (readmem(cpu_slab_ptr + OFFSET(kmem_cache_cpu_freelist),
+ KVADDR, &freelist, sizeof(void *),
+ "kmem_cache_cpu.freelist", RETURN_ON_ERROR))
+ *cpu_freelist = freelist;
+ }
if (cpu_slab_ptr && VALID_MEMBER(kmem_cache_cpu_page)) {
if (!readmem(cpu_slab_ptr + OFFSET(kmem_cache_cpu_page),
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility