All of lore.kernel.org
 help / color / mirror / Atom feed
From: clameter@sgi.com
To: akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org
Subject: [patch 7/7] SLUB: Major slabinfo update
Date: Wed, 25 Apr 2007 22:07:50 -0700	[thread overview]
Message-ID: <20070426050934.945858534@sgi.com> (raw)
In-Reply-To: 20070426050743.867613938@sgi.com

[-- Attachment #1: slub_slabinfo_update --]
[-- Type: text/plain, Size: 23258 bytes --]

Enhancement to slabinfo
- Support for slab shrinking (-r option)
- Slab summary showing system totals
- Sync with new form of alias handling
- Sort by size, reverse sorting etc
- Alias lookups

Signed-off-by: Christoph Lameter <clameter@sgi.com>

Index: linux-2.6.21-rc7-mm1/Documentation/vm/slabinfo.c
===================================================================
--- linux-2.6.21-rc7-mm1.orig/Documentation/vm/slabinfo.c	2007-04-25 21:20:24.000000000 -0700
+++ linux-2.6.21-rc7-mm1/Documentation/vm/slabinfo.c	2007-04-25 21:46:40.000000000 -0700
@@ -3,7 +3,7 @@
  *
  * (C) 2007 sgi, Christoph Lameter <clameter@sgi.com>
  *
- * Compile by doing:
+ * Compile by:
  *
  * gcc -o slabinfo slabinfo.c
  */
@@ -17,15 +17,47 @@
 #include <getopt.h>
 #include <regex.h>
 
+#define MAX_SLABS 500
+#define MAX_ALIASES 500
+#define MAX_NODES 1024
+
+struct slabinfo {
+	char *name;
+	int alias;
+	int refs;
+	int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
+	int hwcache_align, object_size, objs_per_slab;
+	int sanity_checks, slab_size, store_user, trace;
+	int order, poison, reclaim_account, red_zone;
+	unsigned long partial, objects, slabs;
+	int numa[MAX_NODES];
+	int numa_partial[MAX_NODES];
+} slabinfo[MAX_SLABS];
+
+struct aliasinfo {
+	char *name;
+	char *ref;
+	struct slabinfo *slab;
+} aliasinfo[MAX_ALIASES];
+
+int slabs = 0;
+int aliases = 0;
+int highest_node = 0;
+
 char buffer[4096];
 
 int show_alias = 0;
 int show_slab = 0;
-int show_parameters = 0;
 int skip_zero = 1;
 int show_numa = 0;
 int show_track = 0;
+int show_first_alias = 0;
 int validate = 0;
+int shrink = 0;
+int show_inverted = 0;
+int show_single_ref = 0;
+int show_totals = 0;
+int sort_size = 0;
 
 int page_size;
 
@@ -47,11 +79,16 @@ void usage(void)
 		"-a|--aliases           Show aliases\n"
 		"-h|--help              Show usage information\n"
 		"-n|--numa              Show NUMA information\n"
-		"-p|--parameters        Show global parameters\n"
+		"-r|--reduce	        Shrink slabs\n"
 		"-v|--validate          Validate slabs\n"
 		"-t|--tracking          Show alloc/free information\n"
+		"-T|--Totals		Show summary information\n"
 		"-s|--slabs             Show slabs\n"
+		"-S|--Size		Sort by size\n"
 		"-z|--zero              Include empty slabs\n"
+		"-f|--first-alias       Show first alias\n"
+		"-i|--inverted          Inverted list\n"
+		"-1|--1ref              Single reference\n"
 	);
 }
 
@@ -86,23 +123,32 @@ unsigned long get_obj(char *name)
 unsigned long get_obj_and_str(char *name, char **x)
 {
 	unsigned long result = 0;
+	char *p;
+
+	*x = NULL;
 
 	if (!read_obj(name)) {
 		x = NULL;
 		return 0;
 	}
-	result = strtoul(buffer, x, 10);
-	while (**x == ' ')
-		(*x)++;
+	result = strtoul(buffer, &p, 10);
+	while (*p == ' ')
+		p++;
+	if (*p)
+		*x = strdup(p);
 	return result;
 }
 
-void set_obj(char *name, int n)
+void set_obj(struct slabinfo *s, char *name, int n)
 {
-	FILE *f = fopen(name, "w");
+	char x[100];
+
+	sprintf(x, "%s/%s", s->name, name);
+
+	FILE *f = fopen(x, "w");
 
 	if (!f)
-		fatal("Cannot write to %s\n", name);
+		fatal("Cannot write to %s\n", x);
 
 	fprintf(f, "%d\n", n);
 	fclose(f);
@@ -143,167 +189,613 @@ int store_size(char *buffer, unsigned lo
 	return n;
 }
 
-void alias(const char *name)
+void decode_numa_list(int *numa, char *t)
 {
-	int count;
-	char *p;
-
-	if (!show_alias)
-		return;
+	int node;
+	int nr;
 
-	count = readlink(name, buffer, sizeof(buffer));
+	memset(numa, 0, MAX_NODES * sizeof(int));
 
-	if (count < 0)
-		return;
+	while (*t == 'N') {
+		t++;
+		node = strtoul(t, &t, 10);
+		if (*t == '=') {
+			t++;
+			nr = strtoul(t, &t, 10);
+			numa[node] = nr;
+			if (node > highest_node)
+				highest_node = node;
+		}
+		while (*t == ' ')
+			t++;
+	}
+}
 
-	buffer[count] = 0;
+char *hackname(struct slabinfo *s)
+{
+	char *n = s->name;
 
-	p = buffer + count;
+	if (n[0] == ':') {
+		char *nn = malloc(20);
+		char *p;
+
+		strncpy(nn, n, 20);
+		n = nn;
+		p = n + 4;
+		while (*p && *p !=':')
+			p++;
+		*p = 0;
+	}
+	return n;
+}
 
-	while (p > buffer && p[-1] != '/')
-		p--;
-	printf("%-20s -> %s\n", name, p);
+void slab_validate(struct slabinfo *s)
+{
+	set_obj(s, "validate", 1);
 }
 
-void slab_validate(char *name)
+void slab_shrink(struct slabinfo *s)
 {
-	set_obj("validate", 1);
+	set_obj(s, "shrink", 1);
 }
 
 int line = 0;
 
 void first_line(void)
 {
-	printf("Name                Objects   Objsize    Space "
-		"Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n");
+	printf("Name                 Objects   Objsize    Space "
+		"Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
+}
+
+/*
+ * Find the shortest alias of a slab
+ */
+struct aliasinfo *find_one_alias(struct slabinfo *find)
+{
+	struct aliasinfo *a;
+	struct aliasinfo *best = NULL;
+
+	for(a = aliasinfo;a < aliasinfo + aliases; a++) {
+		if (a->slab == find &&
+			(!best || strlen(best->name) < strlen(a->name))) {
+				best = a;
+				if (strncmp(a->name,"kmall", 5) == 0)
+					return best;
+			}
+	}
+	if (best)
+		return best;
+	fatal("Cannot find alias for %s\n", find->name);
+	return NULL;
 }
 
-void slab(const char *name)
+unsigned long slab_size(struct slabinfo *s)
+{
+	return 	s->slabs * (page_size << s->order);
+}
+
+
+void slabcache(struct slabinfo *s)
 {
-	unsigned long aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
-	unsigned long hwcache_align, object_size, objects, objs_per_slab;
-	unsigned long order, partial, poison, reclaim_account, red_zone;
-	unsigned long sanity_checks, slab_size, slabs, store_user, trace;
 	char size_str[20];
 	char dist_str[40];
 	char flags[20];
 	char *p = flags;
+	char *n;
 
-	if (!show_slab)
+	if (skip_zero && !s->slabs)
 		return;
 
-	aliases = get_obj("aliases");
-	align = get_obj("align");
-	cache_dma = get_obj("cache_dma");
-	cpu_slabs = get_obj("cpu_slabs");
-	destroy_by_rcu = get_obj("destroy_by_rcu");
-	hwcache_align = get_obj("hwcache_align");
-	object_size = get_obj("object_size");
-	objects = get_obj("objects");
-	objs_per_slab = get_obj("objs_per_slab");
-	order = get_obj("order");
-	partial = get_obj("partial");
-	poison = get_obj("poison");
-	reclaim_account = get_obj("reclaim_account");
-	red_zone = get_obj("red_zone");
-	sanity_checks = get_obj("sanity_checks");
-	slab_size = get_obj("slab_size");
-	slabs = get_obj("slabs");
-	store_user = get_obj("store_user");
-	trace = get_obj("trace");
-
-	if (skip_zero && !slabs)
-		return;
-
-	store_size(size_str, slabs * page_size);
-	sprintf(dist_str,"%lu/%lu/%lu", slabs, partial, cpu_slabs);
+	store_size(size_str, slab_size(s));
+	sprintf(dist_str,"%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs);
 
 	if (!line++)
 		first_line();
 
-	if (aliases)
+	if (s->aliases)
 		*p++ = '*';
-	if (cache_dma)
+	if (s->cache_dma)
 		*p++ = 'd';
-	if (hwcache_align)
+	if (s->hwcache_align)
 		*p++ = 'A';
-	if (poison)
+	if (s->poison)
 		*p++ = 'P';
-	if (reclaim_account)
+	if (s->reclaim_account)
 		*p++ = 'a';
-	if (red_zone)
+	if (s->red_zone)
 		*p++ = 'Z';
-	if (sanity_checks)
+	if (s->sanity_checks)
 		*p++ = 'F';
-	if (store_user)
+	if (s->store_user)
 		*p++ = 'U';
-	if (trace)
+	if (s->trace)
 		*p++ = 'T';
 
 	*p = 0;
-	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,
+	n = hackname(s);
+	printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
+			n, s->objects, s->object_size, size_str, dist_str,
+			s->objs_per_slab, s->order,
+			s->slabs ? (s->partial * 100) / s->slabs : 100,
+			s->slabs ? (s->objects * s->object_size * 100) /
+				(s->slabs * (page_size << s->order)) : 100,
 			flags);
 }
 
-void slab_numa(const char *name)
+void slab_numa(struct slabinfo *s)
 {
-	unsigned long slabs;
-	char *numainfo;
-
-	slabs = get_obj_and_str("slabs", &numainfo);
+	char *n;
+	int node;
 
-	if (skip_zero && !slabs)
+	if (skip_zero && !s->slabs)
 		return;
+	n = hackname(s);
 
-	printf("%-20s %s", name, numainfo);
-}
+	if (!line) {
+		printf("\nSlab             Node ");
+		for(node = 0; node <= highest_node; node++)
+			printf(" %4d", node);
+		printf("\n----------------------");
+		for(node = 0; node <= highest_node; node++)
+			printf("-----");
+		printf("\n");
+	}
+	printf("%-21s ", n);
+	for(node = 0; node <= highest_node; node++) {
+		char b[20];
 
-void parameter(const char *name)
-{
-	if (!show_parameters)
-		return;
+		store_size(b, s->numa[node]);
+		printf(" %4s", b);
+	}
+	printf("\n");
+	line++;
 }
 
-void show_tracking(const char *name)
+void show_tracking(struct slabinfo *s)
 {
-	printf("\n%s: Calls to allocate a slab object\n", name);
+	printf("\n%s: Calls to allocate a slab object\n", s->name);
 	printf("---------------------------------------------------\n");
 	if (read_obj("alloc_calls"))
 		printf(buffer);
 
-	printf("%s: Calls to free a slab object\n", name);
+	printf("%s: Calls to free a slab object\n", s->name);
 	printf("-----------------------------------------------\n");
 	if (read_obj("free_calls"))
 		printf(buffer);
 
 }
 
+void totals(void)
+{
+	struct slabinfo *s;
+
+	int used_slabs = 0;
+	char b1[20], b2[20], b3[20], b4[20];
+	unsigned long long min_objsize = 0, max_objsize = 0, avg_objsize;
+	unsigned long long min_partial = 0, max_partial = 0, avg_partial, total_partial = 0;
+	unsigned long long min_slabs = 0, max_slabs = 0, avg_slabs, total_slabs = 0;
+	unsigned long long min_size = 0, max_size = 0, avg_size, total_size = 0;
+	unsigned long long min_waste = 0, max_waste = 0, avg_waste, total_waste = 0;
+	unsigned long long min_objects = 0, max_objects = 0, avg_objects, total_objects = 0;
+	unsigned long long min_objwaste = 0, max_objwaste = 0, avg_objwaste;
+	unsigned long long min_used = 0, max_used = 0, avg_used, total_used = 0;
+	unsigned long min_ppart = 0, max_ppart = 0, avg_ppart, total_ppart = 0;
+	unsigned long min_partobj = 0, max_partobj = 0, avg_partobj;
+	unsigned long total_objects_in_partial = 0;
+
+	for (s = slabinfo; s < slabinfo + slabs; s++) {
+		unsigned long long size;
+		unsigned long partial;
+		unsigned long slabs;
+		unsigned long used;
+		unsigned long long wasted;
+		unsigned long long objwaste;
+		long long objects_in_partial;
+		unsigned long percentage_partial;
+
+		if (!s->slabs || !s->objects)
+			continue;
+
+		used_slabs++;
+
+		size = slab_size(s);
+		partial = s->partial << s->order;
+		slabs = s->slabs << s->order;
+		used = s->objects * s->object_size;
+		wasted = size - used;
+		objwaste = wasted / s->objects;
+
+		objects_in_partial = s->objects - (s->slabs - s->partial - s ->cpu_slabs)
+					* s->objs_per_slab;
+
+		if (objects_in_partial < 0)
+			objects_in_partial = 0;
+
+		percentage_partial = objects_in_partial * 100 / s->objects;
+		if (percentage_partial > 100)
+			percentage_partial = 100;
+
+		if (s->object_size < min_objsize || !min_objsize)
+			min_objsize = s->object_size;
+		if (partial && (partial < min_partial || !min_partial))
+			min_partial = partial;
+		if (slabs < min_slabs || !min_partial)
+			min_slabs = slabs;
+		if (size < min_size)
+			min_size = size;
+		if (wasted < min_waste && !min_waste)
+			min_waste = wasted;
+		if (objwaste < min_objwaste || !min_objwaste)
+			min_objwaste = objwaste;
+		if (s->objects < min_objects || !min_objects)
+			min_objects = s->objects;
+		if (used < min_used || !min_used)
+			min_used = used;
+		if (objects_in_partial < min_partobj || !min_partobj)
+			min_partobj = objects_in_partial;
+		if (percentage_partial < min_ppart || !min_ppart)
+			min_ppart = percentage_partial;
+
+		if (s->object_size > max_objsize)
+			max_objsize = s->object_size;
+		if (partial > max_partial)
+			max_partial = partial;
+		if (slabs > max_slabs)
+			max_slabs = slabs;
+		if (size > max_size)
+			max_size = size;
+		if (wasted > max_waste)
+			max_waste = wasted;
+		if (objwaste > max_objwaste)
+			max_objwaste = objwaste;
+		if (s->objects > max_objects)
+			max_objects = s->objects;
+		if (used > max_used)
+			max_used = used;
+		if (objects_in_partial > max_partobj)
+			max_partobj = objects_in_partial;
+		if (percentage_partial > max_ppart)
+			max_ppart = percentage_partial;
+
+		total_objects += s->objects;
+		total_partial += partial;
+		total_slabs += slabs;
+		total_used += used;
+		total_waste += wasted;
+		total_size += size;
+		total_ppart += percentage_partial;
+		total_objects_in_partial += objects_in_partial;
+	}
+
+	if (!total_objects) {
+		printf("No objects\n");
+		return;
+	}
+	if (!used_slabs) {
+		printf("No slabs\n");
+		return;
+	}
+	avg_partial = total_partial / used_slabs;
+	avg_slabs = total_slabs / used_slabs;
+	avg_waste = total_waste / used_slabs;
+	avg_size = total_waste / used_slabs;
+	avg_objects = total_objects / used_slabs;
+	avg_used = total_used / used_slabs;
+	avg_ppart = total_ppart / used_slabs;
+	avg_partobj = total_objects_in_partial / used_slabs;
+
+	avg_objsize = total_used / total_objects;
+	avg_objwaste = total_waste / total_objects;
+
+	printf("Slabcache Totals\n");
+	printf("----------------\n");
+	printf("Slabcaches : %3d      Aliases  : %3d     Active: %3d\n",
+			slabs, aliases, used_slabs);
+
+	store_size(b1, total_used);store_size(b2, total_waste);
+	store_size(b3, total_waste * 100 / total_used);
+	printf("Memory used: %5s   # Loss   : %5s   MRatio: %3s%%\n", b1, b2, b3);
+
+	store_size(b1, total_objects);store_size(b2, total_objects_in_partial);
+	store_size(b3, total_objects_in_partial * 100 / total_objects);
+	printf("# Objects  : %5s   # PartObj: %5s   ORatio: %3s%%\n", b1, b2, b3);
+
+	printf("\n");
+	printf("Per Cache    Average         Min         Max       Total\n");
+	printf("---------------------------------------------------------\n");
+
+	store_size(b1, avg_objects);store_size(b2, min_objects);
+	store_size(b3, max_objects);store_size(b4, total_objects);
+	printf("# Objects %10s  %10s  %10s  %10s\n",
+			b1,	b2,	b3,	b4);
+
+	store_size(b1, avg_slabs);store_size(b2, min_slabs);
+	store_size(b3, max_slabs);store_size(b4, total_slabs);
+	printf("# Slabs   %10s  %10s  %10s  %10s\n",
+			b1,	b2,	b3,	b4);
+
+	store_size(b1, avg_partial);store_size(b2, min_partial);
+	store_size(b3, max_partial);store_size(b4, total_partial);
+	printf("# Partial %10s  %10s  %10s  %10s\n",
+			b1,	b2,	b3,	b4);
+	store_size(b1, avg_ppart);store_size(b2, min_ppart);
+	store_size(b3, max_ppart);
+	printf("Partial   %10s%% %10s%% %10s%%\n",
+			b1,	b2,	b3);
+
+	store_size(b1, avg_size);store_size(b2, min_size);
+	store_size(b3, max_size);store_size(b4, total_size);
+	printf("Memory    %10s  %10s  %10s  %10s\n",
+			b1,	b2,	b3,	b4);
+
+	store_size(b1, avg_used);store_size(b2, min_used);
+	store_size(b3, max_used);store_size(b4, total_used);
+	printf("Used      %10s  %10s  %10s  %10s\n",
+			b1,	b2,	b3,	b4);
+
+	store_size(b1, avg_slabs);store_size(b2, min_slabs);
+	store_size(b3, max_slabs);store_size(b4, total_slabs);
+	printf("Waste     %10s  %10s  %10s  %10s\n",
+			b1,	b2,	b3,	b4);
+
+	printf("\n");
+	printf("Per Object   Average         Min         Max\n");
+	printf("---------------------------------------------\n");
+
+	store_size(b1, avg_objsize);store_size(b2, min_objsize);
+	store_size(b3, max_objsize);
+	printf("Size      %10s  %10s  %10s\n",
+			b1,	b2,	b3);
+
+	store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
+	store_size(b3, max_objwaste);
+	printf("Loss      %10s  %10s  %10s\n",
+			b1,	b2,	b3);
+}
+
+void sort_slabs(void)
+{
+	struct slabinfo *s1,*s2;
+
+	for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
+		for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
+			int result;
+
+			if (sort_size)
+				result = slab_size(s1) < slab_size(s2);
+			else
+				result = strcasecmp(s1->name, s2->name);
+
+			if (show_inverted)
+				result = -result;
+
+			if (result > 0) {
+				struct slabinfo t;
+
+				memcpy(&t, s1, sizeof(struct slabinfo));
+				memcpy(s1, s2, sizeof(struct slabinfo));
+				memcpy(s2, &t, sizeof(struct slabinfo));
+			}
+		}
+	}
+}
+
+void sort_aliases(void)
+{
+	struct aliasinfo *a1,*a2;
+
+	for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) {
+		for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) {
+			char *n1, *n2;
+
+			n1 = a1->name;
+			n2 = a2->name;
+			if (show_alias && !show_inverted) {
+				n1 = a1->ref;
+				n2 = a2->ref;
+			}
+			if (strcasecmp(n1, n2) > 0) {
+				struct aliasinfo t;
+
+				memcpy(&t, a1, sizeof(struct aliasinfo));
+				memcpy(a1, a2, sizeof(struct aliasinfo));
+				memcpy(a2, &t, sizeof(struct aliasinfo));
+			}
+		}
+	}
+}
+
+void link_slabs(void)
+{
+	struct aliasinfo *a;
+	struct slabinfo *s;
+
+	for (a = aliasinfo; a < aliasinfo + aliases; a++) {
+
+		for(s = slabinfo; s < slabinfo + slabs; s++)
+			if (strcmp(a->ref, s->name) == 0) {
+				a->slab = s;
+				s->refs++;
+				break;
+			}
+		if (s == slabinfo + slabs)
+			fatal("Unresolved alias %s\n", a->ref);
+	}
+}
+
+void alias(void)
+{
+	struct aliasinfo *a;
+	char *active = NULL;
+
+	sort_aliases();
+	link_slabs();
+
+	for(a = aliasinfo; a < aliasinfo + aliases; a++) {
+
+		if (!show_single_ref && a->slab->refs == 1)
+			continue;
+
+		if (!show_inverted) {
+			if (active) {
+				if (strcmp(a->slab->name, active) == 0) {
+					printf(" %s", a->name);
+					continue;
+				}
+			}
+			printf("\n%-20s <- %s", a->slab->name, a->name);
+			active = a->slab->name;
+		}
+		else
+			printf("%-20s -> %s\n", a->name, a->slab->name);
+	}
+	if (active)
+		printf("\n");
+}
+
+
+void rename_slabs(void)
+{
+	struct slabinfo *s;
+	struct aliasinfo *a;
+
+	for (s = slabinfo; s < slabinfo + slabs; s++) {
+		if (*s->name != ':')
+			continue;
+
+		if (s->refs > 1 && !show_first_alias)
+			continue;
+
+		a = find_one_alias(s);
+
+		s->name = a->name;
+	}
+}
+
 int slab_mismatch(char *slab)
 {
 	return regexec(&pattern, slab, 0, NULL, 0);
 }
 
+void read_slab_dir(void)
+{
+	DIR *dir;
+	struct dirent *de;
+	struct slabinfo *slab = slabinfo;
+	struct aliasinfo *alias = aliasinfo;
+	char *p;
+	char *t;
+	int count;
+
+	dir = opendir(".");
+	while ((de = readdir(dir))) {
+		if (de->d_name[0] == '.' ||
+				slab_mismatch(de->d_name))
+			continue;
+		switch (de->d_type) {
+		   case DT_LNK:
+		   	alias->name = strdup(de->d_name);
+			count = readlink(de->d_name, buffer, sizeof(buffer));
+
+			if (count < 0)
+				fatal("Cannot read symlink %s\n", de->d_name);
+
+			buffer[count] = 0;
+			p = buffer + count;
+			while (p > buffer && p[-1] != '/')
+				p--;
+			alias->ref = strdup(p);
+			alias++;
+			break;
+		   case DT_DIR:
+			if (chdir(de->d_name))
+				fatal("Unable to access slab %s\n", slab->name);
+		   	slab->name = strdup(de->d_name);
+			slab->alias = 0;
+			slab->refs = 0;
+			slab->aliases = get_obj("aliases");
+			slab->align = get_obj("align");
+			slab->cache_dma = get_obj("cache_dma");
+			slab->cpu_slabs = get_obj("cpu_slabs");
+			slab->destroy_by_rcu = get_obj("destroy_by_rcu");
+			slab->hwcache_align = get_obj("hwcache_align");
+			slab->object_size = get_obj("object_size");
+			slab->objects = get_obj("objects");
+			slab->objs_per_slab = get_obj("objs_per_slab");
+			slab->order = get_obj("order");
+			slab->partial = get_obj("partial");
+			slab->partial = get_obj_and_str("partial", &t);
+			decode_numa_list(slab->numa_partial, t);
+			slab->poison = get_obj("poison");
+			slab->reclaim_account = get_obj("reclaim_account");
+			slab->red_zone = get_obj("red_zone");
+			slab->sanity_checks = get_obj("sanity_checks");
+			slab->slab_size = get_obj("slab_size");
+			slab->slabs = get_obj_and_str("slabs", &t);
+			decode_numa_list(slab->numa, t);
+			slab->store_user = get_obj("store_user");
+			slab->trace = get_obj("trace");
+			chdir("..");
+			slab++;
+			break;
+		   default :
+			fatal("Unknown file type %lx\n", de->d_type);
+		}
+	}
+	closedir(dir);
+	slabs = slab - slabinfo;
+	aliases = alias - aliasinfo;
+	if (slabs > MAX_SLABS)
+		fatal("Too many slabs\n");
+	if (aliases > MAX_ALIASES)
+		fatal("Too many aliases\n");
+}
+
+void output_slabs(void)
+{
+	struct slabinfo *slab;
+
+	for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
+
+		if (slab->alias)
+			continue;
+
+
+		if (show_numa)
+			slab_numa(slab);
+		else
+		if (show_track)
+			show_tracking(slab);
+		else
+		if (validate)
+			slab_validate(slab);
+		else
+		if (shrink)
+			slab_shrink(slab);
+		else {
+			if (show_slab)
+				slabcache(slab);
+		}
+	}
+}
+
 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' },
+	{ "first-alias", 0, NULL, 'f' },
+	{ "reduce", 0, NULL, 'r' },
 	{ "track", 0, NULL, 't'},
+	{ "inverted", 0, NULL, 'i'},
+	{ "1ref", 0, NULL, '1'},
 	{ NULL, 0, NULL, 0 }
 };
 
 int main(int argc, char *argv[])
 {
-	DIR *dir;
-	struct dirent *de;
 	int c;
 	int err;
 	char *pattern_source;
@@ -312,22 +804,31 @@ int main(int argc, char *argv[])
 	if (chdir("/sys/slab"))
 		fatal("This kernel does not have SLUB support.\n");
 
-	while ((c = getopt_long(argc, argv, "ahtvnpsz", opts, NULL)) != -1)
+	while ((c = getopt_long(argc, argv, "afhi1nprstvzTS", opts, NULL)) != -1)
 	switch(c) {
-		case 's':
-			show_slab = 1;
+		case '1':
+			show_single_ref = 1;
 			break;
 		case 'a':
 			show_alias = 1;
 			break;
+		case 'f':
+			show_first_alias = 1;
+			break;
+		case 'h':
+			usage();
+			return 0;
+		case 'i':
+			show_inverted = 1;
+			break;
 		case 'n':
 			show_numa = 1;
 			break;
-		case 'p':
-			show_parameters = 1;
+		case 'r':
+			shrink = 1;
 			break;
-		case 'z':
-			skip_zero = 0;
+		case 's':
+			show_slab = 1;
 			break;
 		case 't':
 			show_track = 1;
@@ -335,17 +836,23 @@ int main(int argc, char *argv[])
 		case 'v':
 			validate = 1;
 			break;
-		case 'h':
-			usage();
-			return 0;
+		case 'z':
+			skip_zero = 0;
+			break;
+		case 'T':
+			show_totals = 1;
+			break;
+		case 'S':
+			sort_size = 1;
+			break;
 
 		default:
 			fatal("%s: Invalid option '%c'\n", argv[0], optopt);
 
 	}
 
-	if (!show_slab && !show_alias && !show_parameters && !show_track
-		&& !validate)
+	if (!show_slab && !show_alias && !show_track
+		&& !validate && !shrink)
 			show_slab = 1;
 
 	if (argc > optind)
@@ -357,39 +864,17 @@ int main(int argc, char *argv[])
 	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] == '.' ||
-				slab_mismatch(de->d_name))
-			continue;
-		switch (de->d_type) {
-		   case DT_LNK:
-			alias(de->d_name);
-			break;
-		   case DT_DIR:
-			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);
-			break;
-		   default :
-			fatal("Unknown file type %lx\n", de->d_type);
-		}
+	read_slab_dir();
+	if (show_alias)
+		alias();
+	else
+	if (show_totals)
+		totals();
+	else {
+		link_slabs();
+		rename_slabs();
+		sort_slabs();
+		output_slabs();
 	}
-	closedir(dir);
 	return 0;
 }

--

      parent reply	other threads:[~2007-04-26  5:11 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-26  5:07 [patch 0/7] SLUB updates clameter
2007-04-26  5:07 ` [patch 1/7] SLUB: Remove duplicate VM_BUG_ON clameter
2007-04-26  5:07 ` [patch 2/7] SLAB: Fix sysfs directory handling clameter
2007-04-26  5:07 ` [patch 3/7] SLUB: debug printk cleanup clameter
2007-04-26  5:07 ` [patch 4/7] SLUB: Conform more to SLABs SLAB_HWCACHE_ALIGN behavior clameter
2007-04-26  5:07 ` [patch 5/7] SLUB: Add MIN_PARTIAL clameter
2007-04-26  5:07 ` [patch 6/7] SLUB: Free slabs and sort partial slab lists in kmem_cache_shrink clameter
2007-04-26  5:07 ` clameter [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070426050934.945858534@sgi.com \
    --to=clameter@sgi.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.