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