What does it mean to release a resource with children? Should the children
[mmotm.git] / Documentation / vm / slqbinfo.c
blob3146d3d7c856343971e094794a40b21a3ed2d7fb
1 /*
2 * Slabinfo: Tool to get reports about slabs
4 * (C) 2007 sgi, Christoph Lameter
6 * Reworked by Lin Ming <ming.m.lin@intel.com> for SLQB
8 * Compile by:
10 * gcc -o slabinfo slabinfo.c
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <dirent.h>
16 #include <strings.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <stdarg.h>
20 #include <getopt.h>
21 #include <regex.h>
22 #include <errno.h>
24 #define MAX_SLABS 500
25 #define MAX_ALIASES 500
26 #define MAX_NODES 1024
28 struct slabinfo {
29 char *name;
30 int align, cache_dma, destroy_by_rcu;
31 int hwcache_align, object_size, objs_per_slab;
32 int slab_size, store_user;
33 int order, poison, reclaim_account, red_zone;
34 int batch;
35 unsigned long objects, slabs, total_objects;
36 unsigned long alloc, alloc_slab_fill, alloc_slab_new;
37 unsigned long free, free_remote;
38 unsigned long claim_remote_list, claim_remote_list_objects;
39 unsigned long flush_free_list, flush_free_list_objects, flush_free_list_remote;
40 unsigned long flush_rfree_list, flush_rfree_list_objects;
41 unsigned long flush_slab_free, flush_slab_partial;
42 int numa[MAX_NODES];
43 int numa_partial[MAX_NODES];
44 } slabinfo[MAX_SLABS];
46 int slabs = 0;
47 int actual_slabs = 0;
48 int highest_node = 0;
50 char buffer[4096];
52 int show_empty = 0;
53 int show_report = 0;
54 int show_slab = 0;
55 int skip_zero = 1;
56 int show_numa = 0;
57 int show_track = 0;
58 int validate = 0;
59 int shrink = 0;
60 int show_inverted = 0;
61 int show_totals = 0;
62 int sort_size = 0;
63 int sort_active = 0;
64 int set_debug = 0;
65 int show_ops = 0;
66 int show_activity = 0;
68 /* Debug options */
69 int sanity = 0;
70 int redzone = 0;
71 int poison = 0;
72 int tracking = 0;
73 int tracing = 0;
75 int page_size;
77 regex_t pattern;
79 void fatal(const char *x, ...)
81 va_list ap;
83 va_start(ap, x);
84 vfprintf(stderr, x, ap);
85 va_end(ap);
86 exit(EXIT_FAILURE);
89 void usage(void)
91 printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n"
92 "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
93 "-A|--activity Most active slabs first\n"
94 "-d<options>|--debug=<options> Set/Clear Debug options\n"
95 "-D|--display-active Switch line format to activity\n"
96 "-e|--empty Show empty slabs\n"
97 "-h|--help Show usage information\n"
98 "-i|--inverted Inverted list\n"
99 "-l|--slabs Show slabs\n"
100 "-n|--numa Show NUMA information\n"
101 "-o|--ops Show kmem_cache_ops\n"
102 "-s|--shrink Shrink slabs\n"
103 "-r|--report Detailed report on single slabs\n"
104 "-S|--Size Sort by size\n"
105 "-t|--tracking Show alloc/free information\n"
106 "-T|--Totals Show summary information\n"
107 "-v|--validate Validate slabs\n"
108 "-z|--zero Include empty slabs\n"
109 "\nValid debug options (FZPUT may be combined)\n"
110 "a / A Switch on all debug options (=FZUP)\n"
111 "- Switch off all debug options\n"
112 "f / F Sanity Checks (SLAB_DEBUG_FREE)\n"
113 "z / Z Redzoning\n"
114 "p / P Poisoning\n"
115 "u / U Tracking\n"
116 "t / T Tracing\n"
120 unsigned long read_obj(const char *name)
122 FILE *f = fopen(name, "r");
124 if (!f)
125 buffer[0] = 0;
126 else {
127 if (!fgets(buffer, sizeof(buffer), f))
128 buffer[0] = 0;
129 fclose(f);
130 if (buffer[strlen(buffer)] == '\n')
131 buffer[strlen(buffer)] = 0;
133 return strlen(buffer);
138 * Get the contents of an attribute
140 unsigned long get_obj(const char *name)
142 if (!read_obj(name))
143 return 0;
145 return atol(buffer);
148 unsigned long get_obj_and_str(const char *name, char **x)
150 unsigned long result = 0;
151 char *p;
153 *x = NULL;
155 if (!read_obj(name)) {
156 x = NULL;
157 return 0;
159 result = strtoul(buffer, &p, 10);
160 while (*p == ' ')
161 p++;
162 if (*p)
163 *x = strdup(p);
164 return result;
167 void set_obj(struct slabinfo *s, const char *name, int n)
169 char x[100];
170 FILE *f;
172 snprintf(x, 100, "%s/%s", s->name, name);
173 f = fopen(x, "w");
174 if (!f)
175 fatal("Cannot write to %s\n", x);
177 fprintf(f, "%d\n", n);
178 fclose(f);
181 unsigned long read_slab_obj(struct slabinfo *s, const char *name)
183 char x[100];
184 FILE *f;
185 size_t l;
187 snprintf(x, 100, "%s/%s", s->name, name);
188 f = fopen(x, "r");
189 if (!f) {
190 buffer[0] = 0;
191 l = 0;
192 } else {
193 l = fread(buffer, 1, sizeof(buffer), f);
194 buffer[l] = 0;
195 fclose(f);
197 return l;
202 * Put a size string together
204 int store_size(char *buffer, unsigned long value)
206 unsigned long divisor = 1;
207 char trailer = 0;
208 int n;
210 if (value > 1000000000UL) {
211 divisor = 100000000UL;
212 trailer = 'G';
213 } else if (value > 1000000UL) {
214 divisor = 100000UL;
215 trailer = 'M';
216 } else if (value > 1000UL) {
217 divisor = 100;
218 trailer = 'K';
221 value /= divisor;
222 n = sprintf(buffer, "%ld",value);
223 if (trailer) {
224 buffer[n] = trailer;
225 n++;
226 buffer[n] = 0;
228 if (divisor != 1) {
229 memmove(buffer + n - 2, buffer + n - 3, 4);
230 buffer[n-2] = '.';
231 n++;
233 return n;
236 void decode_numa_list(int *numa, char *t)
238 int node;
239 int nr;
241 memset(numa, 0, MAX_NODES * sizeof(int));
243 if (!t)
244 return;
246 while (*t == 'N') {
247 t++;
248 node = strtoul(t, &t, 10);
249 if (*t == '=') {
250 t++;
251 nr = strtoul(t, &t, 10);
252 numa[node] = nr;
253 if (node > highest_node)
254 highest_node = node;
256 while (*t == ' ')
257 t++;
261 void slab_validate(struct slabinfo *s)
263 if (strcmp(s->name, "*") == 0)
264 return;
266 set_obj(s, "validate", 1);
269 void slab_shrink(struct slabinfo *s)
271 if (strcmp(s->name, "*") == 0)
272 return;
274 set_obj(s, "shrink", 1);
277 int line = 0;
279 void first_line(void)
281 if (show_activity)
282 printf("Name Objects Alloc Free %%Fill %%New "
283 "FlushR %%FlushR FlushR_Objs O\n");
284 else
285 printf("Name Objects Objsize Space "
286 " O/S O %%Ef Batch Flg\n");
289 unsigned long slab_size(struct slabinfo *s)
291 return s->slabs * (page_size << s->order);
294 unsigned long slab_activity(struct slabinfo *s)
296 return s->alloc + s->free;
299 void slab_numa(struct slabinfo *s, int mode)
301 int node;
303 if (strcmp(s->name, "*") == 0)
304 return;
306 if (!highest_node) {
307 printf("\n%s: No NUMA information available.\n", s->name);
308 return;
311 if (skip_zero && !s->slabs)
312 return;
314 if (!line) {
315 printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
316 for(node = 0; node <= highest_node; node++)
317 printf(" %4d", node);
318 printf("\n----------------------");
319 for(node = 0; node <= highest_node; node++)
320 printf("-----");
321 printf("\n");
323 printf("%-21s ", mode ? "All slabs" : s->name);
324 for(node = 0; node <= highest_node; node++) {
325 char b[20];
327 store_size(b, s->numa[node]);
328 printf(" %4s", b);
330 printf("\n");
331 if (mode) {
332 printf("%-21s ", "Partial slabs");
333 for(node = 0; node <= highest_node; node++) {
334 char b[20];
336 store_size(b, s->numa_partial[node]);
337 printf(" %4s", b);
339 printf("\n");
341 line++;
344 void show_tracking(struct slabinfo *s)
346 printf("\n%s: Kernel object allocation\n", s->name);
347 printf("-----------------------------------------------------------------------\n");
348 if (read_slab_obj(s, "alloc_calls"))
349 printf(buffer);
350 else
351 printf("No Data\n");
353 printf("\n%s: Kernel object freeing\n", s->name);
354 printf("------------------------------------------------------------------------\n");
355 if (read_slab_obj(s, "free_calls"))
356 printf(buffer);
357 else
358 printf("No Data\n");
362 void ops(struct slabinfo *s)
364 if (strcmp(s->name, "*") == 0)
365 return;
367 if (read_slab_obj(s, "ops")) {
368 printf("\n%s: kmem_cache operations\n", s->name);
369 printf("--------------------------------------------\n");
370 printf(buffer);
371 } else
372 printf("\n%s has no kmem_cache operations\n", s->name);
375 const char *onoff(int x)
377 if (x)
378 return "On ";
379 return "Off";
382 void slab_stats(struct slabinfo *s)
384 unsigned long total_alloc;
385 unsigned long total_free;
387 total_alloc = s->alloc;
388 total_free = s->free;
390 if (!total_alloc)
391 return;
393 printf("\n");
394 printf("Slab Perf Counter\n");
395 printf("------------------------------------------------------------------------\n");
396 printf("Alloc: %8lu, partial %8lu, page allocator %8lu\n",
397 total_alloc,
398 s->alloc_slab_fill, s->alloc_slab_new);
399 printf("Free: %8lu, partial %8lu, page allocator %8lu, remote %5lu\n",
400 total_free,
401 s->flush_slab_partial,
402 s->flush_slab_free,
403 s->free_remote);
404 printf("Claim: %8lu, objects %8lu\n",
405 s->claim_remote_list,
406 s->claim_remote_list_objects);
407 printf("Flush: %8lu, objects %8lu, remote: %8lu\n",
408 s->flush_free_list,
409 s->flush_free_list_objects,
410 s->flush_free_list_remote);
411 printf("FlushR:%8lu, objects %8lu\n",
412 s->flush_rfree_list,
413 s->flush_rfree_list_objects);
416 void report(struct slabinfo *s)
418 if (strcmp(s->name, "*") == 0)
419 return;
421 printf("\nSlabcache: %-20s Order : %2d Objects: %lu\n",
422 s->name, s->order, s->objects);
423 if (s->hwcache_align)
424 printf("** Hardware cacheline aligned\n");
425 if (s->cache_dma)
426 printf("** Memory is allocated in a special DMA zone\n");
427 if (s->destroy_by_rcu)
428 printf("** Slabs are destroyed via RCU\n");
429 if (s->reclaim_account)
430 printf("** Reclaim accounting active\n");
432 printf("\nSizes (bytes) Slabs Debug Memory\n");
433 printf("------------------------------------------------------------------------\n");
434 printf("Object : %7d Total : %7ld Sanity Checks : %s Total: %7ld\n",
435 s->object_size, s->slabs, "N/A",
436 s->slabs * (page_size << s->order));
437 printf("SlabObj: %7d Full : %7s Redzoning : %s Used : %7ld\n",
438 s->slab_size, "N/A",
439 onoff(s->red_zone), s->objects * s->object_size);
440 printf("SlabSiz: %7d Partial: %7s Poisoning : %s Loss : %7ld\n",
441 page_size << s->order, "N/A", onoff(s->poison),
442 s->slabs * (page_size << s->order) - s->objects * s->object_size);
443 printf("Loss : %7d CpuSlab: %7s Tracking : %s Lalig: %7ld\n",
444 s->slab_size - s->object_size, "N/A", onoff(s->store_user),
445 (s->slab_size - s->object_size) * s->objects);
446 printf("Align : %7d Objects: %7d Tracing : %s Lpadd: %7ld\n",
447 s->align, s->objs_per_slab, "N/A",
448 ((page_size << s->order) - s->objs_per_slab * s->slab_size) *
449 s->slabs);
451 ops(s);
452 show_tracking(s);
453 slab_numa(s, 1);
454 slab_stats(s);
457 void slabcache(struct slabinfo *s)
459 char size_str[20];
460 char flags[20];
461 char *p = flags;
463 if (strcmp(s->name, "*") == 0)
464 return;
466 if (actual_slabs == 1) {
467 report(s);
468 return;
471 if (skip_zero && !show_empty && !s->slabs)
472 return;
474 if (show_empty && s->slabs)
475 return;
477 store_size(size_str, slab_size(s));
479 if (!line++)
480 first_line();
482 if (s->cache_dma)
483 *p++ = 'd';
484 if (s->hwcache_align)
485 *p++ = 'A';
486 if (s->poison)
487 *p++ = 'P';
488 if (s->reclaim_account)
489 *p++ = 'a';
490 if (s->red_zone)
491 *p++ = 'Z';
492 if (s->store_user)
493 *p++ = 'U';
495 *p = 0;
496 if (show_activity) {
497 unsigned long total_alloc;
498 unsigned long total_free;
500 total_alloc = s->alloc;
501 total_free = s->free;
503 printf("%-21s %8ld %10ld %10ld %5ld %5ld %7ld %5ld %7ld %8d\n",
504 s->name, s->objects,
505 total_alloc, total_free,
506 total_alloc ? (s->alloc_slab_fill * 100 / total_alloc) : 0,
507 total_alloc ? (s->alloc_slab_new * 100 / total_alloc) : 0,
508 s->flush_rfree_list,
509 s->flush_rfree_list * 100 / (total_alloc + total_free),
510 s->flush_rfree_list_objects,
511 s->order);
513 else
514 printf("%-21s %8ld %7d %8s %4d %1d %3ld %4d %s\n",
515 s->name, s->objects, s->object_size, size_str,
516 s->objs_per_slab, s->order,
517 s->slabs ? (s->objects * s->object_size * 100) /
518 (s->slabs * (page_size << s->order)) : 100,
519 s->batch, flags);
523 * Analyze debug options. Return false if something is amiss.
525 int debug_opt_scan(char *opt)
527 if (!opt || !opt[0] || strcmp(opt, "-") == 0)
528 return 1;
530 if (strcasecmp(opt, "a") == 0) {
531 sanity = 1;
532 poison = 1;
533 redzone = 1;
534 tracking = 1;
535 return 1;
538 for ( ; *opt; opt++)
539 switch (*opt) {
540 case 'F' : case 'f':
541 if (sanity)
542 return 0;
543 sanity = 1;
544 break;
545 case 'P' : case 'p':
546 if (poison)
547 return 0;
548 poison = 1;
549 break;
551 case 'Z' : case 'z':
552 if (redzone)
553 return 0;
554 redzone = 1;
555 break;
557 case 'U' : case 'u':
558 if (tracking)
559 return 0;
560 tracking = 1;
561 break;
563 case 'T' : case 't':
564 if (tracing)
565 return 0;
566 tracing = 1;
567 break;
568 default:
569 return 0;
571 return 1;
574 int slab_empty(struct slabinfo *s)
576 if (s->objects > 0)
577 return 0;
580 * We may still have slabs even if there are no objects. Shrinking will
581 * remove them.
583 if (s->slabs != 0)
584 set_obj(s, "shrink", 1);
586 return 1;
589 void slab_debug(struct slabinfo *s)
591 if (strcmp(s->name, "*") == 0)
592 return;
594 if (redzone && !s->red_zone) {
595 if (slab_empty(s))
596 set_obj(s, "red_zone", 1);
597 else
598 fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
600 if (!redzone && s->red_zone) {
601 if (slab_empty(s))
602 set_obj(s, "red_zone", 0);
603 else
604 fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
606 if (poison && !s->poison) {
607 if (slab_empty(s))
608 set_obj(s, "poison", 1);
609 else
610 fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
612 if (!poison && s->poison) {
613 if (slab_empty(s))
614 set_obj(s, "poison", 0);
615 else
616 fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
618 if (tracking && !s->store_user) {
619 if (slab_empty(s))
620 set_obj(s, "store_user", 1);
621 else
622 fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
624 if (!tracking && s->store_user) {
625 if (slab_empty(s))
626 set_obj(s, "store_user", 0);
627 else
628 fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
632 void totals(void)
634 struct slabinfo *s;
636 int used_slabs = 0;
637 char b1[20], b2[20], b3[20], b4[20];
638 unsigned long long max = 1ULL << 63;
640 /* Object size */
641 unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
643 /* Number of slabs in a slab cache */
644 unsigned long long min_slabs = max, max_slabs = 0,
645 avg_slabs, total_slabs = 0;
647 /* Size of the whole slab */
648 unsigned long long min_size = max, max_size = 0,
649 avg_size, total_size = 0;
651 /* Bytes used for object storage in a slab */
652 unsigned long long min_used = max, max_used = 0,
653 avg_used, total_used = 0;
655 /* Waste: Bytes used for alignment and padding */
656 unsigned long long min_waste = max, max_waste = 0,
657 avg_waste, total_waste = 0;
658 /* Number of objects in a slab */
659 unsigned long long min_objects = max, max_objects = 0,
660 avg_objects, total_objects = 0;
661 /* Waste per object */
662 unsigned long long min_objwaste = max,
663 max_objwaste = 0, avg_objwaste,
664 total_objwaste = 0;
666 /* Memory per object */
667 unsigned long long min_memobj = max,
668 max_memobj = 0, avg_memobj,
669 total_objsize = 0;
671 for (s = slabinfo; s < slabinfo + slabs; s++) {
672 unsigned long long size;
673 unsigned long used;
674 unsigned long long wasted;
675 unsigned long long objwaste;
677 if (!s->slabs || !s->objects)
678 continue;
680 used_slabs++;
682 size = slab_size(s);
683 used = s->objects * s->object_size;
684 wasted = size - used;
685 objwaste = s->slab_size - s->object_size;
687 if (s->object_size < min_objsize)
688 min_objsize = s->object_size;
689 if (s->slabs < min_slabs)
690 min_slabs = s->slabs;
691 if (size < min_size)
692 min_size = size;
693 if (wasted < min_waste)
694 min_waste = wasted;
695 if (objwaste < min_objwaste)
696 min_objwaste = objwaste;
697 if (s->objects < min_objects)
698 min_objects = s->objects;
699 if (used < min_used)
700 min_used = used;
701 if (s->slab_size < min_memobj)
702 min_memobj = s->slab_size;
704 if (s->object_size > max_objsize)
705 max_objsize = s->object_size;
706 if (s->slabs > max_slabs)
707 max_slabs = s->slabs;
708 if (size > max_size)
709 max_size = size;
710 if (wasted > max_waste)
711 max_waste = wasted;
712 if (objwaste > max_objwaste)
713 max_objwaste = objwaste;
714 if (s->objects > max_objects)
715 max_objects = s->objects;
716 if (used > max_used)
717 max_used = used;
718 if (s->slab_size > max_memobj)
719 max_memobj = s->slab_size;
721 total_slabs += s->slabs;
722 total_size += size;
723 total_waste += wasted;
725 total_objects += s->objects;
726 total_used += used;
728 total_objwaste += s->objects * objwaste;
729 total_objsize += s->objects * s->slab_size;
732 if (!total_objects) {
733 printf("No objects\n");
734 return;
736 if (!used_slabs) {
737 printf("No slabs\n");
738 return;
741 /* Per slab averages */
742 avg_slabs = total_slabs / used_slabs;
743 avg_size = total_size / used_slabs;
744 avg_waste = total_waste / used_slabs;
746 avg_objects = total_objects / used_slabs;
747 avg_used = total_used / used_slabs;
749 /* Per object object sizes */
750 avg_objsize = total_used / total_objects;
751 avg_objwaste = total_objwaste / total_objects;
752 avg_memobj = total_objsize / total_objects;
754 printf("Slabcache Totals\n");
755 printf("----------------\n");
756 printf("Slabcaches : %3d Active: %3d\n",
757 slabs, used_slabs);
759 store_size(b1, total_size);store_size(b2, total_waste);
760 store_size(b3, total_waste * 100 / total_used);
761 printf("Memory used: %6s # Loss : %6s MRatio:%6s%%\n", b1, b2, b3);
763 store_size(b1, total_objects);
764 printf("# Objects : %6s\n", b1);
766 printf("\n");
767 printf("Per Cache Average Min Max Total\n");
768 printf("---------------------------------------------------------\n");
770 store_size(b1, avg_objects);store_size(b2, min_objects);
771 store_size(b3, max_objects);store_size(b4, total_objects);
772 printf("#Objects %10s %10s %10s %10s\n",
773 b1, b2, b3, b4);
775 store_size(b1, avg_slabs);store_size(b2, min_slabs);
776 store_size(b3, max_slabs);store_size(b4, total_slabs);
777 printf("#Slabs %10s %10s %10s %10s\n",
778 b1, b2, b3, b4);
780 store_size(b1, avg_size);store_size(b2, min_size);
781 store_size(b3, max_size);store_size(b4, total_size);
782 printf("Memory %10s %10s %10s %10s\n",
783 b1, b2, b3, b4);
785 store_size(b1, avg_used);store_size(b2, min_used);
786 store_size(b3, max_used);store_size(b4, total_used);
787 printf("Used %10s %10s %10s %10s\n",
788 b1, b2, b3, b4);
790 store_size(b1, avg_waste);store_size(b2, min_waste);
791 store_size(b3, max_waste);store_size(b4, total_waste);
792 printf("Loss %10s %10s %10s %10s\n",
793 b1, b2, b3, b4);
795 printf("\n");
796 printf("Per Object Average Min Max\n");
797 printf("---------------------------------------------\n");
799 store_size(b1, avg_memobj);store_size(b2, min_memobj);
800 store_size(b3, max_memobj);
801 printf("Memory %10s %10s %10s\n",
802 b1, b2, b3);
803 store_size(b1, avg_objsize);store_size(b2, min_objsize);
804 store_size(b3, max_objsize);
805 printf("User %10s %10s %10s\n",
806 b1, b2, b3);
808 store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
809 store_size(b3, max_objwaste);
810 printf("Loss %10s %10s %10s\n",
811 b1, b2, b3);
814 void sort_slabs(void)
816 struct slabinfo *s1,*s2;
818 for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
819 for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
820 int result;
822 if (sort_size)
823 result = slab_size(s1) < slab_size(s2);
824 else if (sort_active)
825 result = slab_activity(s1) < slab_activity(s2);
826 else
827 result = strcasecmp(s1->name, s2->name);
829 if (show_inverted)
830 result = -result;
832 if (result > 0) {
833 struct slabinfo t;
835 memcpy(&t, s1, sizeof(struct slabinfo));
836 memcpy(s1, s2, sizeof(struct slabinfo));
837 memcpy(s2, &t, sizeof(struct slabinfo));
843 int slab_mismatch(char *slab)
845 return regexec(&pattern, slab, 0, NULL, 0);
848 void read_slab_dir(void)
850 DIR *dir;
851 struct dirent *de;
852 struct slabinfo *slab = slabinfo;
853 char *t;
855 if (chdir("/sys/kernel/slab") && chdir("/sys/slab"))
856 fatal("SYSFS support for SLUB not active\n");
858 dir = opendir(".");
859 while ((de = readdir(dir))) {
860 if (de->d_name[0] == '.' ||
861 (de->d_name[0] != ':' && slab_mismatch(de->d_name)))
862 continue;
863 switch (de->d_type) {
864 case DT_DIR:
865 if (chdir(de->d_name))
866 fatal("Unable to access slab %s\n", slab->name);
867 slab->name = strdup(de->d_name);
868 slab->align = get_obj("align");
869 slab->cache_dma = get_obj("cache_dma");
870 slab->destroy_by_rcu = get_obj("destroy_by_rcu");
871 slab->hwcache_align = get_obj("hwcache_align");
872 slab->object_size = get_obj("object_size");
873 slab->objects = get_obj("objects");
874 slab->total_objects = get_obj("total_objects");
875 slab->objs_per_slab = get_obj("objs_per_slab");
876 slab->order = get_obj("order");
877 slab->poison = get_obj("poison");
878 slab->reclaim_account = get_obj("reclaim_account");
879 slab->red_zone = get_obj("red_zone");
880 slab->slab_size = get_obj("slab_size");
881 slab->slabs = get_obj_and_str("slabs", &t);
882 decode_numa_list(slab->numa, t);
883 free(t);
884 slab->store_user = get_obj("store_user");
885 slab->batch = get_obj("batch");
886 slab->alloc = get_obj("alloc");
887 slab->alloc_slab_fill = get_obj("alloc_slab_fill");
888 slab->alloc_slab_new = get_obj("alloc_slab_new");
889 slab->free = get_obj("free");
890 slab->free_remote = get_obj("free_remote");
891 slab->claim_remote_list = get_obj("claim_remote_list");
892 slab->claim_remote_list_objects = get_obj("claim_remote_list_objects");
893 slab->flush_free_list = get_obj("flush_free_list");
894 slab->flush_free_list_objects = get_obj("flush_free_list_objects");
895 slab->flush_free_list_remote = get_obj("flush_free_list_remote");
896 slab->flush_rfree_list = get_obj("flush_rfree_list");
897 slab->flush_rfree_list_objects = get_obj("flush_rfree_list_objects");
898 slab->flush_slab_free = get_obj("flush_slab_free");
899 slab->flush_slab_partial = get_obj("flush_slab_partial");
901 chdir("..");
902 slab++;
903 break;
904 default :
905 fatal("Unknown file type %lx\n", de->d_type);
908 closedir(dir);
909 slabs = slab - slabinfo;
910 actual_slabs = slabs;
911 if (slabs > MAX_SLABS)
912 fatal("Too many slabs\n");
915 void output_slabs(void)
917 struct slabinfo *slab;
919 for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
921 if (show_numa)
922 slab_numa(slab, 0);
923 else if (show_track)
924 show_tracking(slab);
925 else if (validate)
926 slab_validate(slab);
927 else if (shrink)
928 slab_shrink(slab);
929 else if (set_debug)
930 slab_debug(slab);
931 else if (show_ops)
932 ops(slab);
933 else if (show_slab)
934 slabcache(slab);
935 else if (show_report)
936 report(slab);
940 struct option opts[] = {
941 { "activity", 0, NULL, 'A' },
942 { "debug", 2, NULL, 'd' },
943 { "display-activity", 0, NULL, 'D' },
944 { "empty", 0, NULL, 'e' },
945 { "help", 0, NULL, 'h' },
946 { "inverted", 0, NULL, 'i'},
947 { "numa", 0, NULL, 'n' },
948 { "ops", 0, NULL, 'o' },
949 { "report", 0, NULL, 'r' },
950 { "shrink", 0, NULL, 's' },
951 { "slabs", 0, NULL, 'l' },
952 { "track", 0, NULL, 't'},
953 { "validate", 0, NULL, 'v' },
954 { "zero", 0, NULL, 'z' },
955 { "1ref", 0, NULL, '1'},
956 { NULL, 0, NULL, 0 }
959 int main(int argc, char *argv[])
961 int c;
962 int err;
963 char *pattern_source;
965 page_size = getpagesize();
967 while ((c = getopt_long(argc, argv, "Ad::Dehil1noprstvzTS",
968 opts, NULL)) != -1)
969 switch (c) {
970 case 'A':
971 sort_active = 1;
972 break;
973 case 'd':
974 set_debug = 1;
975 if (!debug_opt_scan(optarg))
976 fatal("Invalid debug option '%s'\n", optarg);
977 break;
978 case 'D':
979 show_activity = 1;
980 break;
981 case 'e':
982 show_empty = 1;
983 break;
984 case 'h':
985 usage();
986 return 0;
987 case 'i':
988 show_inverted = 1;
989 break;
990 case 'n':
991 show_numa = 1;
992 break;
993 case 'o':
994 show_ops = 1;
995 break;
996 case 'r':
997 show_report = 1;
998 break;
999 case 's':
1000 shrink = 1;
1001 break;
1002 case 'l':
1003 show_slab = 1;
1004 break;
1005 case 't':
1006 show_track = 1;
1007 break;
1008 case 'v':
1009 validate = 1;
1010 break;
1011 case 'z':
1012 skip_zero = 0;
1013 break;
1014 case 'T':
1015 show_totals = 1;
1016 break;
1017 case 'S':
1018 sort_size = 1;
1019 break;
1021 default:
1022 fatal("%s: Invalid option '%c'\n", argv[0], optopt);
1026 if (!show_slab && !show_track && !show_report
1027 && !validate && !shrink && !set_debug && !show_ops)
1028 show_slab = 1;
1030 if (argc > optind)
1031 pattern_source = argv[optind];
1032 else
1033 pattern_source = ".*";
1035 err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
1036 if (err)
1037 fatal("%s: Invalid pattern '%s' code %d\n",
1038 argv[0], pattern_source, err);
1039 read_slab_dir();
1040 if (show_totals)
1041 totals();
1042 else {
1043 sort_slabs();
1044 output_slabs();
1046 return 0;