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