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