----- Original Message -----
----- Original Message -----
> If this is a memory corruption in one of the slab, would it be better
> if "crash" just skipped this slab (or marked it as 'fail to load')
and
> show info for the rest of caches?
I suppose that could be done, but there is no recording of the kmem_cache
slab list entries during intialization, so there's currently nothing that
could be "marked". But perhaps a list of "bad" slab caches could be
created
by kmem_cache_init() which could be consulted later when "kmem -[sS]" cycle
through the slab list.
If your problem is due to slab cache corruption, would something like
the attached (and inlined) patch work for you?
--- crash-7.0.1/defs.h.orig
+++ crash-7.0.1/defs.h
@@ -2183,6 +2183,8 @@ struct vm_table { /* kern
int cpu_slab_type;
int nr_vm_event_items;
char **vm_event_items;
+ int nr_bad_slab_caches;
+ ulong *bad_slab_caches;
};
#define NODES (0x1)
--- crash-7.0.1/memory.c.orig
+++ crash-7.0.1/memory.c
@@ -8412,6 +8412,43 @@ kmem_cache_downsize(void)
FREEBUF(cache_buf);
}
+/*
+ * Stash a list of presumably-corrupted slab cache addresses.
+ */
+static void
+mark_bad_slab_cache(ulong cache)
+{
+ size_t sz;
+
+ if (vt->nr_bad_slab_caches) {
+ sz = sizeof(ulong) * (vt->nr_bad_slab_caches + 1);
+ if (!(vt->bad_slab_caches = realloc(vt->bad_slab_caches, sz))) {
+ error(INFO, "cannot realloc bad_slab_caches array\n");
+ vt->nr_bad_slab_caches = 0;
+ return;
+ }
+ } else {
+ if (!(vt->bad_slab_caches = (ulong *)malloc(sizeof(ulong)))) {
+ error(INFO, "cannot malloc bad_slab_caches array\n");
+ return;
+ }
+ }
+
+ vt->bad_slab_caches[vt->nr_bad_slab_caches++] = cache;
+}
+
+static int
+bad_slab_cache(ulong cache)
+{
+ int i;
+
+ for (i = 0; i < vt->nr_bad_slab_caches; i++) {
+ if (vt->bad_slab_caches[i] == cache)
+ return TRUE;
+ }
+
+ return FALSE;
+}
/*
* Determine the largest cpudata limit for a given cache.
@@ -8507,8 +8544,13 @@ kmem_cache_s_array_nodes:
for (i = max_limit = 0; (i < kt->cpus) && cpudata[i]; i++) {
if (!readmem(cpudata[i]+OFFSET(array_cache_limit),
KVADDR, &limit, sizeof(int),
- "array cache limit", RETURN_ON_ERROR))
- goto bail_out;
+ "array cache limit", RETURN_ON_ERROR)) {
+ error(INFO,
+ "kmem_cache: %lx: invalid array_cache pointer: %lx\n",
+ cache, cpudata[i]);
+ mark_bad_slab_cache(cache);
+ return max_limit;
+ }
if (CRASHDEBUG(3))
fprintf(fp, " array limit[%d]: %d\n", i, limit);
if (limit > max_limit)
@@ -9213,6 +9255,11 @@ dump_kmem_cache_percpu_v2(struct meminfo
goto next_cache;
}
+ if (bad_slab_cache(si->cache)) {
+ fprintf(fp, "%lx %-18s [INVALID/CORRUPTED]\n",
si->cache, buf);
+ goto next_cache;
+ }
+
si->curname = buf;
readmem(si->cache+OFFSET(kmem_cache_s_objsize),
@@ -11728,6 +11775,15 @@ dump_vm_table(int verbose)
fprintf(fp, " kmem_cache_count: %ld\n", vt->kmem_cache_count);
fprintf(fp, " kmem_cache_namelen: %d\n", vt->kmem_cache_namelen);
fprintf(fp, "kmem_cache_len_nodes: %ld\n", vt->kmem_cache_len_nodes);
+ fprintf(fp, " nr_bad_slab_caches: %d\n", vt->nr_bad_slab_caches);
+ if (!vt->nr_bad_slab_caches)
+ fprintf(fp, " bad_slab_caches: (unused)\n");
+ else {
+ for (i = 0; i < vt->nr_bad_slab_caches; i++) {
+ fprintf(fp, " bad_slab_caches[%d]: %lx\n",
+ i, vt->bad_slab_caches[i]);
+ }
+ }
fprintf(fp, " PG_reserved: %lx\n", vt->PG_reserved);
fprintf(fp, " PG_slab: %ld (%lx)\n", vt->PG_slab,
(ulong)1 << vt->PG_slab);
Thanks,
Dave