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