Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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