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