Commit a87615b8f9e2349f6d3770af3d72fd6a41ab4239
Committed by
Linus Torvalds
1 parent
be7b3fbcef
Exists in
master
and in
7 other branches
SLUB: slabinfo upgrade
-e Show empty slabs -d Modification of slab debug options at runtime -o Operations. Display of ctor / dtor etc. -r Report: Display all available information about a slabcache. Cleanup tracking display and make it work right. Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 352 additions and 74 deletions Side-by-side Diff
Documentation/vm/slabinfo.c
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | #include <stdarg.h> |
17 | 17 | #include <getopt.h> |
18 | 18 | #include <regex.h> |
19 | +#include <errno.h> | |
19 | 20 | |
20 | 21 | #define MAX_SLABS 500 |
21 | 22 | #define MAX_ALIASES 500 |
22 | 23 | |
... | ... | @@ -41,12 +42,15 @@ |
41 | 42 | } aliasinfo[MAX_ALIASES]; |
42 | 43 | |
43 | 44 | int slabs = 0; |
45 | +int actual_slabs = 0; | |
44 | 46 | int aliases = 0; |
45 | 47 | int alias_targets = 0; |
46 | 48 | int highest_node = 0; |
47 | 49 | |
48 | 50 | char buffer[4096]; |
49 | 51 | |
52 | +int show_empty = 0; | |
53 | +int show_report = 0; | |
50 | 54 | int show_alias = 0; |
51 | 55 | int show_slab = 0; |
52 | 56 | int skip_zero = 1; |
53 | 57 | |
... | ... | @@ -59,7 +63,16 @@ |
59 | 63 | int show_single_ref = 0; |
60 | 64 | int show_totals = 0; |
61 | 65 | int sort_size = 0; |
66 | +int set_debug = 0; | |
67 | +int show_ops = 0; | |
62 | 68 | |
69 | +/* Debug options */ | |
70 | +int sanity = 0; | |
71 | +int redzone = 0; | |
72 | +int poison = 0; | |
73 | +int tracking = 0; | |
74 | +int tracing = 0; | |
75 | + | |
63 | 76 | int page_size; |
64 | 77 | |
65 | 78 | regex_t pattern; |
66 | 79 | |
67 | 80 | |
68 | 81 | |
69 | 82 | |
70 | 83 | |
71 | 84 | |
72 | 85 | |
... | ... | @@ -76,20 +89,33 @@ |
76 | 89 | |
77 | 90 | void usage(void) |
78 | 91 | { |
79 | - printf("slabinfo [-ahnpvtsz] [slab-regexp]\n" | |
92 | + printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n" | |
93 | + "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" | |
80 | 94 | "-a|--aliases Show aliases\n" |
95 | + "-d<options>|--debug=<options> Set/Clear Debug options\n" | |
96 | + "-e|--empty Show empty slabs\n" | |
97 | + "-f|--first-alias Show first alias\n" | |
81 | 98 | "-h|--help Show usage information\n" |
99 | + "-i|--inverted Inverted list\n" | |
100 | + "-l|--slabs Show slabs\n" | |
82 | 101 | "-n|--numa Show NUMA information\n" |
102 | + "-o|--ops Show kmem_cache_ops\n" | |
83 | 103 | "-s|--shrink Shrink slabs\n" |
84 | - "-v|--validate Validate slabs\n" | |
104 | + "-r|--report Detailed report on single slabs\n" | |
105 | + "-S|--Size Sort by size\n" | |
85 | 106 | "-t|--tracking Show alloc/free information\n" |
86 | 107 | "-T|--Totals Show summary information\n" |
87 | - "-l|--slabs Show slabs\n" | |
88 | - "-S|--Size Sort by size\n" | |
108 | + "-v|--validate Validate slabs\n" | |
89 | 109 | "-z|--zero Include empty slabs\n" |
90 | - "-f|--first-alias Show first alias\n" | |
91 | - "-i|--inverted Inverted list\n" | |
92 | 110 | "-1|--1ref Single reference\n" |
111 | + "\nValid debug options (FZPUT may be combined)\n" | |
112 | + "a / A Switch on all debug options (=FZUP)\n" | |
113 | + "- Switch off all debug options\n" | |
114 | + "f / F Sanity Checks (SLAB_DEBUG_FREE)\n" | |
115 | + "z / Z Redzoning\n" | |
116 | + "p / P Poisoning\n" | |
117 | + "u / U Tracking\n" | |
118 | + "t / T Tracing\n" | |
93 | 119 | ); |
94 | 120 | } |
95 | 121 | |
96 | 122 | |
... | ... | @@ -143,11 +169,10 @@ |
143 | 169 | void set_obj(struct slabinfo *s, char *name, int n) |
144 | 170 | { |
145 | 171 | char x[100]; |
172 | + FILE *f; | |
146 | 173 | |
147 | 174 | sprintf(x, "%s/%s", s->name, name); |
148 | - | |
149 | - FILE *f = fopen(x, "w"); | |
150 | - | |
175 | + f = fopen(x, "w"); | |
151 | 176 | if (!f) |
152 | 177 | fatal("Cannot write to %s\n", x); |
153 | 178 | |
... | ... | @@ -155,6 +180,26 @@ |
155 | 180 | fclose(f); |
156 | 181 | } |
157 | 182 | |
183 | +unsigned long read_slab_obj(struct slabinfo *s, char *name) | |
184 | +{ | |
185 | + char x[100]; | |
186 | + FILE *f; | |
187 | + int l; | |
188 | + | |
189 | + sprintf(x, "%s/%s", s->name, name); | |
190 | + f = fopen(x, "r"); | |
191 | + if (!f) { | |
192 | + buffer[0] = 0; | |
193 | + l = 0; | |
194 | + } else { | |
195 | + l = fread(buffer, 1, sizeof(buffer), f); | |
196 | + buffer[l] = 0; | |
197 | + fclose(f); | |
198 | + } | |
199 | + return l; | |
200 | +} | |
201 | + | |
202 | + | |
158 | 203 | /* |
159 | 204 | * Put a size string together |
160 | 205 | */ |
... | ... | @@ -226,7 +271,7 @@ |
226 | 271 | |
227 | 272 | void first_line(void) |
228 | 273 | { |
229 | - printf("Name Objects Objsize Space " | |
274 | + printf("Name Objects Objsize Space " | |
230 | 275 | "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n"); |
231 | 276 | } |
232 | 277 | |
... | ... | @@ -246,10 +291,7 @@ |
246 | 291 | return best; |
247 | 292 | } |
248 | 293 | } |
249 | - if (best) | |
250 | - return best; | |
251 | - fatal("Cannot find alias for %s\n", find->name); | |
252 | - return NULL; | |
294 | + return best; | |
253 | 295 | } |
254 | 296 | |
255 | 297 | unsigned long slab_size(struct slabinfo *s) |
256 | 298 | |
... | ... | @@ -257,7 +299,127 @@ |
257 | 299 | return s->slabs * (page_size << s->order); |
258 | 300 | } |
259 | 301 | |
302 | +void slab_numa(struct slabinfo *s, int mode) | |
303 | +{ | |
304 | + int node; | |
260 | 305 | |
306 | + if (strcmp(s->name, "*") == 0) | |
307 | + return; | |
308 | + | |
309 | + if (!highest_node) { | |
310 | + printf("\n%s: No NUMA information available.\n", s->name); | |
311 | + return; | |
312 | + } | |
313 | + | |
314 | + if (skip_zero && !s->slabs) | |
315 | + return; | |
316 | + | |
317 | + if (!line) { | |
318 | + printf("\n%-21s:", mode ? "NUMA nodes" : "Slab"); | |
319 | + for(node = 0; node <= highest_node; node++) | |
320 | + printf(" %4d", node); | |
321 | + printf("\n----------------------"); | |
322 | + for(node = 0; node <= highest_node; node++) | |
323 | + printf("-----"); | |
324 | + printf("\n"); | |
325 | + } | |
326 | + printf("%-21s ", mode ? "All slabs" : s->name); | |
327 | + for(node = 0; node <= highest_node; node++) { | |
328 | + char b[20]; | |
329 | + | |
330 | + store_size(b, s->numa[node]); | |
331 | + printf(" %4s", b); | |
332 | + } | |
333 | + printf("\n"); | |
334 | + if (mode) { | |
335 | + printf("%-21s ", "Partial slabs"); | |
336 | + for(node = 0; node <= highest_node; node++) { | |
337 | + char b[20]; | |
338 | + | |
339 | + store_size(b, s->numa_partial[node]); | |
340 | + printf(" %4s", b); | |
341 | + } | |
342 | + printf("\n"); | |
343 | + } | |
344 | + line++; | |
345 | +} | |
346 | + | |
347 | +void show_tracking(struct slabinfo *s) | |
348 | +{ | |
349 | + printf("\n%s: Kernel object allocation\n", s->name); | |
350 | + printf("-----------------------------------------------------------------------\n"); | |
351 | + if (read_slab_obj(s, "alloc_calls")) | |
352 | + printf(buffer); | |
353 | + else | |
354 | + printf("No Data\n"); | |
355 | + | |
356 | + printf("\n%s: Kernel object freeing\n", s->name); | |
357 | + printf("------------------------------------------------------------------------\n"); | |
358 | + if (read_slab_obj(s, "free_calls")) | |
359 | + printf(buffer); | |
360 | + else | |
361 | + printf("No Data\n"); | |
362 | + | |
363 | +} | |
364 | + | |
365 | +void ops(struct slabinfo *s) | |
366 | +{ | |
367 | + if (strcmp(s->name, "*") == 0) | |
368 | + return; | |
369 | + | |
370 | + if (read_slab_obj(s, "ops")) { | |
371 | + printf("\n%s: kmem_cache operations\n", s->name); | |
372 | + printf("--------------------------------------------\n"); | |
373 | + printf(buffer); | |
374 | + } else | |
375 | + printf("\n%s has no kmem_cache operations\n", s->name); | |
376 | +} | |
377 | + | |
378 | +const char *onoff(int x) | |
379 | +{ | |
380 | + if (x) | |
381 | + return "On "; | |
382 | + return "Off"; | |
383 | +} | |
384 | + | |
385 | +void report(struct slabinfo *s) | |
386 | +{ | |
387 | + if (strcmp(s->name, "*") == 0) | |
388 | + return; | |
389 | + printf("\nSlabcache: %-20s Aliases: %2d Order : %2d\n", s->name, s->aliases, s->order); | |
390 | + if (s->hwcache_align) | |
391 | + printf("** Hardware cacheline aligned\n"); | |
392 | + if (s->cache_dma) | |
393 | + printf("** Memory is allocated in a special DMA zone\n"); | |
394 | + if (s->destroy_by_rcu) | |
395 | + printf("** Slabs are destroyed via RCU\n"); | |
396 | + if (s->reclaim_account) | |
397 | + printf("** Reclaim accounting active\n"); | |
398 | + | |
399 | + printf("\nSizes (bytes) Slabs Debug Memory\n"); | |
400 | + printf("------------------------------------------------------------------------\n"); | |
401 | + printf("Object : %7d Total : %7ld Sanity Checks : %s Total: %7ld\n", | |
402 | + s->object_size, s->slabs, onoff(s->sanity_checks), | |
403 | + s->slabs * (page_size << s->order)); | |
404 | + printf("SlabObj: %7d Full : %7ld Redzoning : %s Used : %7ld\n", | |
405 | + s->slab_size, s->slabs - s->partial - s->cpu_slabs, | |
406 | + onoff(s->red_zone), s->objects * s->object_size); | |
407 | + printf("SlabSiz: %7d Partial: %7ld Poisoning : %s Loss : %7ld\n", | |
408 | + page_size << s->order, s->partial, onoff(s->poison), | |
409 | + s->slabs * (page_size << s->order) - s->objects * s->object_size); | |
410 | + printf("Loss : %7d CpuSlab: %7d Tracking : %s Lalig: %7ld\n", | |
411 | + s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user), | |
412 | + (s->slab_size - s->object_size) * s->objects); | |
413 | + printf("Align : %7d Objects: %7d Tracing : %s Lpadd: %7ld\n", | |
414 | + s->align, s->objs_per_slab, onoff(s->trace), | |
415 | + ((page_size << s->order) - s->objs_per_slab * s->slab_size) * | |
416 | + s->slabs); | |
417 | + | |
418 | + ops(s); | |
419 | + show_tracking(s); | |
420 | + slab_numa(s, 1); | |
421 | +} | |
422 | + | |
261 | 423 | void slabcache(struct slabinfo *s) |
262 | 424 | { |
263 | 425 | char size_str[20]; |
264 | 426 | |
... | ... | @@ -265,9 +427,20 @@ |
265 | 427 | char flags[20]; |
266 | 428 | char *p = flags; |
267 | 429 | |
268 | - if (skip_zero && !s->slabs) | |
430 | + if (strcmp(s->name, "*") == 0) | |
269 | 431 | return; |
270 | 432 | |
433 | + if (actual_slabs == 1) { | |
434 | + report(s); | |
435 | + return; | |
436 | + } | |
437 | + | |
438 | + if (skip_zero && !show_empty && !s->slabs) | |
439 | + return; | |
440 | + | |
441 | + if (show_empty && s->slabs) | |
442 | + return; | |
443 | + | |
271 | 444 | store_size(size_str, slab_size(s)); |
272 | 445 | sprintf(dist_str,"%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs); |
273 | 446 | |
274 | 447 | |
275 | 448 | |
276 | 449 | |
277 | 450 | |
278 | 451 | |
279 | 452 | |
280 | 453 | |
281 | 454 | |
282 | 455 | |
283 | 456 | |
... | ... | @@ -303,50 +476,130 @@ |
303 | 476 | flags); |
304 | 477 | } |
305 | 478 | |
306 | -void slab_numa(struct slabinfo *s) | |
479 | +/* | |
480 | + * Analyze debug options. Return false if something is amiss. | |
481 | + */ | |
482 | +int debug_opt_scan(char *opt) | |
307 | 483 | { |
308 | - int node; | |
484 | + if (!opt || !opt[0] || strcmp(opt, "-") == 0) | |
485 | + return 1; | |
309 | 486 | |
310 | - if (!highest_node) | |
311 | - fatal("No NUMA information available.\n"); | |
487 | + if (strcasecmp(opt, "a") == 0) { | |
488 | + sanity = 1; | |
489 | + poison = 1; | |
490 | + redzone = 1; | |
491 | + tracking = 1; | |
492 | + return 1; | |
493 | + } | |
312 | 494 | |
313 | - if (skip_zero && !s->slabs) | |
314 | - return; | |
495 | + for ( ; *opt; opt++) | |
496 | + switch (*opt) { | |
497 | + case 'F' : case 'f': | |
498 | + if (sanity) | |
499 | + return 0; | |
500 | + sanity = 1; | |
501 | + break; | |
502 | + case 'P' : case 'p': | |
503 | + if (poison) | |
504 | + return 0; | |
505 | + poison = 1; | |
506 | + break; | |
315 | 507 | |
316 | - if (!line) { | |
317 | - printf("\nSlab Node "); | |
318 | - for(node = 0; node <= highest_node; node++) | |
319 | - printf(" %4d", node); | |
320 | - printf("\n----------------------"); | |
321 | - for(node = 0; node <= highest_node; node++) | |
322 | - printf("-----"); | |
323 | - printf("\n"); | |
324 | - } | |
325 | - printf("%-21s ", s->name); | |
326 | - for(node = 0; node <= highest_node; node++) { | |
327 | - char b[20]; | |
508 | + case 'Z' : case 'z': | |
509 | + if (redzone) | |
510 | + return 0; | |
511 | + redzone = 1; | |
512 | + break; | |
328 | 513 | |
329 | - store_size(b, s->numa[node]); | |
330 | - printf(" %4s", b); | |
331 | - } | |
332 | - printf("\n"); | |
333 | - line++; | |
514 | + case 'U' : case 'u': | |
515 | + if (tracking) | |
516 | + return 0; | |
517 | + tracking = 1; | |
518 | + break; | |
519 | + | |
520 | + case 'T' : case 't': | |
521 | + if (tracing) | |
522 | + return 0; | |
523 | + tracing = 1; | |
524 | + break; | |
525 | + default: | |
526 | + return 0; | |
527 | + } | |
528 | + return 1; | |
334 | 529 | } |
335 | 530 | |
336 | -void show_tracking(struct slabinfo *s) | |
531 | +int slab_empty(struct slabinfo *s) | |
337 | 532 | { |
338 | - printf("\n%s: Calls to allocate a slab object\n", s->name); | |
339 | - printf("---------------------------------------------------\n"); | |
340 | - if (read_obj("alloc_calls")) | |
341 | - printf(buffer); | |
533 | + if (s->objects > 0) | |
534 | + return 0; | |
342 | 535 | |
343 | - printf("%s: Calls to free a slab object\n", s->name); | |
344 | - printf("-----------------------------------------------\n"); | |
345 | - if (read_obj("free_calls")) | |
346 | - printf(buffer); | |
536 | + /* | |
537 | + * We may still have slabs even if there are no objects. Shrinking will | |
538 | + * remove them. | |
539 | + */ | |
540 | + if (s->slabs != 0) | |
541 | + set_obj(s, "shrink", 1); | |
347 | 542 | |
543 | + return 1; | |
348 | 544 | } |
349 | 545 | |
546 | +void slab_debug(struct slabinfo *s) | |
547 | +{ | |
548 | + if (sanity && !s->sanity_checks) { | |
549 | + set_obj(s, "sanity", 1); | |
550 | + } | |
551 | + if (!sanity && s->sanity_checks) { | |
552 | + if (slab_empty(s)) | |
553 | + set_obj(s, "sanity", 0); | |
554 | + else | |
555 | + fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name); | |
556 | + } | |
557 | + if (redzone && !s->red_zone) { | |
558 | + if (slab_empty(s)) | |
559 | + set_obj(s, "red_zone", 1); | |
560 | + else | |
561 | + fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name); | |
562 | + } | |
563 | + if (!redzone && s->red_zone) { | |
564 | + if (slab_empty(s)) | |
565 | + set_obj(s, "red_zone", 0); | |
566 | + else | |
567 | + fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name); | |
568 | + } | |
569 | + if (poison && !s->poison) { | |
570 | + if (slab_empty(s)) | |
571 | + set_obj(s, "poison", 1); | |
572 | + else | |
573 | + fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name); | |
574 | + } | |
575 | + if (!poison && s->poison) { | |
576 | + if (slab_empty(s)) | |
577 | + set_obj(s, "poison", 0); | |
578 | + else | |
579 | + fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name); | |
580 | + } | |
581 | + if (tracking && !s->store_user) { | |
582 | + if (slab_empty(s)) | |
583 | + set_obj(s, "store_user", 1); | |
584 | + else | |
585 | + fprintf(stderr, "%s not empty cannot enable tracking\n", s->name); | |
586 | + } | |
587 | + if (!tracking && s->store_user) { | |
588 | + if (slab_empty(s)) | |
589 | + set_obj(s, "store_user", 0); | |
590 | + else | |
591 | + fprintf(stderr, "%s not empty cannot disable tracking\n", s->name); | |
592 | + } | |
593 | + if (tracing && !s->trace) { | |
594 | + if (slabs == 1) | |
595 | + set_obj(s, "trace", 1); | |
596 | + else | |
597 | + fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name); | |
598 | + } | |
599 | + if (!tracing && s->trace) | |
600 | + set_obj(s, "trace", 1); | |
601 | +} | |
602 | + | |
350 | 603 | void totals(void) |
351 | 604 | { |
352 | 605 | struct slabinfo *s; |
... | ... | @@ -673,7 +926,7 @@ |
673 | 926 | |
674 | 927 | for (a = aliasinfo; a < aliasinfo + aliases; a++) { |
675 | 928 | |
676 | - for(s = slabinfo; s < slabinfo + slabs; s++) | |
929 | + for (s = slabinfo; s < slabinfo + slabs; s++) | |
677 | 930 | if (strcmp(a->ref, s->name) == 0) { |
678 | 931 | a->slab = s; |
679 | 932 | s->refs++; |
... | ... | @@ -704,7 +957,7 @@ |
704 | 957 | continue; |
705 | 958 | } |
706 | 959 | } |
707 | - printf("\n%-20s <- %s", a->slab->name, a->name); | |
960 | + printf("\n%-12s <- %s", a->slab->name, a->name); | |
708 | 961 | active = a->slab->name; |
709 | 962 | } |
710 | 963 | else |
... | ... | @@ -729,7 +982,12 @@ |
729 | 982 | |
730 | 983 | a = find_one_alias(s); |
731 | 984 | |
732 | - s->name = a->name; | |
985 | + if (a) | |
986 | + s->name = a->name; | |
987 | + else { | |
988 | + s->name = "*"; | |
989 | + actual_slabs--; | |
990 | + } | |
733 | 991 | } |
734 | 992 | } |
735 | 993 | |
736 | 994 | |
... | ... | @@ -748,11 +1006,14 @@ |
748 | 1006 | char *t; |
749 | 1007 | int count; |
750 | 1008 | |
1009 | + if (chdir("/sys/slab")) | |
1010 | + fatal("SYSFS support for SLUB not active\n"); | |
1011 | + | |
751 | 1012 | dir = opendir("."); |
752 | 1013 | while ((de = readdir(dir))) { |
753 | 1014 | if (de->d_name[0] == '.' || |
754 | - slab_mismatch(de->d_name)) | |
755 | - continue; | |
1015 | + (de->d_name[0] != ':' && slab_mismatch(de->d_name))) | |
1016 | + continue; | |
756 | 1017 | switch (de->d_type) { |
757 | 1018 | case DT_LNK: |
758 | 1019 | alias->name = strdup(de->d_name); |
... | ... | @@ -807,6 +1068,7 @@ |
807 | 1068 | } |
808 | 1069 | closedir(dir); |
809 | 1070 | slabs = slab - slabinfo; |
1071 | + actual_slabs = slabs; | |
810 | 1072 | aliases = alias - aliasinfo; |
811 | 1073 | if (slabs > MAX_SLABS) |
812 | 1074 | fatal("Too many slabs\n"); |
813 | 1075 | |
814 | 1076 | |
815 | 1077 | |
816 | 1078 | |
817 | 1079 | |
818 | 1080 | |
819 | 1081 | |
... | ... | @@ -825,34 +1087,37 @@ |
825 | 1087 | |
826 | 1088 | |
827 | 1089 | if (show_numa) |
828 | - slab_numa(slab); | |
829 | - else | |
830 | - if (show_track) | |
1090 | + slab_numa(slab, 0); | |
1091 | + else if (show_track) | |
831 | 1092 | show_tracking(slab); |
832 | - else | |
833 | - if (validate) | |
1093 | + else if (validate) | |
834 | 1094 | slab_validate(slab); |
835 | - else | |
836 | - if (shrink) | |
1095 | + else if (shrink) | |
837 | 1096 | slab_shrink(slab); |
838 | - else { | |
839 | - if (show_slab) | |
840 | - slabcache(slab); | |
841 | - } | |
1097 | + else if (set_debug) | |
1098 | + slab_debug(slab); | |
1099 | + else if (show_ops) | |
1100 | + ops(slab); | |
1101 | + else if (show_slab) | |
1102 | + slabcache(slab); | |
842 | 1103 | } |
843 | 1104 | } |
844 | 1105 | |
845 | 1106 | struct option opts[] = { |
846 | 1107 | { "aliases", 0, NULL, 'a' }, |
847 | - { "slabs", 0, NULL, 'l' }, | |
848 | - { "numa", 0, NULL, 'n' }, | |
849 | - { "zero", 0, NULL, 'z' }, | |
850 | - { "help", 0, NULL, 'h' }, | |
851 | - { "validate", 0, NULL, 'v' }, | |
1108 | + { "debug", 2, NULL, 'd' }, | |
1109 | + { "empty", 0, NULL, 'e' }, | |
852 | 1110 | { "first-alias", 0, NULL, 'f' }, |
1111 | + { "help", 0, NULL, 'h' }, | |
1112 | + { "inverted", 0, NULL, 'i'}, | |
1113 | + { "numa", 0, NULL, 'n' }, | |
1114 | + { "ops", 0, NULL, 'o' }, | |
1115 | + { "report", 0, NULL, 'r' }, | |
853 | 1116 | { "shrink", 0, NULL, 's' }, |
1117 | + { "slabs", 0, NULL, 'l' }, | |
854 | 1118 | { "track", 0, NULL, 't'}, |
855 | - { "inverted", 0, NULL, 'i'}, | |
1119 | + { "validate", 0, NULL, 'v' }, | |
1120 | + { "zero", 0, NULL, 'z' }, | |
856 | 1121 | { "1ref", 0, NULL, '1'}, |
857 | 1122 | { NULL, 0, NULL, 0 } |
858 | 1123 | }; |
859 | 1124 | |
... | ... | @@ -864,10 +1129,9 @@ |
864 | 1129 | char *pattern_source; |
865 | 1130 | |
866 | 1131 | page_size = getpagesize(); |
867 | - if (chdir("/sys/slab")) | |
868 | - fatal("This kernel does not have SLUB support.\n"); | |
869 | 1132 | |
870 | - while ((c = getopt_long(argc, argv, "afhil1npstvzTS", opts, NULL)) != -1) | |
1133 | + while ((c = getopt_long(argc, argv, "ad::efhil1noprstvzTS", | |
1134 | + opts, NULL)) != -1) | |
871 | 1135 | switch(c) { |
872 | 1136 | case '1': |
873 | 1137 | show_single_ref = 1; |
... | ... | @@ -875,6 +1139,14 @@ |
875 | 1139 | case 'a': |
876 | 1140 | show_alias = 1; |
877 | 1141 | break; |
1142 | + case 'd': | |
1143 | + set_debug = 1; | |
1144 | + if (!debug_opt_scan(optarg)) | |
1145 | + fatal("Invalid debug option '%s'\n", optarg); | |
1146 | + break; | |
1147 | + case 'e': | |
1148 | + show_empty = 1; | |
1149 | + break; | |
878 | 1150 | case 'f': |
879 | 1151 | show_first_alias = 1; |
880 | 1152 | break; |
... | ... | @@ -887,6 +1159,12 @@ |
887 | 1159 | case 'n': |
888 | 1160 | show_numa = 1; |
889 | 1161 | break; |
1162 | + case 'o': | |
1163 | + show_ops = 1; | |
1164 | + break; | |
1165 | + case 'r': | |
1166 | + show_report = 1; | |
1167 | + break; | |
890 | 1168 | case 's': |
891 | 1169 | shrink = 1; |
892 | 1170 | break; |
... | ... | @@ -914,8 +1192,8 @@ |
914 | 1192 | |
915 | 1193 | } |
916 | 1194 | |
917 | - if (!show_slab && !show_alias && !show_track | |
918 | - && !validate && !shrink) | |
1195 | + if (!show_slab && !show_alias && !show_track && !show_report | |
1196 | + && !validate && !shrink && !set_debug && !show_ops) | |
919 | 1197 | show_slab = 1; |
920 | 1198 | |
921 | 1199 | if (argc > optind) |