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