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;
}
--
prev 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.