Based on kernel version 2.6.26. Page generated on 2008-07-16 21:13 EST.
1 /* 2 * Slabinfo: Tool to get reports about slabs 3 * 4 * (C) 2007 sgi, Christoph Lameter <clameter[AT]sgi[DOT]com> 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 26 struct 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; 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; 42 int numa[MAX_NODES]; 43 int numa_partial[MAX_NODES]; 44 } slabinfo[MAX_SLABS]; 45 46 struct aliasinfo { 47 char *name; 48 char *ref; 49 struct slabinfo *slab; 50 } aliasinfo[MAX_ALIASES]; 51 52 int slabs = 0; 53 int actual_slabs = 0; 54 int aliases = 0; 55 int alias_targets = 0; 56 int highest_node = 0; 57 58 char buffer[4096]; 59 60 int show_empty = 0; 61 int show_report = 0; 62 int show_alias = 0; 63 int show_slab = 0; 64 int skip_zero = 1; 65 int show_numa = 0; 66 int show_track = 0; 67 int show_first_alias = 0; 68 int validate = 0; 69 int shrink = 0; 70 int show_inverted = 0; 71 int show_single_ref = 0; 72 int show_totals = 0; 73 int sort_size = 0; 74 int sort_active = 0; 75 int set_debug = 0; 76 int show_ops = 0; 77 int show_activity = 0; 78 79 /* Debug options */ 80 int sanity = 0; 81 int redzone = 0; 82 int poison = 0; 83 int tracking = 0; 84 int tracing = 0; 85 86 int page_size; 87 88 regex_t pattern; 89 90 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 100 void usage(void) 101 { 102 printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter[AT]sgi[DOT]com\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 134 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 */ 154 unsigned long get_obj(const char *name) 155 { 156 if (!read_obj(name)) 157 return 0; 158 159 return atol(buffer); 160 } 161 162 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 181 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 195 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 */ 218 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 250 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 275 void slab_validate(struct slabinfo *s) 276 { 277 if (strcmp(s->name, "*") == 0) 278 return; 279 280 set_obj(s, "validate", 1); 281 } 282 283 void slab_shrink(struct slabinfo *s) 284 { 285 if (strcmp(s->name, "*") == 0) 286 return; 287 288 set_obj(s, "shrink", 1); 289 } 290 291 int line = 0; 292 293 void first_line(void) 294 { 295 if (show_activity) 296 printf("Name Objects Alloc Free %%Fast\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 */ 305 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 321 unsigned long slab_size(struct slabinfo *s) 322 { 323 return s->slabs * (page_size << s->order); 324 } 325 326 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 332 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 377 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 395 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 408 const char *onoff(int x) 409 { 410 if (x) 411 return "On "; 412 return "Off"; 413 } 414 415 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 480 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 521 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->partial, s->cpu_slabs); 544 545 if (!line++) 546 first_line(); 547 548 if (s->aliases) 549 *p++ = '*'; 550 if (s->cache_dma) 551 *p++ = 'd'; 552 if (s->hwcache_align) 553 *p++ = 'A'; 554 if (s->poison) 555 *p++ = 'P'; 556 if (s->reclaim_account) 557 *p++ = 'a'; 558 if (s->red_zone) 559 *p++ = 'Z'; 560 if (s->sanity_checks) 561 *p++ = 'F'; 562 if (s->store_user) 563 *p++ = 'U'; 564 if (s->trace) 565 *p++ = 'T'; 566 567 *p = 0; 568 if (show_activity) { 569 unsigned long total_alloc; 570 unsigned long total_free; 571 572 total_alloc = s->alloc_fastpath + s->alloc_slowpath; 573 total_free = s->free_fastpath + s->free_slowpath; 574 575 printf("%-21s %8ld %8ld %8ld %3ld %3ld \n", 576 s->name, s->objects, 577 total_alloc, total_free, 578 total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0, 579 total_free ? (s->free_fastpath * 100 / total_free) : 0); 580 } 581 else 582 printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n", 583 s->name, s->objects, s->object_size, size_str, dist_str, 584 s->objs_per_slab, s->order, 585 s->slabs ? (s->partial * 100) / s->slabs : 100, 586 s->slabs ? (s->objects * s->object_size * 100) / 587 (s->slabs * (page_size << s->order)) : 100, 588 flags); 589 } 590 591 /* 592 * Analyze debug options. Return false if something is amiss. 593 */ 594 int debug_opt_scan(char *opt) 595 { 596 if (!opt || !opt[0] || strcmp(opt, "-") == 0) 597 return 1; 598 599 if (strcasecmp(opt, "a") == 0) { 600 sanity = 1; 601 poison = 1; 602 redzone = 1; 603 tracking = 1; 604 return 1; 605 } 606 607 for ( ; *opt; opt++) 608 switch (*opt) { 609 case 'F' : case 'f': 610 if (sanity) 611 return 0; 612 sanity = 1; 613 break; 614 case 'P' : case 'p': 615 if (poison) 616 return 0; 617 poison = 1; 618 break; 619 620 case 'Z' : case 'z': 621 if (redzone) 622 return 0; 623 redzone = 1; 624 break; 625 626 case 'U' : case 'u': 627 if (tracking) 628 return 0; 629 tracking = 1; 630 break; 631 632 case 'T' : case 't': 633 if (tracing) 634 return 0; 635 tracing = 1; 636 break; 637 default: 638 return 0; 639 } 640 return 1; 641 } 642 643 int slab_empty(struct slabinfo *s) 644 { 645 if (s->objects > 0) 646 return 0; 647 648 /* 649 * We may still have slabs even if there are no objects. Shrinking will 650 * remove them. 651 */ 652 if (s->slabs != 0) 653 set_obj(s, "shrink", 1); 654 655 return 1; 656 } 657 658 void slab_debug(struct slabinfo *s) 659 { 660 if (strcmp(s->name, "*") == 0) 661 return; 662 663 if (sanity && !s->sanity_checks) { 664 set_obj(s, "sanity", 1); 665 } 666 if (!sanity && s->sanity_checks) { 667 if (slab_empty(s)) 668 set_obj(s, "sanity", 0); 669 else 670 fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name); 671 } 672 if (redzone && !s->red_zone) { 673 if (slab_empty(s)) 674 set_obj(s, "red_zone", 1); 675 else 676 fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name); 677 } 678 if (!redzone && s->red_zone) { 679 if (slab_empty(s)) 680 set_obj(s, "red_zone", 0); 681 else 682 fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name); 683 } 684 if (poison && !s->poison) { 685 if (slab_empty(s)) 686 set_obj(s, "poison", 1); 687 else 688 fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name); 689 } 690 if (!poison && s->poison) { 691 if (slab_empty(s)) 692 set_obj(s, "poison", 0); 693 else 694 fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name); 695 } 696 if (tracking && !s->store_user) { 697 if (slab_empty(s)) 698 set_obj(s, "store_user", 1); 699 else 700 fprintf(stderr, "%s not empty cannot enable tracking\n", s->name); 701 } 702 if (!tracking && s->store_user) { 703 if (slab_empty(s)) 704 set_obj(s, "store_user", 0); 705 else 706 fprintf(stderr, "%s not empty cannot disable tracking\n", s->name); 707 } 708 if (tracing && !s->trace) { 709 if (slabs == 1) 710 set_obj(s, "trace", 1); 711 else 712 fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name); 713 } 714 if (!tracing && s->trace) 715 set_obj(s, "trace", 1); 716 } 717 718 void totals(void) 719 { 720 struct slabinfo *s; 721 722 int used_slabs = 0; 723 char b1[20], b2[20], b3[20], b4[20]; 724 unsigned long long max = 1ULL << 63; 725 726 /* Object size */ 727 unsigned long long min_objsize = max, max_objsize = 0, avg_objsize; 728 729 /* Number of partial slabs in a slabcache */ 730 unsigned long long min_partial = max, max_partial = 0, 731 avg_partial, total_partial = 0; 732 733 /* Number of slabs in a slab cache */ 734 unsigned long long min_slabs = max, max_slabs = 0, 735 avg_slabs, total_slabs = 0; 736 737 /* Size of the whole slab */ 738 unsigned long long min_size = max, max_size = 0, 739 avg_size, total_size = 0; 740 741 /* Bytes used for object storage in a slab */ 742 unsigned long long min_used = max, max_used = 0, 743 avg_used, total_used = 0; 744 745 /* Waste: Bytes used for alignment and padding */ 746 unsigned long long min_waste = max, max_waste = 0, 747 avg_waste, total_waste = 0; 748 /* Number of objects in a slab */ 749 unsigned long long min_objects = max, max_objects = 0, 750 avg_objects, total_objects = 0; 751 /* Waste per object */ 752 unsigned long long min_objwaste = max, 753 max_objwaste = 0, avg_objwaste, 754 total_objwaste = 0; 755 756 /* Memory per object */ 757 unsigned long long min_memobj = max, 758 max_memobj = 0, avg_memobj, 759 total_objsize = 0; 760 761 /* Percentage of partial slabs per slab */ 762 unsigned long min_ppart = 100, max_ppart = 0, 763 avg_ppart, total_ppart = 0; 764 765 /* Number of objects in partial slabs */ 766 unsigned long min_partobj = max, max_partobj = 0, 767 avg_partobj, total_partobj = 0; 768 769 /* Percentage of partial objects of all objects in a slab */ 770 unsigned long min_ppartobj = 100, max_ppartobj = 0, 771 avg_ppartobj, total_ppartobj = 0; 772 773 774 for (s = slabinfo; s < slabinfo + slabs; s++) { 775 unsigned long long size; 776 unsigned long used; 777 unsigned long long wasted; 778 unsigned long long objwaste; 779 long long objects_in_partial_slabs; 780 unsigned long percentage_partial_slabs; 781 unsigned long percentage_partial_objs; 782 783 if (!s->slabs || !s->objects) 784 continue; 785 786 used_slabs++; 787 788 size = slab_size(s); 789 used = s->objects * s->object_size; 790 wasted = size - used; 791 objwaste = s->slab_size - s->object_size; 792 793 objects_in_partial_slabs = s->objects - 794 (s->slabs - s->partial - s ->cpu_slabs) * 795 s->objs_per_slab; 796 797 if (objects_in_partial_slabs < 0) 798 objects_in_partial_slabs = 0; 799 800 percentage_partial_slabs = s->partial * 100 / s->slabs; 801 if (percentage_partial_slabs > 100) 802 percentage_partial_slabs = 100; 803 804 percentage_partial_objs = objects_in_partial_slabs * 100 805 / s->objects; 806 807 if (percentage_partial_objs > 100) 808 percentage_partial_objs = 100; 809 810 if (s->object_size < min_objsize) 811 min_objsize = s->object_size; 812 if (s->partial < min_partial) 813 min_partial = s->partial; 814 if (s->slabs < min_slabs) 815 min_slabs = s->slabs; 816 if (size < min_size) 817 min_size = size; 818 if (wasted < min_waste) 819 min_waste = wasted; 820 if (objwaste < min_objwaste) 821 min_objwaste = objwaste; 822 if (s->objects < min_objects) 823 min_objects = s->objects; 824 if (used < min_used) 825 min_used = used; 826 if (objects_in_partial_slabs < min_partobj) 827 min_partobj = objects_in_partial_slabs; 828 if (percentage_partial_slabs < min_ppart) 829 min_ppart = percentage_partial_slabs; 830 if (percentage_partial_objs < min_ppartobj) 831 min_ppartobj = percentage_partial_objs; 832 if (s->slab_size < min_memobj) 833 min_memobj = s->slab_size; 834 835 if (s->object_size > max_objsize) 836 max_objsize = s->object_size; 837 if (s->partial > max_partial) 838 max_partial = s->partial; 839 if (s->slabs > max_slabs) 840 max_slabs = s->slabs; 841 if (size > max_size) 842 max_size = size; 843 if (wasted > max_waste) 844 max_waste = wasted; 845 if (objwaste > max_objwaste) 846 max_objwaste = objwaste; 847 if (s->objects > max_objects) 848 max_objects = s->objects; 849 if (used > max_used) 850 max_used = used; 851 if (objects_in_partial_slabs > max_partobj) 852 max_partobj = objects_in_partial_slabs; 853 if (percentage_partial_slabs > max_ppart) 854 max_ppart = percentage_partial_slabs; 855 if (percentage_partial_objs > max_ppartobj) 856 max_ppartobj = percentage_partial_objs; 857 if (s->slab_size > max_memobj) 858 max_memobj = s->slab_size; 859 860 total_partial += s->partial; 861 total_slabs += s->slabs; 862 total_size += size; 863 total_waste += wasted; 864 865 total_objects += s->objects; 866 total_used += used; 867 total_partobj += objects_in_partial_slabs; 868 total_ppart += percentage_partial_slabs; 869 total_ppartobj += percentage_partial_objs; 870 871 total_objwaste += s->objects * objwaste; 872 total_objsize += s->objects * s->slab_size; 873 } 874 875 if (!total_objects) { 876 printf("No objects\n"); 877 return; 878 } 879 if (!used_slabs) { 880 printf("No slabs\n"); 881 return; 882 } 883 884 /* Per slab averages */ 885 avg_partial = total_partial / used_slabs; 886 avg_slabs = total_slabs / used_slabs; 887 avg_size = total_size / used_slabs; 888 avg_waste = total_waste / used_slabs; 889 890 avg_objects = total_objects / used_slabs; 891 avg_used = total_used / used_slabs; 892 avg_partobj = total_partobj / used_slabs; 893 avg_ppart = total_ppart / used_slabs; 894 avg_ppartobj = total_ppartobj / used_slabs; 895 896 /* Per object object sizes */ 897 avg_objsize = total_used / total_objects; 898 avg_objwaste = total_objwaste / total_objects; 899 avg_partobj = total_partobj * 100 / total_objects; 900 avg_memobj = total_objsize / total_objects; 901 902 printf("Slabcache Totals\n"); 903 printf("----------------\n"); 904 printf("Slabcaches : %3d Aliases : %3d->%-3d Active: %3d\n", 905 slabs, aliases, alias_targets, used_slabs); 906 907 store_size(b1, total_size);store_size(b2, total_waste); 908 store_size(b3, total_waste * 100 / total_used); 909 printf("Memory used: %6s # Loss : %6s MRatio:%6s%%\n", b1, b2, b3); 910 911 store_size(b1, total_objects);store_size(b2, total_partobj); 912 store_size(b3, total_partobj * 100 / total_objects); 913 printf("# Objects : %6s # PartObj: %6s ORatio:%6s%%\n", b1, b2, b3); 914 915 printf("\n"); 916 printf("Per Cache Average Min Max Total\n"); 917 printf("---------------------------------------------------------\n"); 918 919 store_size(b1, avg_objects);store_size(b2, min_objects); 920 store_size(b3, max_objects);store_size(b4, total_objects); 921 printf("#Objects %10s %10s %10s %10s\n", 922 b1, b2, b3, b4); 923 924 store_size(b1, avg_slabs);store_size(b2, min_slabs); 925 store_size(b3, max_slabs);store_size(b4, total_slabs); 926 printf("#Slabs %10s %10s %10s %10s\n", 927 b1, b2, b3, b4); 928 929 store_size(b1, avg_partial);store_size(b2, min_partial); 930 store_size(b3, max_partial);store_size(b4, total_partial); 931 printf("#PartSlab %10s %10s %10s %10s\n", 932 b1, b2, b3, b4); 933 store_size(b1, avg_ppart);store_size(b2, min_ppart); 934 store_size(b3, max_ppart); 935 store_size(b4, total_partial * 100 / total_slabs); 936 printf("%%PartSlab%10s%% %10s%% %10s%% %10s%%\n", 937 b1, b2, b3, b4); 938 939 store_size(b1, avg_partobj);store_size(b2, min_partobj); 940 store_size(b3, max_partobj); 941 store_size(b4, total_partobj); 942 printf("PartObjs %10s %10s %10s %10s\n", 943 b1, b2, b3, b4); 944 945 store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj); 946 store_size(b3, max_ppartobj); 947 store_size(b4, total_partobj * 100 / total_objects); 948 printf("%% PartObj%10s%% %10s%% %10s%% %10s%%\n", 949 b1, b2, b3, b4); 950 951 store_size(b1, avg_size);store_size(b2, min_size); 952 store_size(b3, max_size);store_size(b4, total_size); 953 printf("Memory %10s %10s %10s %10s\n", 954 b1, b2, b3, b4); 955 956 store_size(b1, avg_used);store_size(b2, min_used); 957 store_size(b3, max_used);store_size(b4, total_used); 958 printf("Used %10s %10s %10s %10s\n", 959 b1, b2, b3, b4); 960 961 store_size(b1, avg_waste);store_size(b2, min_waste); 962 store_size(b3, max_waste);store_size(b4, total_waste); 963 printf("Loss %10s %10s %10s %10s\n", 964 b1, b2, b3, b4); 965 966 printf("\n"); 967 printf("Per Object Average Min Max\n"); 968 printf("---------------------------------------------\n"); 969 970 store_size(b1, avg_memobj);store_size(b2, min_memobj); 971 store_size(b3, max_memobj); 972 printf("Memory %10s %10s %10s\n", 973 b1, b2, b3); 974 store_size(b1, avg_objsize);store_size(b2, min_objsize); 975 store_size(b3, max_objsize); 976 printf("User %10s %10s %10s\n", 977 b1, b2, b3); 978 979 store_size(b1, avg_objwaste);store_size(b2, min_objwaste); 980 store_size(b3, max_objwaste); 981 printf("Loss %10s %10s %10s\n", 982 b1, b2, b3); 983 } 984 985 void sort_slabs(void) 986 { 987 struct slabinfo *s1,*s2; 988 989 for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) { 990 for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) { 991 int result; 992 993 if (sort_size) 994 result = slab_size(s1) < slab_size(s2); 995 else if (sort_active) 996 result = slab_activity(s1) < slab_activity(s2); 997 else 998 result = strcasecmp(s1->name, s2->name); 999 1000 if (show_inverted) 1001 result = -result; 1002 1003 if (result > 0) { 1004 struct slabinfo t; 1005 1006 memcpy(&t, s1, sizeof(struct slabinfo)); 1007 memcpy(s1, s2, sizeof(struct slabinfo)); 1008 memcpy(s2, &t, sizeof(struct slabinfo)); 1009 } 1010 } 1011 } 1012 } 1013 1014 void sort_aliases(void) 1015 { 1016 struct aliasinfo *a1,*a2; 1017 1018 for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) { 1019 for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) { 1020 char *n1, *n2; 1021 1022 n1 = a1->name; 1023 n2 = a2->name; 1024 if (show_alias && !show_inverted) { 1025 n1 = a1->ref; 1026 n2 = a2->ref; 1027 } 1028 if (strcasecmp(n1, n2) > 0) { 1029 struct aliasinfo t; 1030 1031 memcpy(&t, a1, sizeof(struct aliasinfo)); 1032 memcpy(a1, a2, sizeof(struct aliasinfo)); 1033 memcpy(a2, &t, sizeof(struct aliasinfo)); 1034 } 1035 } 1036 } 1037 } 1038 1039 void link_slabs(void) 1040 { 1041 struct aliasinfo *a; 1042 struct slabinfo *s; 1043 1044 for (a = aliasinfo; a < aliasinfo + aliases; a++) { 1045 1046 for (s = slabinfo; s < slabinfo + slabs; s++) 1047 if (strcmp(a->ref, s->name) == 0) { 1048 a->slab = s; 1049 s->refs++; 1050 break; 1051 } 1052 if (s == slabinfo + slabs) 1053 fatal("Unresolved alias %s\n", a->ref); 1054 } 1055 } 1056 1057 void alias(void) 1058 { 1059 struct aliasinfo *a; 1060 char *active = NULL; 1061 1062 sort_aliases(); 1063 link_slabs(); 1064 1065 for(a = aliasinfo; a < aliasinfo + aliases; a++) { 1066 1067 if (!show_single_ref && a->slab->refs == 1) 1068 continue; 1069 1070 if (!show_inverted) { 1071 if (active) { 1072 if (strcmp(a->slab->name, active) == 0) { 1073 printf(" %s", a->name); 1074 continue; 1075 } 1076 } 1077 printf("\n%-12s <- %s", a->slab->name, a->name); 1078 active = a->slab->name; 1079 } 1080 else 1081 printf("%-20s -> %s\n", a->name, a->slab->name); 1082 } 1083 if (active) 1084 printf("\n"); 1085 } 1086 1087 1088 void rename_slabs(void) 1089 { 1090 struct slabinfo *s; 1091 struct aliasinfo *a; 1092 1093 for (s = slabinfo; s < slabinfo + slabs; s++) { 1094 if (*s->name != ':') 1095 continue; 1096 1097 if (s->refs > 1 && !show_first_alias) 1098 continue; 1099 1100 a = find_one_alias(s); 1101 1102 if (a) 1103 s->name = a->name; 1104 else { 1105 s->name = "*"; 1106 actual_slabs--; 1107 } 1108 } 1109 } 1110 1111 int slab_mismatch(char *slab) 1112 { 1113 return regexec(&pattern, slab, 0, NULL, 0); 1114 } 1115 1116 void read_slab_dir(void) 1117 { 1118 DIR *dir; 1119 struct dirent *de; 1120 struct slabinfo *slab = slabinfo; 1121 struct aliasinfo *alias = aliasinfo; 1122 char *p; 1123 char *t; 1124 int count; 1125 1126 if (chdir("/sys/kernel/slab") && chdir("/sys/slab")) 1127 fatal("SYSFS support for SLUB not active\n"); 1128 1129 dir = opendir("."); 1130 while ((de = readdir(dir))) { 1131 if (de->d_name[0] == '.' || 1132 (de->d_name[0] != ':' && slab_mismatch(de->d_name))) 1133 continue; 1134 switch (de->d_type) { 1135 case DT_LNK: 1136 alias->name = strdup(de->d_name); 1137 count = readlink(de->d_name, buffer, sizeof(buffer)); 1138 1139 if (count < 0) 1140 fatal("Cannot read symlink %s\n", de->d_name); 1141 1142 buffer[count] = 0; 1143 p = buffer + count; 1144 while (p > buffer && p[-1] != '/') 1145 p--; 1146 alias->ref = strdup(p); 1147 alias++; 1148 break; 1149 case DT_DIR: 1150 if (chdir(de->d_name)) 1151 fatal("Unable to access slab %s\n", slab->name); 1152 slab->name = strdup(de->d_name); 1153 slab->alias = 0; 1154 slab->refs = 0; 1155 slab->aliases = get_obj("aliases"); 1156 slab->align = get_obj("align"); 1157 slab->cache_dma = get_obj("cache_dma"); 1158 slab->cpu_slabs = get_obj("cpu_slabs"); 1159 slab->destroy_by_rcu = get_obj("destroy_by_rcu"); 1160 slab->hwcache_align = get_obj("hwcache_align"); 1161 slab->object_size = get_obj("object_size"); 1162 slab->objects = get_obj("objects"); 1163 slab->objs_per_slab = get_obj("objs_per_slab"); 1164 slab->order = get_obj("order"); 1165 slab->partial = get_obj("partial"); 1166 slab->partial = get_obj_and_str("partial", &t); 1167 decode_numa_list(slab->numa_partial, t); 1168 free(t); 1169 slab->poison = get_obj("poison"); 1170 slab->reclaim_account = get_obj("reclaim_account"); 1171 slab->red_zone = get_obj("red_zone"); 1172 slab->sanity_checks = get_obj("sanity_checks"); 1173 slab->slab_size = get_obj("slab_size"); 1174 slab->slabs = get_obj_and_str("slabs", &t); 1175 decode_numa_list(slab->numa, t); 1176 free(t); 1177 slab->store_user = get_obj("store_user"); 1178 slab->trace = get_obj("trace"); 1179 slab->alloc_fastpath = get_obj("alloc_fastpath"); 1180 slab->alloc_slowpath = get_obj("alloc_slowpath"); 1181 slab->free_fastpath = get_obj("free_fastpath"); 1182 slab->free_slowpath = get_obj("free_slowpath"); 1183 slab->free_frozen= get_obj("free_frozen"); 1184 slab->free_add_partial = get_obj("free_add_partial"); 1185 slab->free_remove_partial = get_obj("free_remove_partial"); 1186 slab->alloc_from_partial = get_obj("alloc_from_partial"); 1187 slab->alloc_slab = get_obj("alloc_slab"); 1188 slab->alloc_refill = get_obj("alloc_refill"); 1189 slab->free_slab = get_obj("free_slab"); 1190 slab->cpuslab_flush = get_obj("cpuslab_flush"); 1191 slab->deactivate_full = get_obj("deactivate_full"); 1192 slab->deactivate_empty = get_obj("deactivate_empty"); 1193 slab->deactivate_to_head = get_obj("deactivate_to_head"); 1194 slab->deactivate_to_tail = get_obj("deactivate_to_tail"); 1195 slab->deactivate_remote_frees = get_obj("deactivate_remote_frees"); 1196 chdir(".."); 1197 if (slab->name[0] == ':') 1198 alias_targets++; 1199 slab++; 1200 break; 1201 default : 1202 fatal("Unknown file type %lx\n", de->d_type); 1203 } 1204 } 1205 closedir(dir); 1206 slabs = slab - slabinfo; 1207 actual_slabs = slabs; 1208 aliases = alias - aliasinfo; 1209 if (slabs > MAX_SLABS) 1210 fatal("Too many slabs\n"); 1211 if (aliases > MAX_ALIASES) 1212 fatal("Too many aliases\n"); 1213 } 1214 1215 void output_slabs(void) 1216 { 1217 struct slabinfo *slab; 1218 1219 for (slab = slabinfo; slab < slabinfo + slabs; slab++) { 1220 1221 if (slab->alias) 1222 continue; 1223 1224 1225 if (show_numa) 1226 slab_numa(slab, 0); 1227 else if (show_track) 1228 show_tracking(slab); 1229 else if (validate) 1230 slab_validate(slab); 1231 else if (shrink) 1232 slab_shrink(slab); 1233 else if (set_debug) 1234 slab_debug(slab); 1235 else if (show_ops) 1236 ops(slab); 1237 else if (show_slab) 1238 slabcache(slab); 1239 else if (show_report) 1240 report(slab); 1241 } 1242 } 1243 1244 struct option opts[] = { 1245 { "aliases", 0, NULL, 'a' }, 1246 { "activity", 0, NULL, 'A' }, 1247 { "debug", 2, NULL, 'd' }, 1248 { "display-activity", 0, NULL, 'D' }, 1249 { "empty", 0, NULL, 'e' }, 1250 { "first-alias", 0, NULL, 'f' }, 1251 { "help", 0, NULL, 'h' }, 1252 { "inverted", 0, NULL, 'i'}, 1253 { "numa", 0, NULL, 'n' }, 1254 { "ops", 0, NULL, 'o' }, 1255 { "report", 0, NULL, 'r' }, 1256 { "shrink", 0, NULL, 's' }, 1257 { "slabs", 0, NULL, 'l' }, 1258 { "track", 0, NULL, 't'}, 1259 { "validate", 0, NULL, 'v' }, 1260 { "zero", 0, NULL, 'z' }, 1261 { "1ref", 0, NULL, '1'}, 1262 { NULL, 0, NULL, 0 } 1263 }; 1264 1265 int main(int argc, char *argv[]) 1266 { 1267 int c; 1268 int err; 1269 char *pattern_source; 1270 1271 page_size = getpagesize(); 1272 1273 while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTS", 1274 opts, NULL)) != -1) 1275 switch (c) { 1276 case '1': 1277 show_single_ref = 1; 1278 break; 1279 case 'a': 1280 show_alias = 1; 1281 break; 1282 case 'A': 1283 sort_active = 1; 1284 break; 1285 case 'd': 1286 set_debug = 1; 1287 if (!debug_opt_scan(optarg)) 1288 fatal("Invalid debug option '%s'\n", optarg); 1289 break; 1290 case 'D': 1291 show_activity = 1; 1292 break; 1293 case 'e': 1294 show_empty = 1; 1295 break; 1296 case 'f': 1297 show_first_alias = 1; 1298 break; 1299 case 'h': 1300 usage(); 1301 return 0; 1302 case 'i': 1303 show_inverted = 1; 1304 break; 1305 case 'n': 1306 show_numa = 1; 1307 break; 1308 case 'o': 1309 show_ops = 1; 1310 break; 1311 case 'r': 1312 show_report = 1; 1313 break; 1314 case 's': 1315 shrink = 1; 1316 break; 1317 case 'l': 1318 show_slab = 1; 1319 break; 1320 case 't': 1321 show_track = 1; 1322 break; 1323 case 'v': 1324 validate = 1; 1325 break; 1326 case 'z': 1327 skip_zero = 0; 1328 break; 1329 case 'T': 1330 show_totals = 1; 1331 break; 1332 case 'S': 1333 sort_size = 1; 1334 break; 1335 1336 default: 1337 fatal("%s: Invalid option '%c'\n", argv[0], optopt); 1338 1339 } 1340 1341 if (!show_slab && !show_alias && !show_track && !show_report 1342 && !validate && !shrink && !set_debug && !show_ops) 1343 show_slab = 1; 1344 1345 if (argc > optind) 1346 pattern_source = argv[optind]; 1347 else 1348 pattern_source = ".*"; 1349 1350 err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB); 1351 if (err) 1352 fatal("%s: Invalid pattern '%s' code %d\n", 1353 argv[0], pattern_source, err); 1354 read_slab_dir(); 1355 if (show_alias) 1356 alias(); 1357 else 1358 if (show_totals) 1359 totals(); 1360 else { 1361 link_slabs(); 1362 rename_slabs(); 1363 sort_slabs(); 1364 output_slabs(); 1365 } 1366 return 0; 1367 }