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