slabinfo.c 28 KB

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