aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2007-05-09 05:32:37 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 15:30:44 -0400
commita87615b8f9e2349f6d3770af3d72fd6a41ab4239 (patch)
tree5e2608dad1ad746b0552ef52afec9298320045ac
parentbe7b3fbcef34452127bed93632b8e788f685d70e (diff)
SLUB: slabinfo upgrade
-e Show empty slabs -d Modification of slab debug options at runtime -o Operations. Display of ctor / dtor etc. -r Report: Display all available information about a slabcache. Cleanup tracking display and make it work right. Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/vm/slabinfo.c426
1 files changed, 352 insertions, 74 deletions
diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c
index 41710ccf3a29..686a8e04a4f3 100644
--- a/Documentation/vm/slabinfo.c
+++ b/Documentation/vm/slabinfo.c
@@ -16,6 +16,7 @@
16#include <stdarg.h> 16#include <stdarg.h>
17#include <getopt.h> 17#include <getopt.h>
18#include <regex.h> 18#include <regex.h>
19#include <errno.h>
19 20
20#define MAX_SLABS 500 21#define MAX_SLABS 500
21#define MAX_ALIASES 500 22#define MAX_ALIASES 500
@@ -41,12 +42,15 @@ struct aliasinfo {
41} aliasinfo[MAX_ALIASES]; 42} aliasinfo[MAX_ALIASES];
42 43
43int slabs = 0; 44int slabs = 0;
45int actual_slabs = 0;
44int aliases = 0; 46int aliases = 0;
45int alias_targets = 0; 47int alias_targets = 0;
46int highest_node = 0; 48int highest_node = 0;
47 49
48char buffer[4096]; 50char buffer[4096];
49 51
52int show_empty = 0;
53int show_report = 0;
50int show_alias = 0; 54int show_alias = 0;
51int show_slab = 0; 55int show_slab = 0;
52int skip_zero = 1; 56int skip_zero = 1;
@@ -59,6 +63,15 @@ int show_inverted = 0;
59int show_single_ref = 0; 63int show_single_ref = 0;
60int show_totals = 0; 64int show_totals = 0;
61int sort_size = 0; 65int sort_size = 0;
66int set_debug = 0;
67int show_ops = 0;
68
69/* Debug options */
70int sanity = 0;
71int redzone = 0;
72int poison = 0;
73int tracking = 0;
74int tracing = 0;
62 75
63int page_size; 76int page_size;
64 77
@@ -76,20 +89,33 @@ void fatal(const char *x, ...)
76 89
77void usage(void) 90void usage(void)
78{ 91{
79 printf("slabinfo [-ahnpvtsz] [slab-regexp]\n" 92 printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n"
93 "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
80 "-a|--aliases Show aliases\n" 94 "-a|--aliases Show aliases\n"
95 "-d<options>|--debug=<options> Set/Clear Debug options\n"
96 "-e|--empty Show empty slabs\n"
97 "-f|--first-alias Show first alias\n"
81 "-h|--help Show usage information\n" 98 "-h|--help Show usage information\n"
99 "-i|--inverted Inverted list\n"
100 "-l|--slabs Show slabs\n"
82 "-n|--numa Show NUMA information\n" 101 "-n|--numa Show NUMA information\n"
102 "-o|--ops Show kmem_cache_ops\n"
83 "-s|--shrink Shrink slabs\n" 103 "-s|--shrink Shrink slabs\n"
84 "-v|--validate Validate slabs\n" 104 "-r|--report Detailed report on single slabs\n"
105 "-S|--Size Sort by size\n"
85 "-t|--tracking Show alloc/free information\n" 106 "-t|--tracking Show alloc/free information\n"
86 "-T|--Totals Show summary information\n" 107 "-T|--Totals Show summary information\n"
87 "-l|--slabs Show slabs\n" 108 "-v|--validate Validate slabs\n"
88 "-S|--Size Sort by size\n"
89 "-z|--zero Include empty slabs\n" 109 "-z|--zero Include empty slabs\n"
90 "-f|--first-alias Show first alias\n"
91 "-i|--inverted Inverted list\n"
92 "-1|--1ref Single reference\n" 110 "-1|--1ref Single reference\n"
111 "\nValid debug options (FZPUT may be combined)\n"
112 "a / A Switch on all debug options (=FZUP)\n"
113 "- Switch off all debug options\n"
114 "f / F Sanity Checks (SLAB_DEBUG_FREE)\n"
115 "z / Z Redzoning\n"
116 "p / P Poisoning\n"
117 "u / U Tracking\n"
118 "t / T Tracing\n"
93 ); 119 );
94} 120}
95 121
@@ -143,11 +169,10 @@ unsigned long get_obj_and_str(char *name, char **x)
143void set_obj(struct slabinfo *s, char *name, int n) 169void set_obj(struct slabinfo *s, char *name, int n)
144{ 170{
145 char x[100]; 171 char x[100];
172 FILE *f;
146 173
147 sprintf(x, "%s/%s", s->name, name); 174 sprintf(x, "%s/%s", s->name, name);
148 175 f = fopen(x, "w");
149 FILE *f = fopen(x, "w");
150
151 if (!f) 176 if (!f)
152 fatal("Cannot write to %s\n", x); 177 fatal("Cannot write to %s\n", x);
153 178
@@ -155,6 +180,26 @@ void set_obj(struct slabinfo *s, char *name, int n)
155 fclose(f); 180 fclose(f);
156} 181}
157 182
183unsigned long read_slab_obj(struct slabinfo *s, char *name)
184{
185 char x[100];
186 FILE *f;
187 int l;
188
189 sprintf(x, "%s/%s", s->name, name);
190 f = fopen(x, "r");
191 if (!f) {
192 buffer[0] = 0;
193 l = 0;
194 } else {
195 l = fread(buffer, 1, sizeof(buffer), f);
196 buffer[l] = 0;
197 fclose(f);
198 }
199 return l;
200}
201
202
158/* 203/*
159 * Put a size string together 204 * Put a size string together
160 */ 205 */
@@ -226,7 +271,7 @@ int line = 0;
226 271
227void first_line(void) 272void first_line(void)
228{ 273{
229 printf("Name Objects Objsize Space " 274 printf("Name Objects Objsize Space "
230 "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n"); 275 "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n");
231} 276}
232 277
@@ -246,10 +291,7 @@ struct aliasinfo *find_one_alias(struct slabinfo *find)
246 return best; 291 return best;
247 } 292 }
248 } 293 }
249 if (best) 294 return best;
250 return best;
251 fatal("Cannot find alias for %s\n", find->name);
252 return NULL;
253} 295}
254 296
255unsigned long slab_size(struct slabinfo *s) 297unsigned long slab_size(struct slabinfo *s)
@@ -257,6 +299,126 @@ unsigned long slab_size(struct slabinfo *s)
257 return s->slabs * (page_size << s->order); 299 return s->slabs * (page_size << s->order);
258} 300}
259 301
302void slab_numa(struct slabinfo *s, int mode)
303{
304 int node;
305
306 if (strcmp(s->name, "*") == 0)
307 return;
308
309 if (!highest_node) {
310 printf("\n%s: No NUMA information available.\n", s->name);
311 return;
312 }
313
314 if (skip_zero && !s->slabs)
315 return;
316
317 if (!line) {
318 printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
319 for(node = 0; node <= highest_node; node++)
320 printf(" %4d", node);
321 printf("\n----------------------");
322 for(node = 0; node <= highest_node; node++)
323 printf("-----");
324 printf("\n");
325 }
326 printf("%-21s ", mode ? "All slabs" : s->name);
327 for(node = 0; node <= highest_node; node++) {
328 char b[20];
329
330 store_size(b, s->numa[node]);
331 printf(" %4s", b);
332 }
333 printf("\n");
334 if (mode) {
335 printf("%-21s ", "Partial slabs");
336 for(node = 0; node <= highest_node; node++) {
337 char b[20];
338
339 store_size(b, s->numa_partial[node]);
340 printf(" %4s", b);
341 }
342 printf("\n");
343 }
344 line++;
345}
346
347void show_tracking(struct slabinfo *s)
348{
349 printf("\n%s: Kernel object allocation\n", s->name);
350 printf("-----------------------------------------------------------------------\n");
351 if (read_slab_obj(s, "alloc_calls"))
352 printf(buffer);
353 else
354 printf("No Data\n");
355
356 printf("\n%s: Kernel object freeing\n", s->name);
357 printf("------------------------------------------------------------------------\n");
358 if (read_slab_obj(s, "free_calls"))
359 printf(buffer);
360 else
361 printf("No Data\n");
362
363}
364
365void ops(struct slabinfo *s)
366{
367 if (strcmp(s->name, "*") == 0)
368 return;
369
370 if (read_slab_obj(s, "ops")) {
371 printf("\n%s: kmem_cache operations\n", s->name);
372 printf("--------------------------------------------\n");
373 printf(buffer);
374 } else
375 printf("\n%s has no kmem_cache operations\n", s->name);
376}
377
378const char *onoff(int x)
379{
380 if (x)
381 return "On ";
382 return "Off";
383}
384
385void report(struct slabinfo *s)
386{
387 if (strcmp(s->name, "*") == 0)
388 return;
389 printf("\nSlabcache: %-20s Aliases: %2d Order : %2d\n", s->name, s->aliases, s->order);
390 if (s->hwcache_align)
391 printf("** Hardware cacheline aligned\n");
392 if (s->cache_dma)
393 printf("** Memory is allocated in a special DMA zone\n");
394 if (s->destroy_by_rcu)
395 printf("** Slabs are destroyed via RCU\n");
396 if (s->reclaim_account)
397 printf("** Reclaim accounting active\n");
398
399 printf("\nSizes (bytes) Slabs Debug Memory\n");
400 printf("------------------------------------------------------------------------\n");
401 printf("Object : %7d Total : %7ld Sanity Checks : %s Total: %7ld\n",
402 s->object_size, s->slabs, onoff(s->sanity_checks),
403 s->slabs * (page_size << s->order));
404 printf("SlabObj: %7d Full : %7ld Redzoning : %s Used : %7ld\n",
405 s->slab_size, s->slabs - s->partial - s->cpu_slabs,
406 onoff(s->red_zone), s->objects * s->object_size);
407 printf("SlabSiz: %7d Partial: %7ld Poisoning : %s Loss : %7ld\n",
408 page_size << s->order, s->partial, onoff(s->poison),
409 s->slabs * (page_size << s->order) - s->objects * s->object_size);
410 printf("Loss : %7d CpuSlab: %7d Tracking : %s Lalig: %7ld\n",
411 s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user),
412 (s->slab_size - s->object_size) * s->objects);
413 printf("Align : %7d Objects: %7d Tracing : %s Lpadd: %7ld\n",
414 s->align, s->objs_per_slab, onoff(s->trace),
415 ((page_size << s->order) - s->objs_per_slab * s->slab_size) *
416 s->slabs);
417
418 ops(s);
419 show_tracking(s);
420 slab_numa(s, 1);
421}
260 422
261void slabcache(struct slabinfo *s) 423void slabcache(struct slabinfo *s)
262{ 424{
@@ -265,7 +427,18 @@ void slabcache(struct slabinfo *s)
265 char flags[20]; 427 char flags[20];
266 char *p = flags; 428 char *p = flags;
267 429
268 if (skip_zero && !s->slabs) 430 if (strcmp(s->name, "*") == 0)
431 return;
432
433 if (actual_slabs == 1) {
434 report(s);
435 return;
436 }
437
438 if (skip_zero && !show_empty && !s->slabs)
439 return;
440
441 if (show_empty && s->slabs)
269 return; 442 return;
270 443
271 store_size(size_str, slab_size(s)); 444 store_size(size_str, slab_size(s));
@@ -303,48 +476,128 @@ void slabcache(struct slabinfo *s)
303 flags); 476 flags);
304} 477}
305 478
306void slab_numa(struct slabinfo *s) 479/*
480 * Analyze debug options. Return false if something is amiss.
481 */
482int debug_opt_scan(char *opt)
307{ 483{
308 int node; 484 if (!opt || !opt[0] || strcmp(opt, "-") == 0)
485 return 1;
486
487 if (strcasecmp(opt, "a") == 0) {
488 sanity = 1;
489 poison = 1;
490 redzone = 1;
491 tracking = 1;
492 return 1;
493 }
309 494
310 if (!highest_node) 495 for ( ; *opt; opt++)
311 fatal("No NUMA information available.\n"); 496 switch (*opt) {
497 case 'F' : case 'f':
498 if (sanity)
499 return 0;
500 sanity = 1;
501 break;
502 case 'P' : case 'p':
503 if (poison)
504 return 0;
505 poison = 1;
506 break;
312 507
313 if (skip_zero && !s->slabs) 508 case 'Z' : case 'z':
314 return; 509 if (redzone)
510 return 0;
511 redzone = 1;
512 break;
315 513
316 if (!line) { 514 case 'U' : case 'u':
317 printf("\nSlab Node "); 515 if (tracking)
318 for(node = 0; node <= highest_node; node++) 516 return 0;
319 printf(" %4d", node); 517 tracking = 1;
320 printf("\n----------------------"); 518 break;
321 for(node = 0; node <= highest_node; node++)
322 printf("-----");
323 printf("\n");
324 }
325 printf("%-21s ", s->name);
326 for(node = 0; node <= highest_node; node++) {
327 char b[20];
328 519
329 store_size(b, s->numa[node]); 520 case 'T' : case 't':
330 printf(" %4s", b); 521 if (tracing)
331 } 522 return 0;
332 printf("\n"); 523 tracing = 1;
333 line++; 524 break;
525 default:
526 return 0;
527 }
528 return 1;
334} 529}
335 530
336void show_tracking(struct slabinfo *s) 531int slab_empty(struct slabinfo *s)
337{ 532{
338 printf("\n%s: Calls to allocate a slab object\n", s->name); 533 if (s->objects > 0)
339 printf("---------------------------------------------------\n"); 534 return 0;
340 if (read_obj("alloc_calls"))
341 printf(buffer);
342 535
343 printf("%s: Calls to free a slab object\n", s->name); 536 /*
344 printf("-----------------------------------------------\n"); 537 * We may still have slabs even if there are no objects. Shrinking will
345 if (read_obj("free_calls")) 538 * remove them.
346 printf(buffer); 539 */
540 if (s->slabs != 0)
541 set_obj(s, "shrink", 1);
347 542
543 return 1;
544}
545
546void slab_debug(struct slabinfo *s)
547{
548 if (sanity && !s->sanity_checks) {
549 set_obj(s, "sanity", 1);
550 }
551 if (!sanity && s->sanity_checks) {
552 if (slab_empty(s))
553 set_obj(s, "sanity", 0);
554 else
555 fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name);
556 }
557 if (redzone && !s->red_zone) {
558 if (slab_empty(s))
559 set_obj(s, "red_zone", 1);
560 else
561 fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
562 }
563 if (!redzone && s->red_zone) {
564 if (slab_empty(s))
565 set_obj(s, "red_zone", 0);
566 else
567 fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
568 }
569 if (poison && !s->poison) {
570 if (slab_empty(s))
571 set_obj(s, "poison", 1);
572 else
573 fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
574 }
575 if (!poison && s->poison) {
576 if (slab_empty(s))
577 set_obj(s, "poison", 0);
578 else
579 fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
580 }
581 if (tracking && !s->store_user) {
582 if (slab_empty(s))
583 set_obj(s, "store_user", 1);
584 else
585 fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
586 }
587 if (!tracking && s->store_user) {
588 if (slab_empty(s))
589 set_obj(s, "store_user", 0);
590 else
591 fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
592 }
593 if (tracing && !s->trace) {
594 if (slabs == 1)
595 set_obj(s, "trace", 1);
596 else
597 fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);
598 }
599 if (!tracing && s->trace)
600 set_obj(s, "trace", 1);
348} 601}
349 602
350void totals(void) 603void totals(void)
@@ -673,7 +926,7 @@ void link_slabs(void)
673 926
674 for (a = aliasinfo; a < aliasinfo + aliases; a++) { 927 for (a = aliasinfo; a < aliasinfo + aliases; a++) {
675 928
676 for(s = slabinfo; s < slabinfo + slabs; s++) 929 for (s = slabinfo; s < slabinfo + slabs; s++)
677 if (strcmp(a->ref, s->name) == 0) { 930 if (strcmp(a->ref, s->name) == 0) {
678 a->slab = s; 931 a->slab = s;
679 s->refs++; 932 s->refs++;
@@ -704,7 +957,7 @@ void alias(void)
704 continue; 957 continue;
705 } 958 }
706 } 959 }
707 printf("\n%-20s <- %s", a->slab->name, a->name); 960 printf("\n%-12s <- %s", a->slab->name, a->name);
708 active = a->slab->name; 961 active = a->slab->name;
709 } 962 }
710 else 963 else
@@ -729,7 +982,12 @@ void rename_slabs(void)
729 982
730 a = find_one_alias(s); 983 a = find_one_alias(s);
731 984
732 s->name = a->name; 985 if (a)
986 s->name = a->name;
987 else {
988 s->name = "*";
989 actual_slabs--;
990 }
733 } 991 }
734} 992}
735 993
@@ -748,11 +1006,14 @@ void read_slab_dir(void)
748 char *t; 1006 char *t;
749 int count; 1007 int count;
750 1008
1009 if (chdir("/sys/slab"))
1010 fatal("SYSFS support for SLUB not active\n");
1011
751 dir = opendir("."); 1012 dir = opendir(".");
752 while ((de = readdir(dir))) { 1013 while ((de = readdir(dir))) {
753 if (de->d_name[0] == '.' || 1014 if (de->d_name[0] == '.' ||
754 slab_mismatch(de->d_name)) 1015 (de->d_name[0] != ':' && slab_mismatch(de->d_name)))
755 continue; 1016 continue;
756 switch (de->d_type) { 1017 switch (de->d_type) {
757 case DT_LNK: 1018 case DT_LNK:
758 alias->name = strdup(de->d_name); 1019 alias->name = strdup(de->d_name);
@@ -807,6 +1068,7 @@ void read_slab_dir(void)
807 } 1068 }
808 closedir(dir); 1069 closedir(dir);
809 slabs = slab - slabinfo; 1070 slabs = slab - slabinfo;
1071 actual_slabs = slabs;
810 aliases = alias - aliasinfo; 1072 aliases = alias - aliasinfo;
811 if (slabs > MAX_SLABS) 1073 if (slabs > MAX_SLABS)
812 fatal("Too many slabs\n"); 1074 fatal("Too many slabs\n");
@@ -825,34 +1087,37 @@ void output_slabs(void)
825 1087
826 1088
827 if (show_numa) 1089 if (show_numa)
828 slab_numa(slab); 1090 slab_numa(slab, 0);
829 else 1091 else if (show_track)
830 if (show_track)
831 show_tracking(slab); 1092 show_tracking(slab);
832 else 1093 else if (validate)
833 if (validate)
834 slab_validate(slab); 1094 slab_validate(slab);
835 else 1095 else if (shrink)
836 if (shrink)
837 slab_shrink(slab); 1096 slab_shrink(slab);
838 else { 1097 else if (set_debug)
839 if (show_slab) 1098 slab_debug(slab);
840 slabcache(slab); 1099 else if (show_ops)
841 } 1100 ops(slab);
1101 else if (show_slab)
1102 slabcache(slab);
842 } 1103 }
843} 1104}
844 1105
845struct option opts[] = { 1106struct option opts[] = {
846 { "aliases", 0, NULL, 'a' }, 1107 { "aliases", 0, NULL, 'a' },
847 { "slabs", 0, NULL, 'l' }, 1108 { "debug", 2, NULL, 'd' },
848 { "numa", 0, NULL, 'n' }, 1109 { "empty", 0, NULL, 'e' },
849 { "zero", 0, NULL, 'z' },
850 { "help", 0, NULL, 'h' },
851 { "validate", 0, NULL, 'v' },
852 { "first-alias", 0, NULL, 'f' }, 1110 { "first-alias", 0, NULL, 'f' },
1111 { "help", 0, NULL, 'h' },
1112 { "inverted", 0, NULL, 'i'},
1113 { "numa", 0, NULL, 'n' },
1114 { "ops", 0, NULL, 'o' },
1115 { "report", 0, NULL, 'r' },
853 { "shrink", 0, NULL, 's' }, 1116 { "shrink", 0, NULL, 's' },
1117 { "slabs", 0, NULL, 'l' },
854 { "track", 0, NULL, 't'}, 1118 { "track", 0, NULL, 't'},
855 { "inverted", 0, NULL, 'i'}, 1119 { "validate", 0, NULL, 'v' },
1120 { "zero", 0, NULL, 'z' },
856 { "1ref", 0, NULL, '1'}, 1121 { "1ref", 0, NULL, '1'},
857 { NULL, 0, NULL, 0 } 1122 { NULL, 0, NULL, 0 }
858}; 1123};
@@ -864,10 +1129,9 @@ int main(int argc, char *argv[])
864 char *pattern_source; 1129 char *pattern_source;
865 1130
866 page_size = getpagesize(); 1131 page_size = getpagesize();
867 if (chdir("/sys/slab"))
868 fatal("This kernel does not have SLUB support.\n");
869 1132
870 while ((c = getopt_long(argc, argv, "afhil1npstvzTS", opts, NULL)) != -1) 1133 while ((c = getopt_long(argc, argv, "ad::efhil1noprstvzTS",
1134 opts, NULL)) != -1)
871 switch(c) { 1135 switch(c) {
872 case '1': 1136 case '1':
873 show_single_ref = 1; 1137 show_single_ref = 1;
@@ -875,6 +1139,14 @@ int main(int argc, char *argv[])
875 case 'a': 1139 case 'a':
876 show_alias = 1; 1140 show_alias = 1;
877 break; 1141 break;
1142 case 'd':
1143 set_debug = 1;
1144 if (!debug_opt_scan(optarg))
1145 fatal("Invalid debug option '%s'\n", optarg);
1146 break;
1147 case 'e':
1148 show_empty = 1;
1149 break;
878 case 'f': 1150 case 'f':
879 show_first_alias = 1; 1151 show_first_alias = 1;
880 break; 1152 break;
@@ -887,6 +1159,12 @@ int main(int argc, char *argv[])
887 case 'n': 1159 case 'n':
888 show_numa = 1; 1160 show_numa = 1;
889 break; 1161 break;
1162 case 'o':
1163 show_ops = 1;
1164 break;
1165 case 'r':
1166 show_report = 1;
1167 break;
890 case 's': 1168 case 's':
891 shrink = 1; 1169 shrink = 1;
892 break; 1170 break;
@@ -914,8 +1192,8 @@ int main(int argc, char *argv[])
914 1192
915 } 1193 }
916 1194
917 if (!show_slab && !show_alias && !show_track 1195 if (!show_slab && !show_alias && !show_track && !show_report
918 && !validate && !shrink) 1196 && !validate && !shrink && !set_debug && !show_ops)
919 show_slab = 1; 1197 show_slab = 1;
920 1198
921 if (argc > optind) 1199 if (argc > optind)