.. | .. |
---|
79 | 79 | int sort_active; |
---|
80 | 80 | int set_debug; |
---|
81 | 81 | int show_ops; |
---|
| 82 | +int sort_partial; |
---|
82 | 83 | int show_activity; |
---|
83 | 84 | int output_lines = -1; |
---|
84 | 85 | int sort_loss; |
---|
.. | .. |
---|
110 | 111 | static void usage(void) |
---|
111 | 112 | { |
---|
112 | 113 | printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n" |
---|
113 | | - "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" |
---|
| 114 | + "slabinfo [-aABDefhilLnoPrsStTUvXz1] [N=K] [-dafzput] [slab-regexp]\n" |
---|
114 | 115 | "-a|--aliases Show aliases\n" |
---|
115 | 116 | "-A|--activity Most active slabs first\n" |
---|
116 | | - "-d<options>|--debug=<options> Set/Clear Debug options\n" |
---|
| 117 | + "-B|--Bytes Show size in bytes\n" |
---|
117 | 118 | "-D|--display-active Switch line format to activity\n" |
---|
118 | 119 | "-e|--empty Show empty slabs\n" |
---|
119 | 120 | "-f|--first-alias Show first alias\n" |
---|
120 | 121 | "-h|--help Show usage information\n" |
---|
121 | 122 | "-i|--inverted Inverted list\n" |
---|
122 | 123 | "-l|--slabs Show slabs\n" |
---|
| 124 | + "-L|--Loss Sort by loss\n" |
---|
123 | 125 | "-n|--numa Show NUMA information\n" |
---|
124 | | - "-o|--ops Show kmem_cache_ops\n" |
---|
| 126 | + "-N|--lines=K Show the first K slabs\n" |
---|
| 127 | + "-o|--ops Show kmem_cache_ops\n" |
---|
| 128 | + "-P|--partial Sort by number of partial slabs\n" |
---|
| 129 | + "-r|--report Detailed report on single slabs\n" |
---|
125 | 130 | "-s|--shrink Shrink slabs\n" |
---|
126 | | - "-r|--report Detailed report on single slabs\n" |
---|
127 | 131 | "-S|--Size Sort by size\n" |
---|
128 | 132 | "-t|--tracking Show alloc/free information\n" |
---|
129 | 133 | "-T|--Totals Show summary information\n" |
---|
| 134 | + "-U|--Unreclaim Show unreclaimable slabs only\n" |
---|
130 | 135 | "-v|--validate Validate slabs\n" |
---|
| 136 | + "-X|--Xtotals Show extended summary information\n" |
---|
131 | 137 | "-z|--zero Include empty slabs\n" |
---|
132 | 138 | "-1|--1ref Single reference\n" |
---|
133 | | - "-N|--lines=K Show the first K slabs\n" |
---|
134 | | - "-L|--Loss Sort by loss\n" |
---|
135 | | - "-X|--Xtotals Show extended summary information\n" |
---|
136 | | - "-B|--Bytes Show size in bytes\n" |
---|
137 | | - "-U|--Unreclaim Show unreclaimable slabs only\n" |
---|
138 | | - "\nValid debug options (FZPUT may be combined)\n" |
---|
139 | | - "a / A Switch on all debug options (=FZUP)\n" |
---|
140 | | - "- Switch off all debug options\n" |
---|
141 | | - "f / F Sanity Checks (SLAB_CONSISTENCY_CHECKS)\n" |
---|
142 | | - "z / Z Redzoning\n" |
---|
143 | | - "p / P Poisoning\n" |
---|
144 | | - "u / U Tracking\n" |
---|
145 | | - "t / T Tracing\n" |
---|
| 139 | + |
---|
| 140 | + "\n" |
---|
| 141 | + "-d | --debug Switch off all debug options\n" |
---|
| 142 | + "-da | --debug=a Switch on all debug options (--debug=FZPU)\n" |
---|
| 143 | + |
---|
| 144 | + "\n" |
---|
| 145 | + "-d[afzput] | --debug=[afzput]\n" |
---|
| 146 | + " f | F Sanity Checks (SLAB_CONSISTENCY_CHECKS)\n" |
---|
| 147 | + " z | Z Redzoning\n" |
---|
| 148 | + " p | P Poisoning\n" |
---|
| 149 | + " u | U Tracking\n" |
---|
| 150 | + " t | T Tracing\n" |
---|
| 151 | + |
---|
| 152 | + "\nSorting options (--Loss, --Size, --Partial) are mutually exclusive\n" |
---|
146 | 153 | ); |
---|
147 | 154 | } |
---|
148 | 155 | |
---|
.. | .. |
---|
226 | 233 | return l; |
---|
227 | 234 | } |
---|
228 | 235 | |
---|
| 236 | +static unsigned long read_debug_slab_obj(struct slabinfo *s, const char *name) |
---|
| 237 | +{ |
---|
| 238 | + char x[128]; |
---|
| 239 | + FILE *f; |
---|
| 240 | + size_t l; |
---|
| 241 | + |
---|
| 242 | + snprintf(x, 128, "/sys/kernel/debug/slab/%s/%s", s->name, name); |
---|
| 243 | + f = fopen(x, "r"); |
---|
| 244 | + if (!f) { |
---|
| 245 | + buffer[0] = 0; |
---|
| 246 | + l = 0; |
---|
| 247 | + } else { |
---|
| 248 | + l = fread(buffer, 1, sizeof(buffer), f); |
---|
| 249 | + buffer[l] = 0; |
---|
| 250 | + fclose(f); |
---|
| 251 | + } |
---|
| 252 | + return l; |
---|
| 253 | +} |
---|
229 | 254 | |
---|
230 | 255 | /* |
---|
231 | 256 | * Put a size string together |
---|
.. | .. |
---|
402 | 427 | { |
---|
403 | 428 | printf("\n%s: Kernel object allocation\n", s->name); |
---|
404 | 429 | printf("-----------------------------------------------------------------------\n"); |
---|
405 | | - if (read_slab_obj(s, "alloc_calls")) |
---|
| 430 | + if (read_debug_slab_obj(s, "alloc_traces")) |
---|
| 431 | + printf("%s", buffer); |
---|
| 432 | + else if (read_slab_obj(s, "alloc_calls")) |
---|
406 | 433 | printf("%s", buffer); |
---|
407 | 434 | else |
---|
408 | 435 | printf("No Data\n"); |
---|
409 | 436 | |
---|
410 | 437 | printf("\n%s: Kernel object freeing\n", s->name); |
---|
411 | 438 | printf("------------------------------------------------------------------------\n"); |
---|
412 | | - if (read_slab_obj(s, "free_calls")) |
---|
| 439 | + if (read_debug_slab_obj(s, "free_traces")) |
---|
| 440 | + printf("%s", buffer); |
---|
| 441 | + else if (read_slab_obj(s, "free_calls")) |
---|
413 | 442 | printf("%s", buffer); |
---|
414 | 443 | else |
---|
415 | 444 | printf("No Data\n"); |
---|
.. | .. |
---|
713 | 742 | return; |
---|
714 | 743 | |
---|
715 | 744 | if (sanity && !s->sanity_checks) { |
---|
716 | | - set_obj(s, "sanity", 1); |
---|
| 745 | + set_obj(s, "sanity_checks", 1); |
---|
717 | 746 | } |
---|
718 | 747 | if (!sanity && s->sanity_checks) { |
---|
719 | 748 | if (slab_empty(s)) |
---|
720 | | - set_obj(s, "sanity", 0); |
---|
| 749 | + set_obj(s, "sanity_checks", 0); |
---|
721 | 750 | else |
---|
722 | 751 | fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name); |
---|
723 | 752 | } |
---|
.. | .. |
---|
1038 | 1067 | for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) { |
---|
1039 | 1068 | int result; |
---|
1040 | 1069 | |
---|
1041 | | - if (sort_size) |
---|
1042 | | - result = slab_size(s1) < slab_size(s2); |
---|
1043 | | - else if (sort_active) |
---|
1044 | | - result = slab_activity(s1) < slab_activity(s2); |
---|
1045 | | - else if (sort_loss) |
---|
1046 | | - result = slab_waste(s1) < slab_waste(s2); |
---|
1047 | | - else |
---|
| 1070 | + if (sort_size) { |
---|
| 1071 | + if (slab_size(s1) == slab_size(s2)) |
---|
| 1072 | + result = strcasecmp(s1->name, s2->name); |
---|
| 1073 | + else |
---|
| 1074 | + result = slab_size(s1) < slab_size(s2); |
---|
| 1075 | + } else if (sort_active) { |
---|
| 1076 | + if (slab_activity(s1) == slab_activity(s2)) |
---|
| 1077 | + result = strcasecmp(s1->name, s2->name); |
---|
| 1078 | + else |
---|
| 1079 | + result = slab_activity(s1) < slab_activity(s2); |
---|
| 1080 | + } else if (sort_loss) { |
---|
| 1081 | + if (slab_waste(s1) == slab_waste(s2)) |
---|
| 1082 | + result = strcasecmp(s1->name, s2->name); |
---|
| 1083 | + else |
---|
| 1084 | + result = slab_waste(s1) < slab_waste(s2); |
---|
| 1085 | + } else if (sort_partial) { |
---|
| 1086 | + if (s1->partial == s2->partial) |
---|
| 1087 | + result = strcasecmp(s1->name, s2->name); |
---|
| 1088 | + else |
---|
| 1089 | + result = s1->partial < s2->partial; |
---|
| 1090 | + } else |
---|
1048 | 1091 | result = strcasecmp(s1->name, s2->name); |
---|
1049 | 1092 | |
---|
1050 | 1093 | if (show_inverted) |
---|
.. | .. |
---|
1304 | 1347 | } |
---|
1305 | 1348 | } |
---|
1306 | 1349 | |
---|
| 1350 | +static void _xtotals(char *heading, char *underline, |
---|
| 1351 | + int loss, int size, int partial) |
---|
| 1352 | +{ |
---|
| 1353 | + printf("%s%s", heading, underline); |
---|
| 1354 | + line = 0; |
---|
| 1355 | + sort_loss = loss; |
---|
| 1356 | + sort_size = size; |
---|
| 1357 | + sort_partial = partial; |
---|
| 1358 | + sort_slabs(); |
---|
| 1359 | + output_slabs(); |
---|
| 1360 | +} |
---|
| 1361 | + |
---|
1307 | 1362 | static void xtotals(void) |
---|
1308 | 1363 | { |
---|
| 1364 | + char *heading, *underline; |
---|
| 1365 | + |
---|
1309 | 1366 | totals(); |
---|
1310 | 1367 | |
---|
1311 | 1368 | link_slabs(); |
---|
1312 | 1369 | rename_slabs(); |
---|
1313 | 1370 | |
---|
1314 | | - printf("\nSlabs sorted by size\n"); |
---|
1315 | | - printf("--------------------\n"); |
---|
1316 | | - sort_loss = 0; |
---|
1317 | | - sort_size = 1; |
---|
1318 | | - sort_slabs(); |
---|
1319 | | - output_slabs(); |
---|
| 1371 | + heading = "\nSlabs sorted by size\n"; |
---|
| 1372 | + underline = "--------------------\n"; |
---|
| 1373 | + _xtotals(heading, underline, 0, 1, 0); |
---|
1320 | 1374 | |
---|
1321 | | - printf("\nSlabs sorted by loss\n"); |
---|
1322 | | - printf("--------------------\n"); |
---|
1323 | | - line = 0; |
---|
1324 | | - sort_loss = 1; |
---|
1325 | | - sort_size = 0; |
---|
1326 | | - sort_slabs(); |
---|
1327 | | - output_slabs(); |
---|
| 1375 | + heading = "\nSlabs sorted by loss\n"; |
---|
| 1376 | + underline = "--------------------\n"; |
---|
| 1377 | + _xtotals(heading, underline, 1, 0, 0); |
---|
| 1378 | + |
---|
| 1379 | + heading = "\nSlabs sorted by number of partial slabs\n"; |
---|
| 1380 | + underline = "---------------------------------------\n"; |
---|
| 1381 | + _xtotals(heading, underline, 0, 0, 1); |
---|
| 1382 | + |
---|
1328 | 1383 | printf("\n"); |
---|
1329 | 1384 | } |
---|
1330 | 1385 | |
---|
1331 | 1386 | struct option opts[] = { |
---|
1332 | 1387 | { "aliases", no_argument, NULL, 'a' }, |
---|
1333 | 1388 | { "activity", no_argument, NULL, 'A' }, |
---|
| 1389 | + { "Bytes", no_argument, NULL, 'B'}, |
---|
1334 | 1390 | { "debug", optional_argument, NULL, 'd' }, |
---|
1335 | 1391 | { "display-activity", no_argument, NULL, 'D' }, |
---|
1336 | 1392 | { "empty", no_argument, NULL, 'e' }, |
---|
.. | .. |
---|
1338 | 1394 | { "help", no_argument, NULL, 'h' }, |
---|
1339 | 1395 | { "inverted", no_argument, NULL, 'i'}, |
---|
1340 | 1396 | { "slabs", no_argument, NULL, 'l' }, |
---|
| 1397 | + { "Loss", no_argument, NULL, 'L'}, |
---|
1341 | 1398 | { "numa", no_argument, NULL, 'n' }, |
---|
| 1399 | + { "lines", required_argument, NULL, 'N'}, |
---|
1342 | 1400 | { "ops", no_argument, NULL, 'o' }, |
---|
1343 | | - { "shrink", no_argument, NULL, 's' }, |
---|
| 1401 | + { "partial", no_argument, NULL, 'p'}, |
---|
1344 | 1402 | { "report", no_argument, NULL, 'r' }, |
---|
| 1403 | + { "shrink", no_argument, NULL, 's' }, |
---|
1345 | 1404 | { "Size", no_argument, NULL, 'S'}, |
---|
1346 | 1405 | { "tracking", no_argument, NULL, 't'}, |
---|
1347 | 1406 | { "Totals", no_argument, NULL, 'T'}, |
---|
| 1407 | + { "Unreclaim", no_argument, NULL, 'U'}, |
---|
1348 | 1408 | { "validate", no_argument, NULL, 'v' }, |
---|
| 1409 | + { "Xtotals", no_argument, NULL, 'X'}, |
---|
1349 | 1410 | { "zero", no_argument, NULL, 'z' }, |
---|
1350 | 1411 | { "1ref", no_argument, NULL, '1'}, |
---|
1351 | | - { "lines", required_argument, NULL, 'N'}, |
---|
1352 | | - { "Loss", no_argument, NULL, 'L'}, |
---|
1353 | | - { "Xtotals", no_argument, NULL, 'X'}, |
---|
1354 | | - { "Bytes", no_argument, NULL, 'B'}, |
---|
1355 | | - { "Unreclaim", no_argument, NULL, 'U'}, |
---|
1356 | 1412 | { NULL, 0, NULL, 0 } |
---|
1357 | 1413 | }; |
---|
1358 | 1414 | |
---|
.. | .. |
---|
1364 | 1420 | |
---|
1365 | 1421 | page_size = getpagesize(); |
---|
1366 | 1422 | |
---|
1367 | | - while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTSN:LXBU", |
---|
| 1423 | + while ((c = getopt_long(argc, argv, "aABd::DefhilLnN:oPrsStTUvXz1", |
---|
1368 | 1424 | opts, NULL)) != -1) |
---|
1369 | 1425 | switch (c) { |
---|
1370 | | - case '1': |
---|
1371 | | - show_single_ref = 1; |
---|
1372 | | - break; |
---|
1373 | 1426 | case 'a': |
---|
1374 | 1427 | show_alias = 1; |
---|
1375 | 1428 | break; |
---|
1376 | 1429 | case 'A': |
---|
1377 | 1430 | sort_active = 1; |
---|
| 1431 | + break; |
---|
| 1432 | + case 'B': |
---|
| 1433 | + show_bytes = 1; |
---|
1378 | 1434 | break; |
---|
1379 | 1435 | case 'd': |
---|
1380 | 1436 | set_debug = 1; |
---|
.. | .. |
---|
1396 | 1452 | case 'i': |
---|
1397 | 1453 | show_inverted = 1; |
---|
1398 | 1454 | break; |
---|
1399 | | - case 'n': |
---|
1400 | | - show_numa = 1; |
---|
1401 | | - break; |
---|
1402 | | - case 'o': |
---|
1403 | | - show_ops = 1; |
---|
1404 | | - break; |
---|
1405 | | - case 'r': |
---|
1406 | | - show_report = 1; |
---|
1407 | | - break; |
---|
1408 | | - case 's': |
---|
1409 | | - shrink = 1; |
---|
1410 | | - break; |
---|
1411 | 1455 | case 'l': |
---|
1412 | 1456 | show_slab = 1; |
---|
1413 | 1457 | break; |
---|
1414 | | - case 't': |
---|
1415 | | - show_track = 1; |
---|
| 1458 | + case 'L': |
---|
| 1459 | + sort_loss = 1; |
---|
1416 | 1460 | break; |
---|
1417 | | - case 'v': |
---|
1418 | | - validate = 1; |
---|
1419 | | - break; |
---|
1420 | | - case 'z': |
---|
1421 | | - skip_zero = 0; |
---|
1422 | | - break; |
---|
1423 | | - case 'T': |
---|
1424 | | - show_totals = 1; |
---|
1425 | | - break; |
---|
1426 | | - case 'S': |
---|
1427 | | - sort_size = 1; |
---|
| 1461 | + case 'n': |
---|
| 1462 | + show_numa = 1; |
---|
1428 | 1463 | break; |
---|
1429 | 1464 | case 'N': |
---|
1430 | 1465 | if (optarg) { |
---|
.. | .. |
---|
1433 | 1468 | output_lines = 1; |
---|
1434 | 1469 | } |
---|
1435 | 1470 | break; |
---|
1436 | | - case 'L': |
---|
1437 | | - sort_loss = 1; |
---|
| 1471 | + case 'o': |
---|
| 1472 | + show_ops = 1; |
---|
| 1473 | + break; |
---|
| 1474 | + case 'r': |
---|
| 1475 | + show_report = 1; |
---|
| 1476 | + break; |
---|
| 1477 | + case 'P': |
---|
| 1478 | + sort_partial = 1; |
---|
| 1479 | + break; |
---|
| 1480 | + case 's': |
---|
| 1481 | + shrink = 1; |
---|
| 1482 | + break; |
---|
| 1483 | + case 'S': |
---|
| 1484 | + sort_size = 1; |
---|
| 1485 | + break; |
---|
| 1486 | + case 't': |
---|
| 1487 | + show_track = 1; |
---|
| 1488 | + break; |
---|
| 1489 | + case 'T': |
---|
| 1490 | + show_totals = 1; |
---|
| 1491 | + break; |
---|
| 1492 | + case 'U': |
---|
| 1493 | + unreclaim_only = 1; |
---|
| 1494 | + break; |
---|
| 1495 | + case 'v': |
---|
| 1496 | + validate = 1; |
---|
1438 | 1497 | break; |
---|
1439 | 1498 | case 'X': |
---|
1440 | 1499 | if (output_lines == -1) |
---|
.. | .. |
---|
1442 | 1501 | extended_totals = 1; |
---|
1443 | 1502 | show_bytes = 1; |
---|
1444 | 1503 | break; |
---|
1445 | | - case 'B': |
---|
1446 | | - show_bytes = 1; |
---|
| 1504 | + case 'z': |
---|
| 1505 | + skip_zero = 0; |
---|
1447 | 1506 | break; |
---|
1448 | | - case 'U': |
---|
1449 | | - unreclaim_only = 1; |
---|
| 1507 | + case '1': |
---|
| 1508 | + show_single_ref = 1; |
---|
1450 | 1509 | break; |
---|
1451 | 1510 | default: |
---|
1452 | 1511 | fatal("%s: Invalid option '%c'\n", argv[0], optopt); |
---|