Linux Audio

Check our new training course

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