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