⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slabinfo.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Slabinfo: Tool to get reports about slabs * * (C) 2007 sgi, Christoph Lameter <clameter@sgi.com> * * Compile by: * * gcc -o slabinfo slabinfo.c */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <dirent.h>#include <strings.h>#include <string.h>#include <unistd.h>#include <stdarg.h>#include <getopt.h>#include <regex.h>#include <errno.h>#define MAX_SLABS 500#define MAX_ALIASES 500#define MAX_NODES 1024struct slabinfo {	char *name;	int alias;	int refs;	int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;	int hwcache_align, object_size, objs_per_slab;	int sanity_checks, slab_size, store_user, trace;	int order, poison, reclaim_account, red_zone;	unsigned long partial, objects, slabs;	int numa[MAX_NODES];	int numa_partial[MAX_NODES];} slabinfo[MAX_SLABS];struct aliasinfo {	char *name;	char *ref;	struct slabinfo *slab;} aliasinfo[MAX_ALIASES];int slabs = 0;int actual_slabs = 0;int aliases = 0;int alias_targets = 0;int highest_node = 0;char buffer[4096];int show_empty = 0;int show_report = 0;int show_alias = 0;int show_slab = 0;int skip_zero = 1;int show_numa = 0;int show_track = 0;int show_first_alias = 0;int validate = 0;int shrink = 0;int show_inverted = 0;int show_single_ref = 0;int show_totals = 0;int sort_size = 0;int set_debug = 0;int show_ops = 0;/* Debug options */int sanity = 0;int redzone = 0;int poison = 0;int tracking = 0;int tracing = 0;int page_size;regex_t pattern;void fatal(const char *x, ...){	va_list ap;	va_start(ap, x);	vfprintf(stderr, x, ap);	va_end(ap);	exit(EXIT_FAILURE);}void usage(void){	printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n"		"slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"		"-a|--aliases           Show aliases\n"		"-d<options>|--debug=<options> Set/Clear Debug options\n"		"-e|--empty		Show empty slabs\n"		"-f|--first-alias       Show first alias\n"		"-h|--help              Show usage information\n"		"-i|--inverted          Inverted list\n"		"-l|--slabs             Show slabs\n"		"-n|--numa              Show NUMA information\n"		"-o|--ops		Show kmem_cache_ops\n"		"-s|--shrink            Shrink slabs\n"		"-r|--report		Detailed report on single slabs\n"		"-S|--Size              Sort by size\n"		"-t|--tracking          Show alloc/free information\n"		"-T|--Totals            Show summary information\n"		"-v|--validate          Validate slabs\n"		"-z|--zero              Include empty slabs\n"		"-1|--1ref              Single reference\n"		"\nValid debug options (FZPUT may be combined)\n"		"a / A          Switch on all debug options (=FZUP)\n"		"-              Switch off all debug options\n"		"f / F          Sanity Checks (SLAB_DEBUG_FREE)\n"		"z / Z          Redzoning\n"		"p / P          Poisoning\n"		"u / U          Tracking\n"		"t / T          Tracing\n"	);}unsigned long read_obj(const char *name){	FILE *f = fopen(name, "r");	if (!f)		buffer[0] = 0;	else {		if (!fgets(buffer, sizeof(buffer), f))			buffer[0] = 0;		fclose(f);		if (buffer[strlen(buffer)] == '\n')			buffer[strlen(buffer)] = 0;	}	return strlen(buffer);}/* * Get the contents of an attribute */unsigned long get_obj(const char *name){	if (!read_obj(name))		return 0;	return atol(buffer);}unsigned long get_obj_and_str(const char *name, char **x){	unsigned long result = 0;	char *p;	*x = NULL;	if (!read_obj(name)) {		x = NULL;		return 0;	}	result = strtoul(buffer, &p, 10);	while (*p == ' ')		p++;	if (*p)		*x = strdup(p);	return result;}void set_obj(struct slabinfo *s, const char *name, int n){	char x[100];	FILE *f;	snprintf(x, 100, "%s/%s", s->name, name);	f = fopen(x, "w");	if (!f)		fatal("Cannot write to %s\n", x);	fprintf(f, "%d\n", n);	fclose(f);}unsigned long read_slab_obj(struct slabinfo *s, const char *name){	char x[100];	FILE *f;	size_t l;	snprintf(x, 100, "%s/%s", s->name, name);	f = fopen(x, "r");	if (!f) {		buffer[0] = 0;		l = 0;	} else {		l = fread(buffer, 1, sizeof(buffer), f);		buffer[l] = 0;		fclose(f);	}	return l;}/* * Put a size string together */int store_size(char *buffer, unsigned long value){	unsigned long divisor = 1;	char trailer = 0;	int n;	if (value > 1000000000UL) {		divisor = 100000000UL;		trailer = 'G';	} else if (value > 1000000UL) {		divisor = 100000UL;		trailer = 'M';	} else if (value > 1000UL) {		divisor = 100;		trailer = 'K';	}	value /= divisor;	n = sprintf(buffer, "%ld",value);	if (trailer) {		buffer[n] = trailer;		n++;		buffer[n] = 0;	}	if (divisor != 1) {		memmove(buffer + n - 2, buffer + n - 3, 4);		buffer[n-2] = '.';		n++;	}	return n;}void decode_numa_list(int *numa, char *t){	int node;	int nr;	memset(numa, 0, MAX_NODES * sizeof(int));	if (!t)		return;	while (*t == 'N') {		t++;		node = strtoul(t, &t, 10);		if (*t == '=') {			t++;			nr = strtoul(t, &t, 10);			numa[node] = nr;			if (node > highest_node)				highest_node = node;		}		while (*t == ' ')			t++;	}}void slab_validate(struct slabinfo *s){	if (strcmp(s->name, "*") == 0)		return;	set_obj(s, "validate", 1);}void slab_shrink(struct slabinfo *s){	if (strcmp(s->name, "*") == 0)		return;	set_obj(s, "shrink", 1);}int line = 0;void first_line(void){	printf("Name                   Objects Objsize    Space "		"Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");}/* * Find the shortest alias of a slab */struct aliasinfo *find_one_alias(struct slabinfo *find){	struct aliasinfo *a;	struct aliasinfo *best = NULL;	for(a = aliasinfo;a < aliasinfo + aliases; a++) {		if (a->slab == find &&			(!best || strlen(best->name) < strlen(a->name))) {				best = a;				if (strncmp(a->name,"kmall", 5) == 0)					return best;			}	}	return best;}unsigned long slab_size(struct slabinfo *s){	return 	s->slabs * (page_size << s->order);}void slab_numa(struct slabinfo *s, int mode){	int node;	if (strcmp(s->name, "*") == 0)		return;	if (!highest_node) {		printf("\n%s: No NUMA information available.\n", s->name);		return;	}	if (skip_zero && !s->slabs)		return;	if (!line) {		printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");		for(node = 0; node <= highest_node; node++)			printf(" %4d", node);		printf("\n----------------------");		for(node = 0; node <= highest_node; node++)			printf("-----");		printf("\n");	}	printf("%-21s ", mode ? "All slabs" : s->name);	for(node = 0; node <= highest_node; node++) {		char b[20];		store_size(b, s->numa[node]);		printf(" %4s", b);	}	printf("\n");	if (mode) {		printf("%-21s ", "Partial slabs");		for(node = 0; node <= highest_node; node++) {			char b[20];			store_size(b, s->numa_partial[node]);			printf(" %4s", b);		}		printf("\n");	}	line++;}void show_tracking(struct slabinfo *s){	printf("\n%s: Kernel object allocation\n", s->name);	printf("-----------------------------------------------------------------------\n");	if (read_slab_obj(s, "alloc_calls"))		printf(buffer);	else		printf("No Data\n");	printf("\n%s: Kernel object freeing\n", s->name);	printf("------------------------------------------------------------------------\n");	if (read_slab_obj(s, "free_calls"))		printf(buffer);	else		printf("No Data\n");}void ops(struct slabinfo *s){	if (strcmp(s->name, "*") == 0)		return;	if (read_slab_obj(s, "ops")) {		printf("\n%s: kmem_cache operations\n", s->name);		printf("--------------------------------------------\n");		printf(buffer);	} else		printf("\n%s has no kmem_cache operations\n", s->name);}const char *onoff(int x){	if (x)		return "On ";	return "Off";}void report(struct slabinfo *s){	if (strcmp(s->name, "*") == 0)		return;	printf("\nSlabcache: %-20s  Aliases: %2d Order : %2d Objects: %lu\n",		s->name, s->aliases, s->order, s->objects);	if (s->hwcache_align)		printf("** Hardware cacheline aligned\n");	if (s->cache_dma)		printf("** Memory is allocated in a special DMA zone\n");	if (s->destroy_by_rcu)		printf("** Slabs are destroyed via RCU\n");	if (s->reclaim_account)		printf("** Reclaim accounting active\n");	printf("\nSizes (bytes)     Slabs              Debug                Memory\n");	printf("------------------------------------------------------------------------\n");	printf("Object : %7d  Total  : %7ld   Sanity Checks : %s  Total: %7ld\n",			s->object_size, s->slabs, onoff(s->sanity_checks),			s->slabs * (page_size << s->order));	printf("SlabObj: %7d  Full   : %7ld   Redzoning     : %s  Used : %7ld\n",			s->slab_size, s->slabs - s->partial - s->cpu_slabs,			onoff(s->red_zone), s->objects * s->object_size);	printf("SlabSiz: %7d  Partial: %7ld   Poisoning     : %s  Loss : %7ld\n",			page_size << s->order, s->partial, onoff(s->poison),			s->slabs * (page_size << s->order) - s->objects * s->object_size);	printf("Loss   : %7d  CpuSlab: %7d   Tracking      : %s  Lalig: %7ld\n",			s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user),			(s->slab_size - s->object_size) * s->objects);	printf("Align  : %7d  Objects: %7d   Tracing       : %s  Lpadd: %7ld\n",			s->align, s->objs_per_slab, onoff(s->trace),			((page_size << s->order) - s->objs_per_slab * s->slab_size) *			s->slabs);	ops(s);	show_tracking(s);	slab_numa(s, 1);}void slabcache(struct slabinfo *s){	char size_str[20];	char dist_str[40];	char flags[20];	char *p = flags;	if (strcmp(s->name, "*") == 0)		return;	if (actual_slabs == 1) {		report(s);		return;	}	if (skip_zero && !show_empty && !s->slabs)		return;	if (show_empty && s->slabs)		return;	store_size(size_str, slab_size(s));	snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs);	if (!line++)		first_line();	if (s->aliases)		*p++ = '*';	if (s->cache_dma)		*p++ = 'd';	if (s->hwcache_align)		*p++ = 'A';	if (s->poison)		*p++ = 'P';	if (s->reclaim_account)		*p++ = 'a';	if (s->red_zone)		*p++ = 'Z';	if (s->sanity_checks)		*p++ = 'F';	if (s->store_user)		*p++ = 'U';	if (s->trace)		*p++ = 'T';	*p = 0;	printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",		s->name, s->objects, s->object_size, size_str, dist_str,		s->objs_per_slab, s->order,		s->slabs ? (s->partial * 100) / s->slabs : 100,		s->slabs ? (s->objects * s->object_size * 100) /			(s->slabs * (page_size << s->order)) : 100,		flags);}/* * Analyze debug options. Return false if something is amiss. */int debug_opt_scan(char *opt){	if (!opt || !opt[0] || strcmp(opt, "-") == 0)		return 1;	if (strcasecmp(opt, "a") == 0) {		sanity = 1;		poison = 1;		redzone = 1;		tracking = 1;		return 1;	}	for ( ; *opt; opt++)	 	switch (*opt) {		case 'F' : case 'f':			if (sanity)				return 0;			sanity = 1;			break;		case 'P' : case 'p':			if (poison)				return 0;			poison = 1;			break;		case 'Z' : case 'z':			if (redzone)				return 0;			redzone = 1;			break;		case 'U' : case 'u':			if (tracking)				return 0;			tracking = 1;			break;		case 'T' : case 't':			if (tracing)				return 0;			tracing = 1;			break;		default:			return 0;		}	return 1;}int slab_empty(struct slabinfo *s){	if (s->objects > 0)		return 0;	/*	 * We may still have slabs even if there are no objects. Shrinking will	 * remove them.	 */	if (s->slabs != 0)		set_obj(s, "shrink", 1);	return 1;}void slab_debug(struct slabinfo *s){	if (strcmp(s->name, "*") == 0)		return;	if (sanity && !s->sanity_checks) {		set_obj(s, "sanity", 1);	}	if (!sanity && s->sanity_checks) {		if (slab_empty(s))			set_obj(s, "sanity", 0);		else			fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name);	}	if (redzone && !s->red_zone) {		if (slab_empty(s))			set_obj(s, "red_zone", 1);		else			fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);	}	if (!redzone && s->red_zone) {		if (slab_empty(s))			set_obj(s, "red_zone", 0);		else			fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);	}	if (poison && !s->poison) {		if (slab_empty(s))			set_obj(s, "poison", 1);		else			fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);	}	if (!poison && s->poison) {		if (slab_empty(s))			set_obj(s, "poison", 0);		else			fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);	}	if (tracking && !s->store_user) {		if (slab_empty(s))			set_obj(s, "store_user", 1);		else			fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);	}	if (!tracking && s->store_user) {		if (slab_empty(s))			set_obj(s, "store_user", 0);		else			fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);	}	if (tracing && !s->trace) {		if (slabs == 1)			set_obj(s, "trace", 1);		else			fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);	}	if (!tracing && s->trace)		set_obj(s, "trace", 1);}void totals(void){	struct slabinfo *s;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -