* [SLUB 2/5] Use enum for tracking modes instead of integers
2007-04-10 3:29 [SLUB 1/5] Minor fixes Christoph Lameter
@ 2007-04-10 3:29 ` Christoph Lameter
2007-04-10 3:29 ` [SLUB 3/5] Fix object tracking Christoph Lameter
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2007-04-10 3:29 UTC (permalink / raw)
To: akpm; +Cc: linux-mm, Christoph Lameter
Use enum for tracking modes instead of integers.
Integers caused some confusion. This cleans it up and uses symbolic constants
throughout.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Index: linux-2.6.21-rc6-mm1/mm/slub.c
===================================================================
--- linux-2.6.21-rc6-mm1.orig/mm/slub.c 2007-04-09 15:30:59.000000000 -0700
+++ linux-2.6.21-rc6-mm1/mm/slub.c 2007-04-09 15:32:10.000000000 -0700
@@ -211,7 +211,10 @@ struct track {
unsigned long when; /* When did the operation occur */
};
-struct track *get_track(struct kmem_cache *s, void *object, int alloc)
+enum track_item { TRACK_ALLOC, TRACK_FREE };
+
+struct track *get_track(struct kmem_cache *s, void *object,
+ enum track_item alloc)
{
struct track *p;
@@ -224,7 +227,7 @@ struct track *get_track(struct kmem_cach
}
static void set_track(struct kmem_cache *s, void *object,
- int alloc, void *addr)
+ enum track_item alloc, void *addr)
{
struct track *p;
@@ -249,8 +252,8 @@ static void set_track(struct kmem_cache
static void init_tracking(struct kmem_cache *s, void *object)
{
if (s->flags & SLAB_STORE_USER) {
- set_track(s, object, 0, NULL);
- set_track(s, object, 1, NULL);
+ set_track(s, object, TRACK_FREE, NULL);
+ set_track(s, object, TRACK_ALLOC, NULL);
}
}
@@ -298,8 +301,8 @@ static void print_trailer(struct kmem_ca
off = s->inuse;
if (s->flags & SLAB_STORE_USER) {
- print_track("Last alloc", get_track(s, p, 0));
- print_track("Last free ", get_track(s, p, 1));
+ print_track("Last alloc", get_track(s, p, TRACK_ALLOC));
+ print_track("Last free ", get_track(s, p, TRACK_FREE));
off += 2 * sizeof(struct track);
}
@@ -1186,7 +1189,7 @@ debug:
if (!alloc_object_checks(s, page, object))
goto another_slab;
if (s->flags & SLAB_STORE_USER)
- set_tracking(s, object, 0);
+ set_tracking(s, object, TRACK_ALLOC);
goto have_object;
}
@@ -1274,7 +1277,7 @@ void kmem_cache_free(struct kmem_cache *
page = virt_to_head_page(x);
if (unlikely(PageError(page) && (s->flags & SLAB_STORE_USER)))
- set_tracking(s, x, 1);
+ set_tracking(s, x, TRACK_FREE);
slab_free(s, page, x);
}
EXPORT_SYMBOL(kmem_cache_free);
@@ -1894,7 +1897,7 @@ void kfree(const void *x)
s = page->slab;
if (unlikely(PageError(page) && (s->flags & SLAB_STORE_USER)))
- set_tracking(s, (void *)x, 1);
+ set_tracking(s, (void *)x, TRACK_FREE);
slab_free(s, page, (void *)x);
}
EXPORT_SYMBOL(kfree);
@@ -2254,7 +2257,7 @@ void *__kmalloc_track_caller(size_t size
object = kmem_cache_alloc(s, gfpflags);
if (object && (s->flags & SLAB_STORE_USER))
- set_track(s, object, 0, caller);
+ set_track(s, object, TRACK_ALLOC, caller);
return object;
}
@@ -2271,7 +2274,7 @@ void *__kmalloc_node_track_caller(size_t
object = kmem_cache_alloc_node(s, gfpflags, node);
if (object && (s->flags & SLAB_STORE_USER))
- set_track(s, object, 0, caller);
+ set_track(s, object, TRACK_ALLOC, caller);
return object;
}
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 5+ messages in thread* [SLUB 3/5] Fix object tracking
2007-04-10 3:29 [SLUB 1/5] Minor fixes Christoph Lameter
2007-04-10 3:29 ` [SLUB 2/5] Use enum for tracking modes instead of integers Christoph Lameter
@ 2007-04-10 3:29 ` Christoph Lameter
2007-04-10 3:29 ` [SLUB 4/5] Fix another NUMA bootstrap issue Christoph Lameter
2007-04-10 3:29 ` [SLUB 5/5] Update slabinfo.c Christoph Lameter
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2007-04-10 3:29 UTC (permalink / raw)
To: akpm; +Cc: linux-mm, Christoph Lameter
Object tracking did not work the right way for several call chains. Fix this up
by adding a new parameter to slub_alloc and slub_free that specifies the
caller address explicitly.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
---
mm/slub.c | 133 +++++++++++++++++++++++++++++---------------------------------
1 file changed, 63 insertions(+), 70 deletions(-)
Index: linux-2.6.21-rc6-mm1/mm/slub.c
===================================================================
--- linux-2.6.21-rc6-mm1.orig/mm/slub.c 2007-04-09 16:03:51.000000000 -0700
+++ linux-2.6.21-rc6-mm1/mm/slub.c 2007-04-09 16:06:47.000000000 -0700
@@ -246,9 +246,6 @@ static void set_track(struct kmem_cache
memset(p, 0, sizeof(struct track));
}
-#define set_tracking(__s, __o, __a) set_track(__s, __o, __a, \
- __builtin_return_address(0))
-
static void init_tracking(struct kmem_cache *s, void *object)
{
if (s->flags & SLAB_STORE_USER) {
@@ -1107,8 +1104,8 @@ static void flush_all(struct kmem_cache
* Fastpath is not possible if we need to get a new slab or have
* debugging enabled (which means all slabs are marked with PageError)
*/
-static __always_inline void *slab_alloc(struct kmem_cache *s,
- gfp_t gfpflags, int node)
+static void *slab_alloc(struct kmem_cache *s,
+ gfp_t gfpflags, int node, void *addr)
{
struct page *page;
void **object;
@@ -1189,20 +1186,20 @@ debug:
if (!alloc_object_checks(s, page, object))
goto another_slab;
if (s->flags & SLAB_STORE_USER)
- set_tracking(s, object, TRACK_ALLOC);
+ set_track(s, object, TRACK_ALLOC, addr);
goto have_object;
}
void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
{
- return slab_alloc(s, gfpflags, -1);
+ return slab_alloc(s, gfpflags, -1, __builtin_return_address(0));
}
EXPORT_SYMBOL(kmem_cache_alloc);
#ifdef CONFIG_NUMA
void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node)
{
- return slab_alloc(s, gfpflags, node);
+ return slab_alloc(s, gfpflags, node, __builtin_return_address(0));
}
EXPORT_SYMBOL(kmem_cache_alloc_node);
#endif
@@ -1213,7 +1210,8 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
*
* No special cachelines need to be read
*/
-static void slab_free(struct kmem_cache *s, struct page *page, void *x)
+static void slab_free(struct kmem_cache *s, struct page *page,
+ void *x, void *addr)
{
void *prior;
void **object = (void *)x;
@@ -1265,20 +1263,20 @@ slab_empty:
return;
debug:
- if (free_object_checks(s, page, x))
- goto checks_ok;
- goto out_unlock;
+ if (!free_object_checks(s, page, x))
+ goto out_unlock;
+ if (s->flags & SLAB_STORE_USER)
+ set_track(s, x, TRACK_FREE, addr);
+ goto checks_ok;
}
void kmem_cache_free(struct kmem_cache *s, void *x)
{
- struct page * page;
+ struct page *page;
page = virt_to_head_page(x);
- if (unlikely(PageError(page) && (s->flags & SLAB_STORE_USER)))
- set_tracking(s, x, TRACK_FREE);
- slab_free(s, page, x);
+ slab_free(s, page, x, __builtin_return_address(0));
}
EXPORT_SYMBOL(kmem_cache_free);
@@ -1836,7 +1834,7 @@ void *__kmalloc(size_t size, gfp_t flags
struct kmem_cache *s = get_slab(size, flags);
if (s)
- return kmem_cache_alloc(s, flags);
+ return slab_alloc(s, flags, -1, __builtin_return_address(0));
return NULL;
}
EXPORT_SYMBOL(__kmalloc);
@@ -1847,7 +1845,7 @@ void *__kmalloc_node(size_t size, gfp_t
struct kmem_cache *s = get_slab(size, flags);
if (s)
- return kmem_cache_alloc_node(s, flags, node);
+ return slab_alloc(s, flags, node, __builtin_return_address(0));
return NULL;
}
EXPORT_SYMBOL(__kmalloc_node);
@@ -1893,12 +1891,9 @@ void kfree(const void *x)
return;
page = virt_to_head_page(x);
-
s = page->slab;
- if (unlikely(PageError(page) && (s->flags & SLAB_STORE_USER)))
- set_tracking(s, (void *)x, TRACK_FREE);
- slab_free(s, page, (void *)x);
+ slab_free(s, page, (void *)x, __builtin_return_address(0));
}
EXPORT_SYMBOL(kfree);
@@ -2098,7 +2093,7 @@ void *kmem_cache_zalloc(struct kmem_cach
{
void *x;
- x = kmem_cache_alloc(s, flags);
+ x = slab_alloc(s, flags, -1, __builtin_return_address(0));
if (x)
memset(x, 0, s->objsize);
return x;
@@ -2249,34 +2244,22 @@ __initcall(cpucache_init);
void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
{
struct kmem_cache *s = get_slab(size, gfpflags);
- void *object;
if (!s)
return NULL;
- object = kmem_cache_alloc(s, gfpflags);
-
- if (object && (s->flags & SLAB_STORE_USER))
- set_track(s, object, TRACK_ALLOC, caller);
-
- return object;
+ return slab_alloc(s, gfpflags, -1, caller);
}
void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
int node, void *caller)
{
struct kmem_cache *s = get_slab(size, gfpflags);
- void *object;
if (!s)
return NULL;
- object = kmem_cache_alloc_node(s, gfpflags, node);
-
- if (object && (s->flags & SLAB_STORE_USER))
- set_track(s, object, TRACK_ALLOC, caller);
-
- return object;
+ return slab_alloc(s, gfpflags, node, caller);
}
#ifdef CONFIG_SYSFS
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 5+ messages in thread* [SLUB 4/5] Fix another NUMA bootstrap issue
2007-04-10 3:29 [SLUB 1/5] Minor fixes Christoph Lameter
2007-04-10 3:29 ` [SLUB 2/5] Use enum for tracking modes instead of integers Christoph Lameter
2007-04-10 3:29 ` [SLUB 3/5] Fix object tracking Christoph Lameter
@ 2007-04-10 3:29 ` Christoph Lameter
2007-04-10 3:29 ` [SLUB 5/5] Update slabinfo.c Christoph Lameter
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2007-04-10 3:29 UTC (permalink / raw)
To: akpm; +Cc: linux-mm, Christoph Lameter
SLUB : Fix another NUMA bootstrap issue.
Make sure that the bootstrap allocation occurs on the correct node and
that the slab we allocated gets put onto the partial list. Otherwise the rest
of the slab is lost for good.
And while we are at it reduce the amount of #ifdefs by rearranging code.
init_kmem_cache_node already initializes most fields. Avoid memset and just
set the remaining field manually.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Index: linux-2.6.21-rc6-mm1/mm/slub.c
===================================================================
--- linux-2.6.21-rc6-mm1.orig/mm/slub.c 2007-04-09 18:20:00.000000000 -0700
+++ linux-2.6.21-rc6-mm1/mm/slub.c 2007-04-09 19:55:32.000000000 -0700
@@ -1379,15 +1379,46 @@ static unsigned long calculate_alignment
static void init_kmem_cache_node(struct kmem_cache_node *n)
{
- memset(n, 0, sizeof(struct kmem_cache_node));
+ n->nr_partial = 0;
atomic_long_set(&n->nr_slabs, 0);
spin_lock_init(&n->list_lock);
INIT_LIST_HEAD(&n->partial);
}
+#ifdef CONFIG_NUMA
+/*
+ * No kmalloc_node yet so do it by hand. We know that this is the first
+ * slab on the node for this slabcache. There are no concurrent accesses
+ * possible.
+ *
+ * Note that this function only works on the kmalloc_node_cache
+ * when allocating for the kmalloc_node_cache.
+ */
+struct kmem_cache_node * __init early_kmem_cache_node_alloc(
+ gfp_t gfpflags, int node)
+{
+ struct page *page;
+ struct kmem_cache_node *n;
+
+ BUG_ON(kmalloc_caches->size < sizeof(struct kmem_cache_node));
+ page = new_slab(kmalloc_caches, gfpflags | GFP_THISNODE, node);
+ /* new_slab() disables interupts */
+ local_irq_enable();
+
+ BUG_ON(!page);
+ n = page->freelist;
+ BUG_ON(!n);
+ page->freelist = get_freepointer(kmalloc_caches, n);
+ page->inuse++;
+ kmalloc_caches->node[node] = n;
+ init_kmem_cache_node(n);
+ atomic_long_inc(&n->nr_slabs);
+ add_partial(kmalloc_caches, page);
+ return n;
+}
+
static void free_kmem_cache_nodes(struct kmem_cache *s)
{
-#ifdef CONFIG_NUMA
int node;
for_each_online_node(node) {
@@ -1396,12 +1427,10 @@ static void free_kmem_cache_nodes(struct
kmem_cache_free(kmalloc_caches, n);
s->node[node] = NULL;
}
-#endif
}
static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags)
{
-#ifdef CONFIG_NUMA
int node;
int local_node;
@@ -1415,45 +1444,37 @@ static int init_kmem_cache_nodes(struct
if (local_node == node)
n = &s->local_node;
- else
- if (slab_state == DOWN) {
- /*
- * No kmalloc_node yet so do it by hand.
- * We know that this is the first slab on the
- * node for this slabcache. There are no concurrent
- * accesses possible.
- */
- struct page *page;
-
- BUG_ON(s->size < sizeof(struct kmem_cache_node));
- page = new_slab(kmalloc_caches, gfpflags, node);
- /* new_slab() disables interupts */
- local_irq_enable();
-
- BUG_ON(!page);
- n = page->freelist;
- page->freelist = get_freepointer(kmalloc_caches, n);
- page->inuse++;
- } else
+ else {
+ if (slab_state == DOWN) {
+ n = early_kmem_cache_node_alloc(gfpflags,
+ node);
+ continue;
+ }
n = kmem_cache_alloc_node(kmalloc_caches,
gfpflags, node);
- if (!n) {
- free_kmem_cache_nodes(s);
- return 0;
- }
+ if (!n) {
+ free_kmem_cache_nodes(s);
+ return 0;
+ }
+ }
s->node[node] = n;
init_kmem_cache_node(n);
-
- if (slab_state == DOWN)
- atomic_long_inc(&n->nr_slabs);
}
+ return 1;
+}
#else
+static void free_kmem_cache_nodes(struct kmem_cache *s)
+{
+}
+
+static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags)
+{
init_kmem_cache_node(&s->local_node);
-#endif
return 1;
}
+#endif
int calculate_sizes(struct kmem_cache *s)
{
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 5+ messages in thread* [SLUB 5/5] Update slabinfo.c
2007-04-10 3:29 [SLUB 1/5] Minor fixes Christoph Lameter
` (2 preceding siblings ...)
2007-04-10 3:29 ` [SLUB 4/5] Fix another NUMA bootstrap issue Christoph Lameter
@ 2007-04-10 3:29 ` Christoph Lameter
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2007-04-10 3:29 UTC (permalink / raw)
To: akpm; +Cc: linux-mm, Christoph Lameter
Update slabinfo
This adds a lot of new functionality including display of NUMA information,
tracking information, slab verification etc. Some of those will only be
supported in V7.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
---
Documentation/vm/slabinfo.c | 184 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 167 insertions(+), 17 deletions(-)
Index: linux-2.6.21-rc6-mm1/Documentation/vm/slabinfo.c
===================================================================
--- linux-2.6.21-rc6-mm1.orig/Documentation/vm/slabinfo.c 2007-04-09 20:11:01.000000000 -0700
+++ linux-2.6.21-rc6-mm1/Documentation/vm/slabinfo.c 2007-04-09 20:23:50.000000000 -0700
@@ -14,16 +14,23 @@
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
+#include <getopt.h>
+#include <regex.h>
-char buffer[200];
+char buffer[4096];
int show_alias = 0;
-int show_slab = 1;
-int show_parameter = 0;
+int show_slab = 0;
+int show_parameters = 0;
int skip_zero = 1;
+int show_numa = 0;
+int show_track = 0;
+int validate = 0;
int page_size;
+regex_t pattern;
+
void fatal(const char *x, ...)
{
va_list ap;
@@ -34,23 +41,71 @@ void fatal(const char *x, ...)
exit(1);
}
+void usage(void)
+{
+ printf("slabinfo [-ahnpvtsz] [slab-regexp]\n"
+ "-a|--aliases Show aliases\n"
+ "-h|--help Show usage information\n"
+ "-n|--numa Show NUMA information\n"
+ "-p|--parameters Show global parameters\n"
+ "-v|--validate Validate slabs\n"
+ "-t|--tracking Show alloc/free information\n"
+ "-s|--slabs Show slabs\n"
+ "-z|--zero Include empty slabs\n"
+ );
+}
+
+unsigned long read_obj(char *name)
+{
+ FILE *f = fopen(name, "r");
+
+ if (!f)
+ buffer[0] = 0;
+ else {
+ if (!fgets(buffer,sizeof(buffer), f))
+ buffer[0] = 0;
+ fclose(f);
+ if (buffer[strlen(buffer)] == '\n')
+ buffer[strlen(buffer)] = 0;
+ }
+ return strlen(buffer);
+}
+
+
/*
* Get the contents of an attribute
*/
unsigned long get_obj(char *name)
{
- FILE *f = fopen(name, "r");
+ if (!read_obj(name))
+ return 0;
+
+ return atol(buffer);
+}
+
+unsigned long get_obj_and_str(char *name, char **x)
+{
unsigned long result = 0;
- if (!f) {
- getcwd(buffer, sizeof(buffer));
- fatal("Cannot open file '%s/%s'\n", buffer, name);
+ if (!read_obj(name)) {
+ x = NULL;
+ return 0;
}
+ result = strtoul(buffer, x, 10);
+ while (**x == ' ')
+ (*x)++;
+ return result;
+}
+
+void set_obj(char *name, int n)
+{
+ FILE *f = fopen(name, "w");
- if (fgets(buffer,sizeof(buffer), f))
- result = atol(buffer);
+ if (!f)
+ fatal("Cannot write to %s\n", name);
+
+ fprintf(f, "%d\n", n);
fclose(f);
- return result;
}
/*
@@ -90,12 +145,29 @@ int store_size(char *buffer, unsigned lo
void alias(const char *name)
{
- char *target;
+ int count;
+ char *p;
if (!show_alias)
return;
- /* Read link target */
- printf("%20s -> %s", name, target);
+
+ count = readlink(name, buffer, sizeof(buffer));
+
+ if (count < 0)
+ return;
+
+ buffer[count] = 0;
+
+ p = buffer + count;
+
+ while (p > buffer && p[-1] != '/')
+ p--;
+ printf("%-20s -> %s\n", name, p);
+}
+
+void slab_validate(char *name)
+{
+ set_obj("validate", 1);
}
int line = 0;
@@ -120,9 +192,6 @@ void slab(const char *name)
if (!show_slab)
return;
- if (chdir(name))
- fatal("Unable to access slab %s\n", name);
-
aliases = get_obj("aliases");
align = get_obj("align");
cache_dma = get_obj("cache_dma");
@@ -144,7 +213,7 @@ void slab(const char *name)
trace = get_obj("trace");
if (skip_zero && !slabs)
- goto out;
+ return;
store_size(size_str, slabs * page_size);
sprintf(dist_str,"%lu/%lu/%lu", slabs, partial, cpu_slabs);
@@ -172,41 +241,147 @@ void slab(const char *name)
*p++ = 'T';
*p = 0;
- printf("%-20s %8ld %7d %8s %14s %3ld %1ld %3d %3d %s\n",
+ printf("%-20s %8ld %7ld %8s %14s %3ld %1ld %3ld %3ld %s\n",
name, objects, object_size, size_str, dist_str,
objs_per_slab, order,
slabs ? (partial * 100) / slabs : 100,
- slabs ? (objects * object_size * 100) / (slabs * (page_size << order)) : 100,
+ slabs ? (objects * object_size * 100) /
+ (slabs * (page_size << order)) : 100,
flags);
-out:
- chdir("..");
+}
+
+void slab_numa(const char *name)
+{
+ unsigned long slabs;
+ char *numainfo;
+
+ slabs = get_obj_and_str("slabs", &numainfo);
+
+ if (skip_zero && !slabs)
+ return;
+
+ printf("%-20s %s", name, numainfo);
}
void parameter(const char *name)
{
- if (!show_parameter)
+ if (!show_parameters)
return;
}
+void show_tracking(const char *name)
+{
+ printf("\n%s: Calls to allocate a slab object\n", name);
+ printf("---------------------------------------------------\n");
+ if (read_obj("alloc_calls"))
+ printf(buffer);
+
+ printf("%s: Calls to free a slab object\n", name);
+ printf("-----------------------------------------------\n");
+ if (read_obj("free_calls"))
+ printf(buffer);
+
+}
+
+int slab_mismatch(char *slab)
+{
+ return regexec(&pattern, slab, 0, NULL, 0);
+}
+
+struct option opts[] = {
+ { "aliases", 0, NULL, 'a' },
+ { "slabs", 0, NULL, 's' },
+ { "numa", 0, NULL, 'n' },
+ { "parameters", 0, NULL, 'p' },
+ { "zero", 0, NULL, 'z' },
+ { "help", 0, NULL, 'h' },
+ { "validate", 0, NULL, 'v' },
+ { "track", 0, NULL, 't'},
+ { NULL, 0, NULL, 0 }
+};
+
int main(int argc, char *argv[])
{
DIR *dir;
struct dirent *de;
+ int c;
+ int err;
+ char *pattern_source;
page_size = getpagesize();
if (chdir("/sys/slab"))
fatal("This kernel does not have SLUB support.\n");
+ while ((c = getopt_long(argc, argv, "ahtvnpsz", opts, NULL)) != -1)
+ switch(c) {
+ case 's':
+ show_slab = 1;
+ break;
+ case 'a':
+ show_alias = 1;
+ break;
+ case 'n':
+ show_numa = 1;
+ break;
+ case 'p':
+ show_parameters = 1;
+ break;
+ case 'z':
+ skip_zero = 0;
+ break;
+ case 't':
+ show_track = 1;
+ break;
+ case 'v':
+ validate = 1;
+ break;
+ case 'h':
+ usage();
+ return 0;
+
+ default:
+ fatal("%s: Invalid option '%c'\n", argv[0], optopt);
+
+ }
+
+ if (!show_slab && !show_alias && !show_parameters && !show_track
+ && !validate)
+ show_slab = 1;
+
+ if (argc > optind)
+ pattern_source = argv[optind];
+ else
+ pattern_source = ".*";
+
+ err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
+ if (err)
+ fatal("%s: Invalid pattern '%s' code %d\n",
+ argv[0], pattern_source, err);
+
dir = opendir(".");
while ((de = readdir(dir))) {
- if (de->d_name[0] == '.')
+ if (de->d_name[0] == '.' ||
+ slab_mismatch(de->d_name))
continue;
switch (de->d_type) {
case DT_LNK:
alias(de->d_name);
break;
case DT_DIR:
- slab(de->d_name);
+ if (chdir(de->d_name))
+ fatal("Unable to access slab %s\n", de->d_name);
+
+ if (show_numa)
+ slab_numa(de->d_name);
+ else
+ if (show_track)
+ show_tracking(de->d_name);
+ else
+ if (validate)
+ slab_validate(de->d_name);
+ else
+ slab(de->d_name);
+ chdir("..");
break;
case DT_REG:
parameter(de->d_name);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 5+ messages in thread