Merge tag 'armsoc-dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[sfrench/cifs-2.6.git] / tools / vm / slabinfo.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Slabinfo: Tool to get reports about slabs
4  *
5  * (C) 2007 sgi, Christoph Lameter
6  * (C) 2011 Linux Foundation, Christoph Lameter
7  *
8  * Compile with:
9  *
10  * gcc -o slabinfo slabinfo.c
11  */
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>
23
24 #define MAX_SLABS 500
25 #define MAX_ALIASES 500
26 #define MAX_NODES 1024
27
28 struct slabinfo {
29         char *name;
30         int alias;
31         int refs;
32         int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
33         unsigned int hwcache_align, object_size, objs_per_slab;
34         unsigned int sanity_checks, slab_size, store_user, trace;
35         int order, poison, reclaim_account, red_zone;
36         unsigned long partial, objects, slabs, objects_partial, objects_total;
37         unsigned long alloc_fastpath, alloc_slowpath;
38         unsigned long free_fastpath, free_slowpath;
39         unsigned long free_frozen, free_add_partial, free_remove_partial;
40         unsigned long alloc_from_partial, alloc_slab, free_slab, alloc_refill;
41         unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
42         unsigned long deactivate_to_head, deactivate_to_tail;
43         unsigned long deactivate_remote_frees, order_fallback;
44         unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail;
45         unsigned long alloc_node_mismatch, deactivate_bypass;
46         unsigned long cpu_partial_alloc, cpu_partial_free;
47         int numa[MAX_NODES];
48         int numa_partial[MAX_NODES];
49 } slabinfo[MAX_SLABS];
50
51 struct aliasinfo {
52         char *name;
53         char *ref;
54         struct slabinfo *slab;
55 } aliasinfo[MAX_ALIASES];
56
57 int slabs;
58 int actual_slabs;
59 int aliases;
60 int alias_targets;
61 int highest_node;
62
63 char buffer[4096];
64
65 int show_empty;
66 int show_report;
67 int show_alias;
68 int show_slab;
69 int skip_zero = 1;
70 int show_numa;
71 int show_track;
72 int show_first_alias;
73 int validate;
74 int shrink;
75 int show_inverted;
76 int show_single_ref;
77 int show_totals;
78 int sort_size;
79 int sort_active;
80 int set_debug;
81 int show_ops;
82 int show_activity;
83 int output_lines = -1;
84 int sort_loss;
85 int extended_totals;
86 int show_bytes;
87 int unreclaim_only;
88
89 /* Debug options */
90 int sanity;
91 int redzone;
92 int poison;
93 int tracking;
94 int tracing;
95
96 int page_size;
97
98 regex_t pattern;
99
100 static void fatal(const char *x, ...)
101 {
102         va_list ap;
103
104         va_start(ap, x);
105         vfprintf(stderr, x, ap);
106         va_end(ap);
107         exit(EXIT_FAILURE);
108 }
109
110 static void usage(void)
111 {
112         printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n"
113                 "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
114                 "-a|--aliases           Show aliases\n"
115                 "-A|--activity          Most active slabs first\n"
116                 "-d<options>|--debug=<options> Set/Clear Debug options\n"
117                 "-D|--display-active    Switch line format to activity\n"
118                 "-e|--empty             Show empty slabs\n"
119                 "-f|--first-alias       Show first alias\n"
120                 "-h|--help              Show usage information\n"
121                 "-i|--inverted          Inverted list\n"
122                 "-l|--slabs             Show slabs\n"
123                 "-n|--numa              Show NUMA information\n"
124                 "-o|--ops               Show kmem_cache_ops\n"
125                 "-s|--shrink            Shrink slabs\n"
126                 "-r|--report            Detailed report on single slabs\n"
127                 "-S|--Size              Sort by size\n"
128                 "-t|--tracking          Show alloc/free information\n"
129                 "-T|--Totals            Show summary information\n"
130                 "-v|--validate          Validate slabs\n"
131                 "-z|--zero              Include empty slabs\n"
132                 "-1|--1ref              Single reference\n"
133                 "-N|--lines=K           Show the first K slabs\n"
134                 "-L|--Loss              Sort by loss\n"
135                 "-X|--Xtotals           Show extended summary information\n"
136                 "-B|--Bytes             Show size in bytes\n"
137                 "-U|--Unreclaim         Show unreclaimable slabs only\n"
138                 "\nValid debug options (FZPUT may be combined)\n"
139                 "a / A          Switch on all debug options (=FZUP)\n"
140                 "-              Switch off all debug options\n"
141                 "f / F          Sanity Checks (SLAB_CONSISTENCY_CHECKS)\n"
142                 "z / Z          Redzoning\n"
143                 "p / P          Poisoning\n"
144                 "u / U          Tracking\n"
145                 "t / T          Tracing\n"
146         );
147 }
148
149 static unsigned long read_obj(const char *name)
150 {
151         FILE *f = fopen(name, "r");
152
153         if (!f)
154                 buffer[0] = 0;
155         else {
156                 if (!fgets(buffer, sizeof(buffer), f))
157                         buffer[0] = 0;
158                 fclose(f);
159                 if (buffer[strlen(buffer)] == '\n')
160                         buffer[strlen(buffer)] = 0;
161         }
162         return strlen(buffer);
163 }
164
165
166 /*
167  * Get the contents of an attribute
168  */
169 static unsigned long get_obj(const char *name)
170 {
171         if (!read_obj(name))
172                 return 0;
173
174         return atol(buffer);
175 }
176
177 static unsigned long get_obj_and_str(const char *name, char **x)
178 {
179         unsigned long result = 0;
180         char *p;
181
182         *x = NULL;
183
184         if (!read_obj(name)) {
185                 x = NULL;
186                 return 0;
187         }
188         result = strtoul(buffer, &p, 10);
189         while (*p == ' ')
190                 p++;
191         if (*p)
192                 *x = strdup(p);
193         return result;
194 }
195
196 static void set_obj(struct slabinfo *s, const char *name, int n)
197 {
198         char x[100];
199         FILE *f;
200
201         snprintf(x, 100, "%s/%s", s->name, name);
202         f = fopen(x, "w");
203         if (!f)
204                 fatal("Cannot write to %s\n", x);
205
206         fprintf(f, "%d\n", n);
207         fclose(f);
208 }
209
210 static unsigned long read_slab_obj(struct slabinfo *s, const char *name)
211 {
212         char x[100];
213         FILE *f;
214         size_t l;
215
216         snprintf(x, 100, "%s/%s", s->name, name);
217         f = fopen(x, "r");
218         if (!f) {
219                 buffer[0] = 0;
220                 l = 0;
221         } else {
222                 l = fread(buffer, 1, sizeof(buffer), f);
223                 buffer[l] = 0;
224                 fclose(f);
225         }
226         return l;
227 }
228
229
230 /*
231  * Put a size string together
232  */
233 static int store_size(char *buffer, unsigned long value)
234 {
235         unsigned long divisor = 1;
236         char trailer = 0;
237         int n;
238
239         if (!show_bytes) {
240                 if (value > 1000000000UL) {
241                         divisor = 100000000UL;
242                         trailer = 'G';
243                 } else if (value > 1000000UL) {
244                         divisor = 100000UL;
245                         trailer = 'M';
246                 } else if (value > 1000UL) {
247                         divisor = 100;
248                         trailer = 'K';
249                 }
250         }
251
252         value /= divisor;
253         n = sprintf(buffer, "%ld",value);
254         if (trailer) {
255                 buffer[n] = trailer;
256                 n++;
257                 buffer[n] = 0;
258         }
259         if (divisor != 1) {
260                 memmove(buffer + n - 2, buffer + n - 3, 4);
261                 buffer[n-2] = '.';
262                 n++;
263         }
264         return n;
265 }
266
267 static void decode_numa_list(int *numa, char *t)
268 {
269         int node;
270         int nr;
271
272         memset(numa, 0, MAX_NODES * sizeof(int));
273
274         if (!t)
275                 return;
276
277         while (*t == 'N') {
278                 t++;
279                 node = strtoul(t, &t, 10);
280                 if (*t == '=') {
281                         t++;
282                         nr = strtoul(t, &t, 10);
283                         numa[node] = nr;
284                         if (node > highest_node)
285                                 highest_node = node;
286                 }
287                 while (*t == ' ')
288                         t++;
289         }
290 }
291
292 static void slab_validate(struct slabinfo *s)
293 {
294         if (strcmp(s->name, "*") == 0)
295                 return;
296
297         set_obj(s, "validate", 1);
298 }
299
300 static void slab_shrink(struct slabinfo *s)
301 {
302         if (strcmp(s->name, "*") == 0)
303                 return;
304
305         set_obj(s, "shrink", 1);
306 }
307
308 int line = 0;
309
310 static void first_line(void)
311 {
312         if (show_activity)
313                 printf("Name                   Objects      Alloc       Free"
314                         "   %%Fast Fallb O CmpX   UL\n");
315         else
316                 printf("Name                   Objects Objsize           %s "
317                         "Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n",
318                         sort_loss ? " Loss" : "Space");
319 }
320
321 /*
322  * Find the shortest alias of a slab
323  */
324 static struct aliasinfo *find_one_alias(struct slabinfo *find)
325 {
326         struct aliasinfo *a;
327         struct aliasinfo *best = NULL;
328
329         for(a = aliasinfo;a < aliasinfo + aliases; a++) {
330                 if (a->slab == find &&
331                         (!best || strlen(best->name) < strlen(a->name))) {
332                                 best = a;
333                                 if (strncmp(a->name,"kmall", 5) == 0)
334                                         return best;
335                         }
336         }
337         return best;
338 }
339
340 static unsigned long slab_size(struct slabinfo *s)
341 {
342         return  s->slabs * (page_size << s->order);
343 }
344
345 static unsigned long slab_activity(struct slabinfo *s)
346 {
347         return  s->alloc_fastpath + s->free_fastpath +
348                 s->alloc_slowpath + s->free_slowpath;
349 }
350
351 static unsigned long slab_waste(struct slabinfo *s)
352 {
353         return  slab_size(s) - s->objects * s->object_size;
354 }
355
356 static void slab_numa(struct slabinfo *s, int mode)
357 {
358         int node;
359
360         if (strcmp(s->name, "*") == 0)
361                 return;
362
363         if (!highest_node) {
364                 printf("\n%s: No NUMA information available.\n", s->name);
365                 return;
366         }
367
368         if (skip_zero && !s->slabs)
369                 return;
370
371         if (!line) {
372                 printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
373                 for(node = 0; node <= highest_node; node++)
374                         printf(" %4d", node);
375                 printf("\n----------------------");
376                 for(node = 0; node <= highest_node; node++)
377                         printf("-----");
378                 printf("\n");
379         }
380         printf("%-21s ", mode ? "All slabs" : s->name);
381         for(node = 0; node <= highest_node; node++) {
382                 char b[20];
383
384                 store_size(b, s->numa[node]);
385                 printf(" %4s", b);
386         }
387         printf("\n");
388         if (mode) {
389                 printf("%-21s ", "Partial slabs");
390                 for(node = 0; node <= highest_node; node++) {
391                         char b[20];
392
393                         store_size(b, s->numa_partial[node]);
394                         printf(" %4s", b);
395                 }
396                 printf("\n");
397         }
398         line++;
399 }
400
401 static void show_tracking(struct slabinfo *s)
402 {
403         printf("\n%s: Kernel object allocation\n", s->name);
404         printf("-----------------------------------------------------------------------\n");
405         if (read_slab_obj(s, "alloc_calls"))
406                 printf("%s", buffer);
407         else
408                 printf("No Data\n");
409
410         printf("\n%s: Kernel object freeing\n", s->name);
411         printf("------------------------------------------------------------------------\n");
412         if (read_slab_obj(s, "free_calls"))
413                 printf("%s", buffer);
414         else
415                 printf("No Data\n");
416
417 }
418
419 static void ops(struct slabinfo *s)
420 {
421         if (strcmp(s->name, "*") == 0)
422                 return;
423
424         if (read_slab_obj(s, "ops")) {
425                 printf("\n%s: kmem_cache operations\n", s->name);
426                 printf("--------------------------------------------\n");
427                 printf("%s", buffer);
428         } else
429                 printf("\n%s has no kmem_cache operations\n", s->name);
430 }
431
432 static const char *onoff(int x)
433 {
434         if (x)
435                 return "On ";
436         return "Off";
437 }
438
439 static void slab_stats(struct slabinfo *s)
440 {
441         unsigned long total_alloc;
442         unsigned long total_free;
443         unsigned long total;
444
445         if (!s->alloc_slab)
446                 return;
447
448         total_alloc = s->alloc_fastpath + s->alloc_slowpath;
449         total_free = s->free_fastpath + s->free_slowpath;
450
451         if (!total_alloc)
452                 return;
453
454         printf("\n");
455         printf("Slab Perf Counter       Alloc     Free %%Al %%Fr\n");
456         printf("--------------------------------------------------\n");
457         printf("Fastpath             %8lu %8lu %3lu %3lu\n",
458                 s->alloc_fastpath, s->free_fastpath,
459                 s->alloc_fastpath * 100 / total_alloc,
460                 total_free ? s->free_fastpath * 100 / total_free : 0);
461         printf("Slowpath             %8lu %8lu %3lu %3lu\n",
462                 total_alloc - s->alloc_fastpath, s->free_slowpath,
463                 (total_alloc - s->alloc_fastpath) * 100 / total_alloc,
464                 total_free ? s->free_slowpath * 100 / total_free : 0);
465         printf("Page Alloc           %8lu %8lu %3lu %3lu\n",
466                 s->alloc_slab, s->free_slab,
467                 s->alloc_slab * 100 / total_alloc,
468                 total_free ? s->free_slab * 100 / total_free : 0);
469         printf("Add partial          %8lu %8lu %3lu %3lu\n",
470                 s->deactivate_to_head + s->deactivate_to_tail,
471                 s->free_add_partial,
472                 (s->deactivate_to_head + s->deactivate_to_tail) * 100 / total_alloc,
473                 total_free ? s->free_add_partial * 100 / total_free : 0);
474         printf("Remove partial       %8lu %8lu %3lu %3lu\n",
475                 s->alloc_from_partial, s->free_remove_partial,
476                 s->alloc_from_partial * 100 / total_alloc,
477                 total_free ? s->free_remove_partial * 100 / total_free : 0);
478
479         printf("Cpu partial list     %8lu %8lu %3lu %3lu\n",
480                 s->cpu_partial_alloc, s->cpu_partial_free,
481                 s->cpu_partial_alloc * 100 / total_alloc,
482                 total_free ? s->cpu_partial_free * 100 / total_free : 0);
483
484         printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n",
485                 s->deactivate_remote_frees, s->free_frozen,
486                 s->deactivate_remote_frees * 100 / total_alloc,
487                 total_free ? s->free_frozen * 100 / total_free : 0);
488
489         printf("Total                %8lu %8lu\n\n", total_alloc, total_free);
490
491         if (s->cpuslab_flush)
492                 printf("Flushes %8lu\n", s->cpuslab_flush);
493
494         total = s->deactivate_full + s->deactivate_empty +
495                         s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
496
497         if (total) {
498                 printf("\nSlab Deactivation             Occurrences %%\n");
499                 printf("-------------------------------------------------\n");
500                 printf("Slab full                     %7lu  %3lu%%\n",
501                         s->deactivate_full, (s->deactivate_full * 100) / total);
502                 printf("Slab empty                    %7lu  %3lu%%\n",
503                         s->deactivate_empty, (s->deactivate_empty * 100) / total);
504                 printf("Moved to head of partial list %7lu  %3lu%%\n",
505                         s->deactivate_to_head, (s->deactivate_to_head * 100) / total);
506                 printf("Moved to tail of partial list %7lu  %3lu%%\n",
507                         s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
508                 printf("Deactivation bypass           %7lu  %3lu%%\n",
509                         s->deactivate_bypass, (s->deactivate_bypass * 100) / total);
510                 printf("Refilled from foreign frees   %7lu  %3lu%%\n",
511                         s->alloc_refill, (s->alloc_refill * 100) / total);
512                 printf("Node mismatch                 %7lu  %3lu%%\n",
513                         s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
514         }
515
516         if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) {
517                 printf("\nCmpxchg_double Looping\n------------------------\n");
518                 printf("Locked Cmpxchg Double redos   %lu\nUnlocked Cmpxchg Double redos %lu\n",
519                         s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
520         }
521 }
522
523 static void report(struct slabinfo *s)
524 {
525         if (strcmp(s->name, "*") == 0)
526                 return;
527
528         printf("\nSlabcache: %-15s  Aliases: %2d Order : %2d Objects: %lu\n",
529                 s->name, s->aliases, s->order, s->objects);
530         if (s->hwcache_align)
531                 printf("** Hardware cacheline aligned\n");
532         if (s->cache_dma)
533                 printf("** Memory is allocated in a special DMA zone\n");
534         if (s->destroy_by_rcu)
535                 printf("** Slabs are destroyed via RCU\n");
536         if (s->reclaim_account)
537                 printf("** Reclaim accounting active\n");
538
539         printf("\nSizes (bytes)     Slabs              Debug                Memory\n");
540         printf("------------------------------------------------------------------------\n");
541         printf("Object : %7d  Total  : %7ld   Sanity Checks : %s  Total: %7ld\n",
542                         s->object_size, s->slabs, onoff(s->sanity_checks),
543                         s->slabs * (page_size << s->order));
544         printf("SlabObj: %7d  Full   : %7ld   Redzoning     : %s  Used : %7ld\n",
545                         s->slab_size, s->slabs - s->partial - s->cpu_slabs,
546                         onoff(s->red_zone), s->objects * s->object_size);
547         printf("SlabSiz: %7d  Partial: %7ld   Poisoning     : %s  Loss : %7ld\n",
548                         page_size << s->order, s->partial, onoff(s->poison),
549                         s->slabs * (page_size << s->order) - s->objects * s->object_size);
550         printf("Loss   : %7d  CpuSlab: %7d   Tracking      : %s  Lalig: %7ld\n",
551                         s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user),
552                         (s->slab_size - s->object_size) * s->objects);
553         printf("Align  : %7d  Objects: %7d   Tracing       : %s  Lpadd: %7ld\n",
554                         s->align, s->objs_per_slab, onoff(s->trace),
555                         ((page_size << s->order) - s->objs_per_slab * s->slab_size) *
556                         s->slabs);
557
558         ops(s);
559         show_tracking(s);
560         slab_numa(s, 1);
561         slab_stats(s);
562 }
563
564 static void slabcache(struct slabinfo *s)
565 {
566         char size_str[20];
567         char dist_str[40];
568         char flags[20];
569         char *p = flags;
570
571         if (strcmp(s->name, "*") == 0)
572                 return;
573
574         if (unreclaim_only && s->reclaim_account)
575                 return;
576
577         if (actual_slabs == 1) {
578                 report(s);
579                 return;
580         }
581
582         if (skip_zero && !show_empty && !s->slabs)
583                 return;
584
585         if (show_empty && s->slabs)
586                 return;
587
588         if (sort_loss == 0)
589                 store_size(size_str, slab_size(s));
590         else
591                 store_size(size_str, slab_waste(s));
592         snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs - s->cpu_slabs,
593                                                 s->partial, s->cpu_slabs);
594
595         if (!line++)
596                 first_line();
597
598         if (s->aliases)
599                 *p++ = '*';
600         if (s->cache_dma)
601                 *p++ = 'd';
602         if (s->hwcache_align)
603                 *p++ = 'A';
604         if (s->poison)
605                 *p++ = 'P';
606         if (s->reclaim_account)
607                 *p++ = 'a';
608         if (s->red_zone)
609                 *p++ = 'Z';
610         if (s->sanity_checks)
611                 *p++ = 'F';
612         if (s->store_user)
613                 *p++ = 'U';
614         if (s->trace)
615                 *p++ = 'T';
616
617         *p = 0;
618         if (show_activity) {
619                 unsigned long total_alloc;
620                 unsigned long total_free;
621
622                 total_alloc = s->alloc_fastpath + s->alloc_slowpath;
623                 total_free = s->free_fastpath + s->free_slowpath;
624
625                 printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d %4ld %4ld\n",
626                         s->name, s->objects,
627                         total_alloc, total_free,
628                         total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
629                         total_free ? (s->free_fastpath * 100 / total_free) : 0,
630                         s->order_fallback, s->order, s->cmpxchg_double_fail,
631                         s->cmpxchg_double_cpu_fail);
632         } else {
633                 printf("%-21s %8ld %7d %15s %14s %4d %1d %3ld %3ld %s\n",
634                         s->name, s->objects, s->object_size, size_str, dist_str,
635                         s->objs_per_slab, s->order,
636                         s->slabs ? (s->partial * 100) / s->slabs : 100,
637                         s->slabs ? (s->objects * s->object_size * 100) /
638                                 (s->slabs * (page_size << s->order)) : 100,
639                         flags);
640         }
641 }
642
643 /*
644  * Analyze debug options. Return false if something is amiss.
645  */
646 static int debug_opt_scan(char *opt)
647 {
648         if (!opt || !opt[0] || strcmp(opt, "-") == 0)
649                 return 1;
650
651         if (strcasecmp(opt, "a") == 0) {
652                 sanity = 1;
653                 poison = 1;
654                 redzone = 1;
655                 tracking = 1;
656                 return 1;
657         }
658
659         for ( ; *opt; opt++)
660                 switch (*opt) {
661                 case 'F' : case 'f':
662                         if (sanity)
663                                 return 0;
664                         sanity = 1;
665                         break;
666                 case 'P' : case 'p':
667                         if (poison)
668                                 return 0;
669                         poison = 1;
670                         break;
671
672                 case 'Z' : case 'z':
673                         if (redzone)
674                                 return 0;
675                         redzone = 1;
676                         break;
677
678                 case 'U' : case 'u':
679                         if (tracking)
680                                 return 0;
681                         tracking = 1;
682                         break;
683
684                 case 'T' : case 't':
685                         if (tracing)
686                                 return 0;
687                         tracing = 1;
688                         break;
689                 default:
690                         return 0;
691                 }
692         return 1;
693 }
694
695 static int slab_empty(struct slabinfo *s)
696 {
697         if (s->objects > 0)
698                 return 0;
699
700         /*
701          * We may still have slabs even if there are no objects. Shrinking will
702          * remove them.
703          */
704         if (s->slabs != 0)
705                 set_obj(s, "shrink", 1);
706
707         return 1;
708 }
709
710 static void slab_debug(struct slabinfo *s)
711 {
712         if (strcmp(s->name, "*") == 0)
713                 return;
714
715         if (sanity && !s->sanity_checks) {
716                 set_obj(s, "sanity", 1);
717         }
718         if (!sanity && s->sanity_checks) {
719                 if (slab_empty(s))
720                         set_obj(s, "sanity", 0);
721                 else
722                         fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name);
723         }
724         if (redzone && !s->red_zone) {
725                 if (slab_empty(s))
726                         set_obj(s, "red_zone", 1);
727                 else
728                         fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
729         }
730         if (!redzone && s->red_zone) {
731                 if (slab_empty(s))
732                         set_obj(s, "red_zone", 0);
733                 else
734                         fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
735         }
736         if (poison && !s->poison) {
737                 if (slab_empty(s))
738                         set_obj(s, "poison", 1);
739                 else
740                         fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
741         }
742         if (!poison && s->poison) {
743                 if (slab_empty(s))
744                         set_obj(s, "poison", 0);
745                 else
746                         fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
747         }
748         if (tracking && !s->store_user) {
749                 if (slab_empty(s))
750                         set_obj(s, "store_user", 1);
751                 else
752                         fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
753         }
754         if (!tracking && s->store_user) {
755                 if (slab_empty(s))
756                         set_obj(s, "store_user", 0);
757                 else
758                         fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
759         }
760         if (tracing && !s->trace) {
761                 if (slabs == 1)
762                         set_obj(s, "trace", 1);
763                 else
764                         fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);
765         }
766         if (!tracing && s->trace)
767                 set_obj(s, "trace", 1);
768 }
769
770 static void totals(void)
771 {
772         struct slabinfo *s;
773
774         int used_slabs = 0;
775         char b1[20], b2[20], b3[20], b4[20];
776         unsigned long long max = 1ULL << 63;
777
778         /* Object size */
779         unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
780
781         /* Number of partial slabs in a slabcache */
782         unsigned long long min_partial = max, max_partial = 0,
783                                 avg_partial, total_partial = 0;
784
785         /* Number of slabs in a slab cache */
786         unsigned long long min_slabs = max, max_slabs = 0,
787                                 avg_slabs, total_slabs = 0;
788
789         /* Size of the whole slab */
790         unsigned long long min_size = max, max_size = 0,
791                                 avg_size, total_size = 0;
792
793         /* Bytes used for object storage in a slab */
794         unsigned long long min_used = max, max_used = 0,
795                                 avg_used, total_used = 0;
796
797         /* Waste: Bytes used for alignment and padding */
798         unsigned long long min_waste = max, max_waste = 0,
799                                 avg_waste, total_waste = 0;
800         /* Number of objects in a slab */
801         unsigned long long min_objects = max, max_objects = 0,
802                                 avg_objects, total_objects = 0;
803         /* Waste per object */
804         unsigned long long min_objwaste = max,
805                                 max_objwaste = 0, avg_objwaste,
806                                 total_objwaste = 0;
807
808         /* Memory per object */
809         unsigned long long min_memobj = max,
810                                 max_memobj = 0, avg_memobj,
811                                 total_objsize = 0;
812
813         /* Percentage of partial slabs per slab */
814         unsigned long min_ppart = 100, max_ppart = 0,
815                                 avg_ppart, total_ppart = 0;
816
817         /* Number of objects in partial slabs */
818         unsigned long min_partobj = max, max_partobj = 0,
819                                 avg_partobj, total_partobj = 0;
820
821         /* Percentage of partial objects of all objects in a slab */
822         unsigned long min_ppartobj = 100, max_ppartobj = 0,
823                                 avg_ppartobj, total_ppartobj = 0;
824
825
826         for (s = slabinfo; s < slabinfo + slabs; s++) {
827                 unsigned long long size;
828                 unsigned long used;
829                 unsigned long long wasted;
830                 unsigned long long objwaste;
831                 unsigned long percentage_partial_slabs;
832                 unsigned long percentage_partial_objs;
833
834                 if (!s->slabs || !s->objects)
835                         continue;
836
837                 used_slabs++;
838
839                 size = slab_size(s);
840                 used = s->objects * s->object_size;
841                 wasted = size - used;
842                 objwaste = s->slab_size - s->object_size;
843
844                 percentage_partial_slabs = s->partial * 100 / s->slabs;
845                 if (percentage_partial_slabs > 100)
846                         percentage_partial_slabs = 100;
847
848                 percentage_partial_objs = s->objects_partial * 100
849                                                         / s->objects;
850
851                 if (percentage_partial_objs > 100)
852                         percentage_partial_objs = 100;
853
854                 if (s->object_size < min_objsize)
855                         min_objsize = s->object_size;
856                 if (s->partial < min_partial)
857                         min_partial = s->partial;
858                 if (s->slabs < min_slabs)
859                         min_slabs = s->slabs;
860                 if (size < min_size)
861                         min_size = size;
862                 if (wasted < min_waste)
863                         min_waste = wasted;
864                 if (objwaste < min_objwaste)
865                         min_objwaste = objwaste;
866                 if (s->objects < min_objects)
867                         min_objects = s->objects;
868                 if (used < min_used)
869                         min_used = used;
870                 if (s->objects_partial < min_partobj)
871                         min_partobj = s->objects_partial;
872                 if (percentage_partial_slabs < min_ppart)
873                         min_ppart = percentage_partial_slabs;
874                 if (percentage_partial_objs < min_ppartobj)
875                         min_ppartobj = percentage_partial_objs;
876                 if (s->slab_size < min_memobj)
877                         min_memobj = s->slab_size;
878
879                 if (s->object_size > max_objsize)
880                         max_objsize = s->object_size;
881                 if (s->partial > max_partial)
882                         max_partial = s->partial;
883                 if (s->slabs > max_slabs)
884                         max_slabs = s->slabs;
885                 if (size > max_size)
886                         max_size = size;
887                 if (wasted > max_waste)
888                         max_waste = wasted;
889                 if (objwaste > max_objwaste)
890                         max_objwaste = objwaste;
891                 if (s->objects > max_objects)
892                         max_objects = s->objects;
893                 if (used > max_used)
894                         max_used = used;
895                 if (s->objects_partial > max_partobj)
896                         max_partobj = s->objects_partial;
897                 if (percentage_partial_slabs > max_ppart)
898                         max_ppart = percentage_partial_slabs;
899                 if (percentage_partial_objs > max_ppartobj)
900                         max_ppartobj = percentage_partial_objs;
901                 if (s->slab_size > max_memobj)
902                         max_memobj = s->slab_size;
903
904                 total_partial += s->partial;
905                 total_slabs += s->slabs;
906                 total_size += size;
907                 total_waste += wasted;
908
909                 total_objects += s->objects;
910                 total_used += used;
911                 total_partobj += s->objects_partial;
912                 total_ppart += percentage_partial_slabs;
913                 total_ppartobj += percentage_partial_objs;
914
915                 total_objwaste += s->objects * objwaste;
916                 total_objsize += s->objects * s->slab_size;
917         }
918
919         if (!total_objects) {
920                 printf("No objects\n");
921                 return;
922         }
923         if (!used_slabs) {
924                 printf("No slabs\n");
925                 return;
926         }
927
928         /* Per slab averages */
929         avg_partial = total_partial / used_slabs;
930         avg_slabs = total_slabs / used_slabs;
931         avg_size = total_size / used_slabs;
932         avg_waste = total_waste / used_slabs;
933
934         avg_objects = total_objects / used_slabs;
935         avg_used = total_used / used_slabs;
936         avg_partobj = total_partobj / used_slabs;
937         avg_ppart = total_ppart / used_slabs;
938         avg_ppartobj = total_ppartobj / used_slabs;
939
940         /* Per object object sizes */
941         avg_objsize = total_used / total_objects;
942         avg_objwaste = total_objwaste / total_objects;
943         avg_partobj = total_partobj * 100 / total_objects;
944         avg_memobj = total_objsize / total_objects;
945
946         printf("Slabcache Totals\n");
947         printf("----------------\n");
948         printf("Slabcaches : %15d   Aliases  : %11d->%-3d  Active:    %3d\n",
949                         slabs, aliases, alias_targets, used_slabs);
950
951         store_size(b1, total_size);store_size(b2, total_waste);
952         store_size(b3, total_waste * 100 / total_used);
953         printf("Memory used: %15s   # Loss   : %15s   MRatio:%6s%%\n", b1, b2, b3);
954
955         store_size(b1, total_objects);store_size(b2, total_partobj);
956         store_size(b3, total_partobj * 100 / total_objects);
957         printf("# Objects  : %15s   # PartObj: %15s   ORatio:%6s%%\n", b1, b2, b3);
958
959         printf("\n");
960         printf("Per Cache         Average              "
961                 "Min              Max            Total\n");
962         printf("---------------------------------------"
963                 "-------------------------------------\n");
964
965         store_size(b1, avg_objects);store_size(b2, min_objects);
966         store_size(b3, max_objects);store_size(b4, total_objects);
967         printf("#Objects  %15s  %15s  %15s  %15s\n",
968                         b1,     b2,     b3,     b4);
969
970         store_size(b1, avg_slabs);store_size(b2, min_slabs);
971         store_size(b3, max_slabs);store_size(b4, total_slabs);
972         printf("#Slabs    %15s  %15s  %15s  %15s\n",
973                         b1,     b2,     b3,     b4);
974
975         store_size(b1, avg_partial);store_size(b2, min_partial);
976         store_size(b3, max_partial);store_size(b4, total_partial);
977         printf("#PartSlab %15s  %15s  %15s  %15s\n",
978                         b1,     b2,     b3,     b4);
979         store_size(b1, avg_ppart);store_size(b2, min_ppart);
980         store_size(b3, max_ppart);
981         store_size(b4, total_partial * 100  / total_slabs);
982         printf("%%PartSlab%15s%% %15s%% %15s%% %15s%%\n",
983                         b1,     b2,     b3,     b4);
984
985         store_size(b1, avg_partobj);store_size(b2, min_partobj);
986         store_size(b3, max_partobj);
987         store_size(b4, total_partobj);
988         printf("PartObjs  %15s  %15s  %15s  %15s\n",
989                         b1,     b2,     b3,     b4);
990
991         store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj);
992         store_size(b3, max_ppartobj);
993         store_size(b4, total_partobj * 100 / total_objects);
994         printf("%% PartObj%15s%% %15s%% %15s%% %15s%%\n",
995                         b1,     b2,     b3,     b4);
996
997         store_size(b1, avg_size);store_size(b2, min_size);
998         store_size(b3, max_size);store_size(b4, total_size);
999         printf("Memory    %15s  %15s  %15s  %15s\n",
1000                         b1,     b2,     b3,     b4);
1001
1002         store_size(b1, avg_used);store_size(b2, min_used);
1003         store_size(b3, max_used);store_size(b4, total_used);
1004         printf("Used      %15s  %15s  %15s  %15s\n",
1005                         b1,     b2,     b3,     b4);
1006
1007         store_size(b1, avg_waste);store_size(b2, min_waste);
1008         store_size(b3, max_waste);store_size(b4, total_waste);
1009         printf("Loss      %15s  %15s  %15s  %15s\n",
1010                         b1,     b2,     b3,     b4);
1011
1012         printf("\n");
1013         printf("Per Object        Average              "
1014                 "Min              Max\n");
1015         printf("---------------------------------------"
1016                 "--------------------\n");
1017
1018         store_size(b1, avg_memobj);store_size(b2, min_memobj);
1019         store_size(b3, max_memobj);
1020         printf("Memory    %15s  %15s  %15s\n",
1021                         b1,     b2,     b3);
1022         store_size(b1, avg_objsize);store_size(b2, min_objsize);
1023         store_size(b3, max_objsize);
1024         printf("User      %15s  %15s  %15s\n",
1025                         b1,     b2,     b3);
1026
1027         store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
1028         store_size(b3, max_objwaste);
1029         printf("Loss      %15s  %15s  %15s\n",
1030                         b1,     b2,     b3);
1031 }
1032
1033 static void sort_slabs(void)
1034 {
1035         struct slabinfo *s1,*s2;
1036
1037         for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
1038                 for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
1039                         int result;
1040
1041                         if (sort_size)
1042                                 result = slab_size(s1) < slab_size(s2);
1043                         else if (sort_active)
1044                                 result = slab_activity(s1) < slab_activity(s2);
1045                         else if (sort_loss)
1046                                 result = slab_waste(s1) < slab_waste(s2);
1047                         else
1048                                 result = strcasecmp(s1->name, s2->name);
1049
1050                         if (show_inverted)
1051                                 result = -result;
1052
1053                         if (result > 0) {
1054                                 struct slabinfo t;
1055
1056                                 memcpy(&t, s1, sizeof(struct slabinfo));
1057                                 memcpy(s1, s2, sizeof(struct slabinfo));
1058                                 memcpy(s2, &t, sizeof(struct slabinfo));
1059                         }
1060                 }
1061         }
1062 }
1063
1064 static void sort_aliases(void)
1065 {
1066         struct aliasinfo *a1,*a2;
1067
1068         for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) {
1069                 for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) {
1070                         char *n1, *n2;
1071
1072                         n1 = a1->name;
1073                         n2 = a2->name;
1074                         if (show_alias && !show_inverted) {
1075                                 n1 = a1->ref;
1076                                 n2 = a2->ref;
1077                         }
1078                         if (strcasecmp(n1, n2) > 0) {
1079                                 struct aliasinfo t;
1080
1081                                 memcpy(&t, a1, sizeof(struct aliasinfo));
1082                                 memcpy(a1, a2, sizeof(struct aliasinfo));
1083                                 memcpy(a2, &t, sizeof(struct aliasinfo));
1084                         }
1085                 }
1086         }
1087 }
1088
1089 static void link_slabs(void)
1090 {
1091         struct aliasinfo *a;
1092         struct slabinfo *s;
1093
1094         for (a = aliasinfo; a < aliasinfo + aliases; a++) {
1095
1096                 for (s = slabinfo; s < slabinfo + slabs; s++)
1097                         if (strcmp(a->ref, s->name) == 0) {
1098                                 a->slab = s;
1099                                 s->refs++;
1100                                 break;
1101                         }
1102                 if (s == slabinfo + slabs)
1103                         fatal("Unresolved alias %s\n", a->ref);
1104         }
1105 }
1106
1107 static void alias(void)
1108 {
1109         struct aliasinfo *a;
1110         char *active = NULL;
1111
1112         sort_aliases();
1113         link_slabs();
1114
1115         for(a = aliasinfo; a < aliasinfo + aliases; a++) {
1116
1117                 if (!show_single_ref && a->slab->refs == 1)
1118                         continue;
1119
1120                 if (!show_inverted) {
1121                         if (active) {
1122                                 if (strcmp(a->slab->name, active) == 0) {
1123                                         printf(" %s", a->name);
1124                                         continue;
1125                                 }
1126                         }
1127                         printf("\n%-12s <- %s", a->slab->name, a->name);
1128                         active = a->slab->name;
1129                 }
1130                 else
1131                         printf("%-15s -> %s\n", a->name, a->slab->name);
1132         }
1133         if (active)
1134                 printf("\n");
1135 }
1136
1137
1138 static void rename_slabs(void)
1139 {
1140         struct slabinfo *s;
1141         struct aliasinfo *a;
1142
1143         for (s = slabinfo; s < slabinfo + slabs; s++) {
1144                 if (*s->name != ':')
1145                         continue;
1146
1147                 if (s->refs > 1 && !show_first_alias)
1148                         continue;
1149
1150                 a = find_one_alias(s);
1151
1152                 if (a)
1153                         s->name = a->name;
1154                 else {
1155                         s->name = "*";
1156                         actual_slabs--;
1157                 }
1158         }
1159 }
1160
1161 static int slab_mismatch(char *slab)
1162 {
1163         return regexec(&pattern, slab, 0, NULL, 0);
1164 }
1165
1166 static void read_slab_dir(void)
1167 {
1168         DIR *dir;
1169         struct dirent *de;
1170         struct slabinfo *slab = slabinfo;
1171         struct aliasinfo *alias = aliasinfo;
1172         char *p;
1173         char *t;
1174         int count;
1175
1176         if (chdir("/sys/kernel/slab") && chdir("/sys/slab"))
1177                 fatal("SYSFS support for SLUB not active\n");
1178
1179         dir = opendir(".");
1180         while ((de = readdir(dir))) {
1181                 if (de->d_name[0] == '.' ||
1182                         (de->d_name[0] != ':' && slab_mismatch(de->d_name)))
1183                                 continue;
1184                 switch (de->d_type) {
1185                    case DT_LNK:
1186                         alias->name = strdup(de->d_name);
1187                         count = readlink(de->d_name, buffer, sizeof(buffer)-1);
1188
1189                         if (count < 0)
1190                                 fatal("Cannot read symlink %s\n", de->d_name);
1191
1192                         buffer[count] = 0;
1193                         p = buffer + count;
1194                         while (p > buffer && p[-1] != '/')
1195                                 p--;
1196                         alias->ref = strdup(p);
1197                         alias++;
1198                         break;
1199                    case DT_DIR:
1200                         if (chdir(de->d_name))
1201                                 fatal("Unable to access slab %s\n", slab->name);
1202                         slab->name = strdup(de->d_name);
1203                         slab->alias = 0;
1204                         slab->refs = 0;
1205                         slab->aliases = get_obj("aliases");
1206                         slab->align = get_obj("align");
1207                         slab->cache_dma = get_obj("cache_dma");
1208                         slab->cpu_slabs = get_obj("cpu_slabs");
1209                         slab->destroy_by_rcu = get_obj("destroy_by_rcu");
1210                         slab->hwcache_align = get_obj("hwcache_align");
1211                         slab->object_size = get_obj("object_size");
1212                         slab->objects = get_obj("objects");
1213                         slab->objects_partial = get_obj("objects_partial");
1214                         slab->objects_total = get_obj("objects_total");
1215                         slab->objs_per_slab = get_obj("objs_per_slab");
1216                         slab->order = get_obj("order");
1217                         slab->partial = get_obj("partial");
1218                         slab->partial = get_obj_and_str("partial", &t);
1219                         decode_numa_list(slab->numa_partial, t);
1220                         free(t);
1221                         slab->poison = get_obj("poison");
1222                         slab->reclaim_account = get_obj("reclaim_account");
1223                         slab->red_zone = get_obj("red_zone");
1224                         slab->sanity_checks = get_obj("sanity_checks");
1225                         slab->slab_size = get_obj("slab_size");
1226                         slab->slabs = get_obj_and_str("slabs", &t);
1227                         decode_numa_list(slab->numa, t);
1228                         free(t);
1229                         slab->store_user = get_obj("store_user");
1230                         slab->trace = get_obj("trace");
1231                         slab->alloc_fastpath = get_obj("alloc_fastpath");
1232                         slab->alloc_slowpath = get_obj("alloc_slowpath");
1233                         slab->free_fastpath = get_obj("free_fastpath");
1234                         slab->free_slowpath = get_obj("free_slowpath");
1235                         slab->free_frozen= get_obj("free_frozen");
1236                         slab->free_add_partial = get_obj("free_add_partial");
1237                         slab->free_remove_partial = get_obj("free_remove_partial");
1238                         slab->alloc_from_partial = get_obj("alloc_from_partial");
1239                         slab->alloc_slab = get_obj("alloc_slab");
1240                         slab->alloc_refill = get_obj("alloc_refill");
1241                         slab->free_slab = get_obj("free_slab");
1242                         slab->cpuslab_flush = get_obj("cpuslab_flush");
1243                         slab->deactivate_full = get_obj("deactivate_full");
1244                         slab->deactivate_empty = get_obj("deactivate_empty");
1245                         slab->deactivate_to_head = get_obj("deactivate_to_head");
1246                         slab->deactivate_to_tail = get_obj("deactivate_to_tail");
1247                         slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
1248                         slab->order_fallback = get_obj("order_fallback");
1249                         slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail");
1250                         slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail");
1251                         slab->cpu_partial_alloc = get_obj("cpu_partial_alloc");
1252                         slab->cpu_partial_free = get_obj("cpu_partial_free");
1253                         slab->alloc_node_mismatch = get_obj("alloc_node_mismatch");
1254                         slab->deactivate_bypass = get_obj("deactivate_bypass");
1255                         chdir("..");
1256                         if (slab->name[0] == ':')
1257                                 alias_targets++;
1258                         slab++;
1259                         break;
1260                    default :
1261                         fatal("Unknown file type %lx\n", de->d_type);
1262                 }
1263         }
1264         closedir(dir);
1265         slabs = slab - slabinfo;
1266         actual_slabs = slabs;
1267         aliases = alias - aliasinfo;
1268         if (slabs > MAX_SLABS)
1269                 fatal("Too many slabs\n");
1270         if (aliases > MAX_ALIASES)
1271                 fatal("Too many aliases\n");
1272 }
1273
1274 static void output_slabs(void)
1275 {
1276         struct slabinfo *slab;
1277         int lines = output_lines;
1278
1279         for (slab = slabinfo; (slab < slabinfo + slabs) &&
1280                         lines != 0; slab++) {
1281
1282                 if (slab->alias)
1283                         continue;
1284
1285                 if (lines != -1)
1286                         lines--;
1287
1288                 if (show_numa)
1289                         slab_numa(slab, 0);
1290                 else if (show_track)
1291                         show_tracking(slab);
1292                 else if (validate)
1293                         slab_validate(slab);
1294                 else if (shrink)
1295                         slab_shrink(slab);
1296                 else if (set_debug)
1297                         slab_debug(slab);
1298                 else if (show_ops)
1299                         ops(slab);
1300                 else if (show_slab)
1301                         slabcache(slab);
1302                 else if (show_report)
1303                         report(slab);
1304         }
1305 }
1306
1307 static void xtotals(void)
1308 {
1309         totals();
1310
1311         link_slabs();
1312         rename_slabs();
1313
1314         printf("\nSlabs sorted by size\n");
1315         printf("--------------------\n");
1316         sort_loss = 0;
1317         sort_size = 1;
1318         sort_slabs();
1319         output_slabs();
1320
1321         printf("\nSlabs sorted by loss\n");
1322         printf("--------------------\n");
1323         line = 0;
1324         sort_loss = 1;
1325         sort_size = 0;
1326         sort_slabs();
1327         output_slabs();
1328         printf("\n");
1329 }
1330
1331 struct option opts[] = {
1332         { "aliases", no_argument, NULL, 'a' },
1333         { "activity", no_argument, NULL, 'A' },
1334         { "debug", optional_argument, NULL, 'd' },
1335         { "display-activity", no_argument, NULL, 'D' },
1336         { "empty", no_argument, NULL, 'e' },
1337         { "first-alias", no_argument, NULL, 'f' },
1338         { "help", no_argument, NULL, 'h' },
1339         { "inverted", no_argument, NULL, 'i'},
1340         { "slabs", no_argument, NULL, 'l' },
1341         { "numa", no_argument, NULL, 'n' },
1342         { "ops", no_argument, NULL, 'o' },
1343         { "shrink", no_argument, NULL, 's' },
1344         { "report", no_argument, NULL, 'r' },
1345         { "Size", no_argument, NULL, 'S'},
1346         { "tracking", no_argument, NULL, 't'},
1347         { "Totals", no_argument, NULL, 'T'},
1348         { "validate", no_argument, NULL, 'v' },
1349         { "zero", no_argument, NULL, 'z' },
1350         { "1ref", no_argument, NULL, '1'},
1351         { "lines", required_argument, NULL, 'N'},
1352         { "Loss", no_argument, NULL, 'L'},
1353         { "Xtotals", no_argument, NULL, 'X'},
1354         { "Bytes", no_argument, NULL, 'B'},
1355         { "Unreclaim", no_argument, NULL, 'U'},
1356         { NULL, 0, NULL, 0 }
1357 };
1358
1359 int main(int argc, char *argv[])
1360 {
1361         int c;
1362         int err;
1363         char *pattern_source;
1364
1365         page_size = getpagesize();
1366
1367         while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTSN:LXBU",
1368                                                 opts, NULL)) != -1)
1369                 switch (c) {
1370                 case '1':
1371                         show_single_ref = 1;
1372                         break;
1373                 case 'a':
1374                         show_alias = 1;
1375                         break;
1376                 case 'A':
1377                         sort_active = 1;
1378                         break;
1379                 case 'd':
1380                         set_debug = 1;
1381                         if (!debug_opt_scan(optarg))
1382                                 fatal("Invalid debug option '%s'\n", optarg);
1383                         break;
1384                 case 'D':
1385                         show_activity = 1;
1386                         break;
1387                 case 'e':
1388                         show_empty = 1;
1389                         break;
1390                 case 'f':
1391                         show_first_alias = 1;
1392                         break;
1393                 case 'h':
1394                         usage();
1395                         return 0;
1396                 case 'i':
1397                         show_inverted = 1;
1398                         break;
1399                 case 'n':
1400                         show_numa = 1;
1401                         break;
1402                 case 'o':
1403                         show_ops = 1;
1404                         break;
1405                 case 'r':
1406                         show_report = 1;
1407                         break;
1408                 case 's':
1409                         shrink = 1;
1410                         break;
1411                 case 'l':
1412                         show_slab = 1;
1413                         break;
1414                 case 't':
1415                         show_track = 1;
1416                         break;
1417                 case 'v':
1418                         validate = 1;
1419                         break;
1420                 case 'z':
1421                         skip_zero = 0;
1422                         break;
1423                 case 'T':
1424                         show_totals = 1;
1425                         break;
1426                 case 'S':
1427                         sort_size = 1;
1428                         break;
1429                 case 'N':
1430                         if (optarg) {
1431                                 output_lines = atoi(optarg);
1432                                 if (output_lines < 1)
1433                                         output_lines = 1;
1434                         }
1435                         break;
1436                 case 'L':
1437                         sort_loss = 1;
1438                         break;
1439                 case 'X':
1440                         if (output_lines == -1)
1441                                 output_lines = 1;
1442                         extended_totals = 1;
1443                         show_bytes = 1;
1444                         break;
1445                 case 'B':
1446                         show_bytes = 1;
1447                         break;
1448                 case 'U':
1449                         unreclaim_only = 1;
1450                         break;
1451                 default:
1452                         fatal("%s: Invalid option '%c'\n", argv[0], optopt);
1453
1454         }
1455
1456         if (!show_slab && !show_alias && !show_track && !show_report
1457                 && !validate && !shrink && !set_debug && !show_ops)
1458                         show_slab = 1;
1459
1460         if (argc > optind)
1461                 pattern_source = argv[optind];
1462         else
1463                 pattern_source = ".*";
1464
1465         err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
1466         if (err)
1467                 fatal("%s: Invalid pattern '%s' code %d\n",
1468                         argv[0], pattern_source, err);
1469         read_slab_dir();
1470         if (show_alias) {
1471                 alias();
1472         } else if (extended_totals) {
1473                 xtotals();
1474         } else if (show_totals) {
1475                 totals();
1476         } else {
1477                 link_slabs();
1478                 rename_slabs();
1479                 sort_slabs();
1480                 output_slabs();
1481         }
1482         return 0;
1483 }