]> git.proxmox.com Git - mirror_zfs-debian.git/blob - cmd/arc_summary/arc_summary.py
Imported Upstream version 0.6.5.3
[mirror_zfs-debian.git] / cmd / arc_summary / arc_summary.py
1 #!/usr/bin/python
2 #
3 # $Id: arc_summary.pl,v 388:e27800740aa2 2011-07-08 02:53:29Z jhell $
4 #
5 # Copyright (c) 2008 Ben Rockwood <benr@cuddletech.com>,
6 # Copyright (c) 2010 Martin Matuska <mm@FreeBSD.org>,
7 # Copyright (c) 2010-2011 Jason J. Hellenthal <jhell@DataIX.net>,
8 # All rights reserved.
9 #
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions
12 # are met:
13 #
14 # 1. Redistributions of source code must retain the above copyright
15 # notice, this list of conditions and the following disclaimer.
16 # 2. Redistributions in binary form must reproduce the above copyright
17 # notice, this list of conditions and the following disclaimer in the
18 # documentation and/or other materials provided with the distribution.
19 #
20 # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 # SUCH DAMAGE.
31 #
32 # If you are having troubles when using this script from cron(8) please try
33 # adjusting your PATH before reporting problems.
34 #
35 # /usr/bin & /sbin
36 #
37 # Binaries used are:
38 #
39 # dc(1), kldstat(8), sed(1), sysctl(8) & vmstat(8)
40 #
41 # Binaries that I am working on phasing out are:
42 #
43 # dc(1) & sed(1)
44
45 import sys
46 import time
47 import getopt
48 import re
49 from os import listdir
50 from subprocess import Popen, PIPE
51 from decimal import Decimal as D
52
53
54 usetunable = True
55 show_tunable_descriptions = False
56 alternate_tunable_layout = False
57 kstat_pobj = re.compile("^([^:]+):\s+(.+)\s*$", flags=re.M)
58
59
60 def get_Kstat():
61 def load_proc_kstats(fn, namespace):
62 kstats = [line.strip() for line in open(fn)]
63 del kstats[0:2]
64 for kstat in kstats:
65 kstat = kstat.strip()
66 name, unused, value = kstat.split()
67 Kstat[namespace + name] = D(value)
68
69 Kstats = [
70 "hw.pagesize",
71 "hw.physmem",
72 "kern.maxusers",
73 "vm.kmem_map_free",
74 "vm.kmem_map_size",
75 "vm.kmem_size",
76 "vm.kmem_size_max",
77 "vm.kmem_size_min",
78 "vm.kmem_size_scale",
79 "vm.stats",
80 "vm.swap_total",
81 "vm.swap_reserved",
82 "kstat.zfs",
83 "vfs.zfs"
84 ]
85 Kstat = {}
86 load_proc_kstats('/proc/spl/kstat/zfs/arcstats',
87 'kstat.zfs.misc.arcstats.')
88 load_proc_kstats('/proc/spl/kstat/zfs/zfetchstats',
89 'kstat.zfs.misc.zfetchstats.')
90 load_proc_kstats('/proc/spl/kstat/zfs/vdev_cache_stats',
91 'kstat.zfs.misc.vdev_cache_stats.')
92
93 return Kstat
94
95 def div1():
96 sys.stdout.write("\n")
97 for i in xrange(18):
98 sys.stdout.write("%s" % "----")
99 sys.stdout.write("\n")
100
101
102 def div2():
103 sys.stdout.write("\n")
104
105
106 def fBytes(Bytes=0, Decimal=2):
107 kbytes = (2 ** 10)
108 mbytes = (2 ** 20)
109 gbytes = (2 ** 30)
110 tbytes = (2 ** 40)
111 pbytes = (2 ** 50)
112 ebytes = (2 ** 60)
113 zbytes = (2 ** 70)
114 ybytes = (2 ** 80)
115
116 if Bytes >= ybytes:
117 return str("%0." + str(Decimal) + "f") % (Bytes / ybytes) + "\tYiB"
118 elif Bytes >= zbytes:
119 return str("%0." + str(Decimal) + "f") % (Bytes / zbytes) + "\tZiB"
120 elif Bytes >= ebytes:
121 return str("%0." + str(Decimal) + "f") % (Bytes / ebytes) + "\tEiB"
122 elif Bytes >= pbytes:
123 return str("%0." + str(Decimal) + "f") % (Bytes / pbytes) + "\tPiB"
124 elif Bytes >= tbytes:
125 return str("%0." + str(Decimal) + "f") % (Bytes / tbytes) + "\tTiB"
126 elif Bytes >= gbytes:
127 return str("%0." + str(Decimal) + "f") % (Bytes / gbytes) + "\tGiB"
128 elif Bytes >= mbytes:
129 return str("%0." + str(Decimal) + "f") % (Bytes / mbytes) + "\tMiB"
130 elif Bytes >= kbytes:
131 return str("%0." + str(Decimal) + "f") % (Bytes / kbytes) + "\tKiB"
132 elif Bytes == 0:
133 return str("%d" % 0) + "\tBytes"
134 else:
135 return str("%d" % Bytes) + "\tBytes"
136
137
138 def fHits(Hits=0, Decimal=2):
139 khits = (10 ** 3)
140 mhits = (10 ** 6)
141 bhits = (10 ** 9)
142 thits = (10 ** 12)
143 qhits = (10 ** 15)
144 Qhits = (10 ** 18)
145 shits = (10 ** 21)
146 Shits = (10 ** 24)
147
148 if Hits >= Shits:
149 return str("%0." + str(Decimal) + "f") % (Hits / Shits) + "S"
150 elif Hits >= shits:
151 return str("%0." + str(Decimal) + "f") % (Hits / shits) + "s"
152 elif Hits >= Qhits:
153 return str("%0." + str(Decimal) + "f") % (Hits / Qhits) + "Q"
154 elif Hits >= qhits:
155 return str("%0." + str(Decimal) + "f") % (Hits / qhits) + "q"
156 elif Hits >= thits:
157 return str("%0." + str(Decimal) + "f") % (Hits / thits) + "t"
158 elif Hits >= bhits:
159 return str("%0." + str(Decimal) + "f") % (Hits / bhits) + "b"
160 elif Hits >= mhits:
161 return str("%0." + str(Decimal) + "f") % (Hits / mhits) + "m"
162 elif Hits >= khits:
163 return str("%0." + str(Decimal) + "f") % (Hits / khits) + "k"
164 elif Hits == 0:
165 return str("%d" % 0)
166 else:
167 return str("%d" % Hits)
168
169
170 def fPerc(lVal=0, rVal=0, Decimal=2):
171 if rVal > 0:
172 return str("%0." + str(Decimal) + "f") % (100 * (lVal / rVal)) + "%"
173 else:
174 return str("%0." + str(Decimal) + "f") % 100 + "%"
175
176
177 def get_arc_summary(Kstat):
178
179 output = {}
180 memory_throttle_count = Kstat[
181 "kstat.zfs.misc.arcstats.memory_throttle_count"
182 ]
183
184 if memory_throttle_count > 0:
185 output['health'] = 'THROTTLED'
186 else:
187 output['health'] = 'HEALTHY'
188
189 output['memory_throttle_count'] = fHits(memory_throttle_count)
190
191 ### ARC Misc. ###
192 deleted = Kstat["kstat.zfs.misc.arcstats.deleted"]
193 mutex_miss = Kstat["kstat.zfs.misc.arcstats.mutex_miss"]
194
195 ### ARC Misc. ###
196 output["arc_misc"] = {}
197 output["arc_misc"]["deleted"] = fHits(deleted)
198 output["arc_misc"]['mutex_miss'] = fHits(mutex_miss)
199 output["arc_misc"]['evict_skips'] = fHits(mutex_miss)
200
201 ### ARC Sizing ###
202 arc_size = Kstat["kstat.zfs.misc.arcstats.size"]
203 mru_size = Kstat["kstat.zfs.misc.arcstats.p"]
204 target_max_size = Kstat["kstat.zfs.misc.arcstats.c_max"]
205 target_min_size = Kstat["kstat.zfs.misc.arcstats.c_min"]
206 target_size = Kstat["kstat.zfs.misc.arcstats.c"]
207
208 target_size_ratio = (target_max_size / target_min_size)
209
210 ### ARC Sizing ###
211 output['arc_sizing'] = {}
212 output['arc_sizing']['arc_size'] = {
213 'per': fPerc(arc_size, target_max_size),
214 'num': fBytes(arc_size),
215 }
216 output['arc_sizing']['target_max_size'] = {
217 'ratio': target_size_ratio,
218 'num': fBytes(target_max_size),
219 }
220 output['arc_sizing']['target_min_size'] = {
221 'per': fPerc(target_min_size, target_max_size),
222 'num': fBytes(target_min_size),
223 }
224 output['arc_sizing']['target_size'] = {
225 'per': fPerc(target_size, target_max_size),
226 'num': fBytes(target_size),
227 }
228
229 ### ARC Hash Breakdown ###
230 output['arc_hash_break'] = {}
231 output['arc_hash_break']['hash_chain_max'] = Kstat[
232 "kstat.zfs.misc.arcstats.hash_chain_max"
233 ]
234 output['arc_hash_break']['hash_chains'] = Kstat[
235 "kstat.zfs.misc.arcstats.hash_chains"
236 ]
237 output['arc_hash_break']['hash_collisions'] = Kstat[
238 "kstat.zfs.misc.arcstats.hash_collisions"
239 ]
240 output['arc_hash_break']['hash_elements'] = Kstat[
241 "kstat.zfs.misc.arcstats.hash_elements"
242 ]
243 output['arc_hash_break']['hash_elements_max'] = Kstat[
244 "kstat.zfs.misc.arcstats.hash_elements_max"
245 ]
246
247 output['arc_size_break'] = {}
248 if arc_size > target_size:
249 mfu_size = (arc_size - mru_size)
250 output['arc_size_break']['recently_used_cache_size'] = {
251 'per': fPerc(mru_size, arc_size),
252 'num': fBytes(mru_size),
253 }
254 output['arc_size_break']['frequently_used_cache_size'] = {
255 'per': fPerc(mfu_size, arc_size),
256 'num': fBytes(mfu_size),
257 }
258
259 elif arc_size < target_size:
260 mfu_size = (target_size - mru_size)
261 output['arc_size_break']['recently_used_cache_size'] = {
262 'per': fPerc(mru_size, target_size),
263 'num': fBytes(mru_size),
264 }
265 output['arc_size_break']['frequently_used_cache_size'] = {
266 'per': fPerc(mfu_size, target_size),
267 'num': fBytes(mfu_size),
268 }
269
270 ### ARC Hash Breakdown ###
271 hash_chain_max = Kstat["kstat.zfs.misc.arcstats.hash_chain_max"]
272 hash_chains = Kstat["kstat.zfs.misc.arcstats.hash_chains"]
273 hash_collisions = Kstat["kstat.zfs.misc.arcstats.hash_collisions"]
274 hash_elements = Kstat["kstat.zfs.misc.arcstats.hash_elements"]
275 hash_elements_max = Kstat["kstat.zfs.misc.arcstats.hash_elements_max"]
276
277 output['arc_hash_break'] = {}
278 output['arc_hash_break']['elements_max'] = fHits(hash_elements_max)
279 output['arc_hash_break']['elements_current'] = {
280 'per': fPerc(hash_elements, hash_elements_max),
281 'num': fHits(hash_elements),
282 }
283 output['arc_hash_break']['collisions'] = fHits(hash_collisions)
284 output['arc_hash_break']['chain_max'] = fHits(hash_chain_max)
285 output['arc_hash_break']['chains'] = fHits(hash_chains)
286
287 return output
288
289
290 def _arc_summary(Kstat):
291 ### ARC Sizing ###
292 arc = get_arc_summary(Kstat)
293
294 sys.stdout.write("ARC Summary: (%s)\n" % arc['health'])
295
296 sys.stdout.write("\tMemory Throttle Count:\t\t\t%s\n" %
297 arc['memory_throttle_count'])
298 sys.stdout.write("\n")
299
300 ### ARC Misc. ###
301 sys.stdout.write("ARC Misc:\n")
302 sys.stdout.write("\tDeleted:\t\t\t\t%s\n" % arc['arc_misc']['deleted'])
303 sys.stdout.write("\tMutex Misses:\t\t\t\t%s\n" %
304 arc['arc_misc']['mutex_miss'])
305 sys.stdout.write("\tEvict Skips:\t\t\t\t%s\n" %
306 arc['arc_misc']['mutex_miss'])
307 sys.stdout.write("\n")
308
309 ### ARC Sizing ###
310 sys.stdout.write("ARC Size:\t\t\t\t%s\t%s\n" % (
311 arc['arc_sizing']['arc_size']['per'],
312 arc['arc_sizing']['arc_size']['num']
313 )
314 )
315 sys.stdout.write("\tTarget Size: (Adaptive)\t\t%s\t%s\n" % (
316 arc['arc_sizing']['target_size']['per'],
317 arc['arc_sizing']['target_size']['num'],
318 )
319 )
320
321 sys.stdout.write("\tMin Size (Hard Limit):\t\t%s\t%s\n" % (
322 arc['arc_sizing']['target_min_size']['per'],
323 arc['arc_sizing']['target_min_size']['num'],
324 )
325 )
326
327 sys.stdout.write("\tMax Size (High Water):\t\t%d:1\t%s\n" % (
328 arc['arc_sizing']['target_max_size']['ratio'],
329 arc['arc_sizing']['target_max_size']['num'],
330 )
331 )
332
333 sys.stdout.write("\nARC Size Breakdown:\n")
334 sys.stdout.write("\tRecently Used Cache Size:\t%s\t%s\n" % (
335 arc['arc_size_break']['recently_used_cache_size']['per'],
336 arc['arc_size_break']['recently_used_cache_size']['num'],
337 )
338 )
339 sys.stdout.write("\tFrequently Used Cache Size:\t%s\t%s\n" % (
340 arc['arc_size_break']['frequently_used_cache_size']['per'],
341 arc['arc_size_break']['frequently_used_cache_size']['num'],
342 )
343 )
344
345 sys.stdout.write("\n")
346
347 ### ARC Hash Breakdown ###
348 sys.stdout.write("ARC Hash Breakdown:\n")
349 sys.stdout.write("\tElements Max:\t\t\t\t%s\n" %
350 arc['arc_hash_break']['elements_max'])
351 sys.stdout.write("\tElements Current:\t\t%s\t%s\n" % (
352 arc['arc_hash_break']['elements_current']['per'],
353 arc['arc_hash_break']['elements_current']['num'],
354 )
355 )
356 sys.stdout.write("\tCollisions:\t\t\t\t%s\n" %
357 arc['arc_hash_break']['collisions'])
358 sys.stdout.write("\tChain Max:\t\t\t\t%s\n" %
359 arc['arc_hash_break']['chain_max'])
360 sys.stdout.write("\tChains:\t\t\t\t\t%s\n" %
361 arc['arc_hash_break']['chains'])
362
363
364 def get_arc_efficiency(Kstat):
365 output = {}
366
367 arc_hits = Kstat["kstat.zfs.misc.arcstats.hits"]
368 arc_misses = Kstat["kstat.zfs.misc.arcstats.misses"]
369 demand_data_hits = Kstat["kstat.zfs.misc.arcstats.demand_data_hits"]
370 demand_data_misses = Kstat["kstat.zfs.misc.arcstats.demand_data_misses"]
371 demand_metadata_hits = Kstat[
372 "kstat.zfs.misc.arcstats.demand_metadata_hits"
373 ]
374 demand_metadata_misses = Kstat[
375 "kstat.zfs.misc.arcstats.demand_metadata_misses"
376 ]
377 mfu_ghost_hits = Kstat["kstat.zfs.misc.arcstats.mfu_ghost_hits"]
378 mfu_hits = Kstat["kstat.zfs.misc.arcstats.mfu_hits"]
379 mru_ghost_hits = Kstat["kstat.zfs.misc.arcstats.mru_ghost_hits"]
380 mru_hits = Kstat["kstat.zfs.misc.arcstats.mru_hits"]
381 prefetch_data_hits = Kstat["kstat.zfs.misc.arcstats.prefetch_data_hits"]
382 prefetch_data_misses = Kstat[
383 "kstat.zfs.misc.arcstats.prefetch_data_misses"
384 ]
385 prefetch_metadata_hits = Kstat[
386 "kstat.zfs.misc.arcstats.prefetch_metadata_hits"
387 ]
388 prefetch_metadata_misses = Kstat[
389 "kstat.zfs.misc.arcstats.prefetch_metadata_misses"
390 ]
391
392 anon_hits = arc_hits - (
393 mfu_hits + mru_hits + mfu_ghost_hits + mru_ghost_hits
394 )
395 arc_accesses_total = (arc_hits + arc_misses)
396 demand_data_total = (demand_data_hits + demand_data_misses)
397 prefetch_data_total = (prefetch_data_hits + prefetch_data_misses)
398 real_hits = (mfu_hits + mru_hits)
399
400 output["total_accesses"] = fHits(arc_accesses_total)
401 output["cache_hit_ratio"] = {
402 'per': fPerc(arc_hits, arc_accesses_total),
403 'num': fHits(arc_hits),
404 }
405 output["cache_miss_ratio"] = {
406 'per': fPerc(arc_misses, arc_accesses_total),
407 'num': fHits(arc_misses),
408 }
409 output["actual_hit_ratio"] = {
410 'per': fPerc(real_hits, arc_accesses_total),
411 'num': fHits(real_hits),
412 }
413 output["data_demand_efficiency"] = {
414 'per': fPerc(demand_data_hits, demand_data_total),
415 'num': fHits(demand_data_total),
416 }
417
418 if prefetch_data_total > 0:
419 output["data_prefetch_efficiency"] = {
420 'per': fPerc(prefetch_data_hits, prefetch_data_total),
421 'num': fHits(prefetch_data_total),
422 }
423
424 if anon_hits > 0:
425 output["cache_hits_by_cache_list"] = {}
426 output["cache_hits_by_cache_list"]["anonymously_used"] = {
427 'per': fPerc(anon_hits, arc_hits),
428 'num': fHits(anon_hits),
429 }
430
431 output["most_recently_used"] = {
432 'per': fPerc(mru_hits, arc_hits),
433 'num': fHits(mru_hits),
434 }
435 output["most_frequently_used"] = {
436 'per': fPerc(mfu_hits, arc_hits),
437 'num': fHits(mfu_hits),
438 }
439 output["most_recently_used_ghost"] = {
440 'per': fPerc(mru_ghost_hits, arc_hits),
441 'num': fHits(mru_ghost_hits),
442 }
443 output["most_frequently_used_ghost"] = {
444 'per': fPerc(mfu_ghost_hits, arc_hits),
445 'num': fHits(mfu_ghost_hits),
446 }
447
448 output["cache_hits_by_data_type"] = {}
449 output["cache_hits_by_data_type"]["demand_data"] = {
450 'per': fPerc(demand_data_hits, arc_hits),
451 'num': fHits(demand_data_hits),
452 }
453 output["cache_hits_by_data_type"]["prefetch_data"] = {
454 'per': fPerc(prefetch_data_hits, arc_hits),
455 'num': fHits(prefetch_data_hits),
456 }
457 output["cache_hits_by_data_type"]["demand_metadata"] = {
458 'per': fPerc(demand_metadata_hits, arc_hits),
459 'num': fHits(demand_metadata_hits),
460 }
461 output["cache_hits_by_data_type"]["prefetch_metadata"] = {
462 'per': fPerc(prefetch_metadata_hits, arc_hits),
463 'num': fHits(prefetch_metadata_hits),
464 }
465
466 output["cache_misses_by_data_type"] = {}
467 output["cache_misses_by_data_type"]["demand_data"] = {
468 'per': fPerc(demand_data_misses, arc_misses),
469 'num': fHits(demand_data_misses),
470 }
471 output["cache_misses_by_data_type"]["prefetch_data"] = {
472 'per': fPerc(prefetch_data_misses, arc_misses),
473 'num': fHits(prefetch_data_misses),
474 }
475 output["cache_misses_by_data_type"]["demand_metadata"] = {
476 'per': fPerc(demand_metadata_misses, arc_misses),
477 'num': fHits(demand_metadata_misses),
478 }
479 output["cache_misses_by_data_type"]["prefetch_metadata"] = {
480 'per': fPerc(prefetch_metadata_misses, arc_misses),
481 'num': fHits(prefetch_metadata_misses),
482 }
483
484 return output
485
486
487 def _arc_efficiency(Kstat):
488 arc = get_arc_efficiency(Kstat)
489
490 sys.stdout.write("ARC Total accesses:\t\t\t\t\t%s\n" %
491 arc['total_accesses'])
492 sys.stdout.write("\tCache Hit Ratio:\t\t%s\t%s\n" % (
493 arc['cache_hit_ratio']['per'],
494 arc['cache_hit_ratio']['num'],
495 )
496 )
497 sys.stdout.write("\tCache Miss Ratio:\t\t%s\t%s\n" % (
498 arc['cache_miss_ratio']['per'],
499 arc['cache_miss_ratio']['num'],
500 )
501 )
502
503 sys.stdout.write("\tActual Hit Ratio:\t\t%s\t%s\n" % (
504 arc['actual_hit_ratio']['per'],
505 arc['actual_hit_ratio']['num'],
506 )
507 )
508
509 sys.stdout.write("\n")
510 sys.stdout.write("\tData Demand Efficiency:\t\t%s\t%s\n" % (
511 arc['data_demand_efficiency']['per'],
512 arc['data_demand_efficiency']['num'],
513 )
514 )
515
516 if 'data_prefetch_efficiency' in arc:
517 sys.stdout.write("\tData Prefetch Efficiency:\t%s\t%s\n" % (
518 arc['data_prefetch_efficiency']['per'],
519 arc['data_prefetch_efficiency']['num'],
520 )
521 )
522 sys.stdout.write("\n")
523
524 sys.stdout.write("\tCACHE HITS BY CACHE LIST:\n")
525 if 'cache_hits_by_cache_list' in arc:
526 sys.stdout.write("\t Anonymously Used:\t\t%s\t%s\n" % (
527 arc['cache_hits_by_cache_list']['anonymously_used']['per'],
528 arc['cache_hits_by_cache_list']['anonymously_used']['num'],
529 )
530 )
531 sys.stdout.write("\t Most Recently Used:\t\t%s\t%s\n" % (
532 arc['most_recently_used']['per'],
533 arc['most_recently_used']['num'],
534 )
535 )
536 sys.stdout.write("\t Most Frequently Used:\t\t%s\t%s\n" % (
537 arc['most_frequently_used']['per'],
538 arc['most_frequently_used']['num'],
539 )
540 )
541 sys.stdout.write("\t Most Recently Used Ghost:\t%s\t%s\n" % (
542 arc['most_recently_used_ghost']['per'],
543 arc['most_recently_used_ghost']['num'],
544 )
545 )
546 sys.stdout.write("\t Most Frequently Used Ghost:\t%s\t%s\n" % (
547 arc['most_frequently_used_ghost']['per'],
548 arc['most_frequently_used_ghost']['num'],
549 )
550 )
551
552 sys.stdout.write("\n\tCACHE HITS BY DATA TYPE:\n")
553 sys.stdout.write("\t Demand Data:\t\t\t%s\t%s\n" % (
554 arc["cache_hits_by_data_type"]['demand_data']['per'],
555 arc["cache_hits_by_data_type"]['demand_data']['num'],
556 )
557 )
558 sys.stdout.write("\t Prefetch Data:\t\t%s\t%s\n" % (
559 arc["cache_hits_by_data_type"]['prefetch_data']['per'],
560 arc["cache_hits_by_data_type"]['prefetch_data']['num'],
561 )
562 )
563 sys.stdout.write("\t Demand Metadata:\t\t%s\t%s\n" % (
564 arc["cache_hits_by_data_type"]['demand_metadata']['per'],
565 arc["cache_hits_by_data_type"]['demand_metadata']['num'],
566 )
567 )
568 sys.stdout.write("\t Prefetch Metadata:\t\t%s\t%s\n" % (
569 arc["cache_hits_by_data_type"]['prefetch_metadata']['per'],
570 arc["cache_hits_by_data_type"]['prefetch_metadata']['num'],
571 )
572 )
573
574 sys.stdout.write("\n\tCACHE MISSES BY DATA TYPE:\n")
575 sys.stdout.write("\t Demand Data:\t\t\t%s\t%s\n" % (
576 arc["cache_misses_by_data_type"]['demand_data']['per'],
577 arc["cache_misses_by_data_type"]['demand_data']['num'],
578 )
579 )
580 sys.stdout.write("\t Prefetch Data:\t\t%s\t%s\n" % (
581 arc["cache_misses_by_data_type"]['prefetch_data']['per'],
582 arc["cache_misses_by_data_type"]['prefetch_data']['num'],
583 )
584 )
585 sys.stdout.write("\t Demand Metadata:\t\t%s\t%s\n" % (
586 arc["cache_misses_by_data_type"]['demand_metadata']['per'],
587 arc["cache_misses_by_data_type"]['demand_metadata']['num'],
588 )
589 )
590 sys.stdout.write("\t Prefetch Metadata:\t\t%s\t%s\n" % (
591 arc["cache_misses_by_data_type"]['prefetch_metadata']['per'],
592 arc["cache_misses_by_data_type"]['prefetch_metadata']['num'],
593 )
594 )
595
596
597 def get_l2arc_summary(Kstat):
598 output = {}
599
600 l2_abort_lowmem = Kstat["kstat.zfs.misc.arcstats.l2_abort_lowmem"]
601 l2_cksum_bad = Kstat["kstat.zfs.misc.arcstats.l2_cksum_bad"]
602 l2_evict_lock_retry = Kstat["kstat.zfs.misc.arcstats.l2_evict_lock_retry"]
603 l2_evict_reading = Kstat["kstat.zfs.misc.arcstats.l2_evict_reading"]
604 l2_feeds = Kstat["kstat.zfs.misc.arcstats.l2_feeds"]
605 l2_free_on_write = Kstat["kstat.zfs.misc.arcstats.l2_free_on_write"]
606 l2_hdr_size = Kstat["kstat.zfs.misc.arcstats.l2_hdr_size"]
607 l2_hits = Kstat["kstat.zfs.misc.arcstats.l2_hits"]
608 l2_io_error = Kstat["kstat.zfs.misc.arcstats.l2_io_error"]
609 l2_misses = Kstat["kstat.zfs.misc.arcstats.l2_misses"]
610 l2_rw_clash = Kstat["kstat.zfs.misc.arcstats.l2_rw_clash"]
611 l2_size = Kstat["kstat.zfs.misc.arcstats.l2_size"]
612 l2_asize = Kstat["kstat.zfs.misc.arcstats.l2_asize"]
613 l2_writes_done = Kstat["kstat.zfs.misc.arcstats.l2_writes_done"]
614 l2_writes_error = Kstat["kstat.zfs.misc.arcstats.l2_writes_error"]
615 l2_writes_sent = Kstat["kstat.zfs.misc.arcstats.l2_writes_sent"]
616
617 l2_access_total = (l2_hits + l2_misses)
618 output['l2_health_count'] = (l2_writes_error + l2_cksum_bad + l2_io_error)
619
620 output['l2_access_total'] = l2_access_total
621 output['l2_size'] = l2_size
622 output['l2_asize'] = l2_asize
623
624 if l2_size > 0 and l2_access_total > 0:
625
626 if output['l2_health_count'] > 0:
627 output["health"] = "DEGRADED"
628 else:
629 output["health"] = "HEALTHY"
630
631 output["low_memory_aborts"] = fHits(l2_abort_lowmem)
632 output["free_on_write"] = fHits(l2_free_on_write)
633 output["rw_clashes"] = fHits(l2_rw_clash)
634 output["bad_checksums"] = fHits(l2_cksum_bad)
635 output["io_errors"] = fHits(l2_io_error)
636
637 output["l2_arc_size"] = {}
638 output["l2_arc_size"]["adative"] = fBytes(l2_size)
639 output["l2_arc_size"]["actual"] = {
640 'per': fPerc(l2_asize, l2_size),
641 'num': fBytes(l2_asize)
642 }
643 output["l2_arc_size"]["head_size"] = {
644 'per': fPerc(l2_hdr_size, l2_size),
645 'num': fBytes(l2_hdr_size),
646 }
647
648 output["l2_arc_evicts"] = {}
649 output["l2_arc_evicts"]['lock_retries'] = fHits(l2_evict_lock_retry)
650 output["l2_arc_evicts"]['reading'] = fHits(l2_evict_reading)
651
652 output['l2_arc_breakdown'] = {}
653 output['l2_arc_breakdown']['value'] = fHits(l2_access_total)
654 output['l2_arc_breakdown']['hit_ratio'] = {
655 'per': fPerc(l2_hits, l2_access_total),
656 'num': fHits(l2_hits),
657 }
658 output['l2_arc_breakdown']['miss_ratio'] = {
659 'per': fPerc(l2_misses, l2_access_total),
660 'num': fHits(l2_misses),
661 }
662 output['l2_arc_breakdown']['feeds'] = fHits(l2_feeds)
663
664 output['l2_arc_buffer'] = {}
665
666 output['l2_arc_writes'] = {}
667 output['l2_writes_done'] = l2_writes_done
668 output['l2_writes_sent'] = l2_writes_sent
669 if l2_writes_done != l2_writes_sent:
670 output['l2_arc_writes']['writes_sent'] = {
671 'value': "FAULTED",
672 'num': fHits(l2_writes_sent),
673 }
674 output['l2_arc_writes']['done_ratio'] = {
675 'per': fPerc(l2_writes_done, l2_writes_sent),
676 'num': fHits(l2_writes_done),
677 }
678 output['l2_arc_writes']['error_ratio'] = {
679 'per': fPerc(l2_writes_error, l2_writes_sent),
680 'num': fHits(l2_writes_error),
681 }
682 else:
683 output['l2_arc_writes']['writes_sent'] = {
684 'per': fPerc(100),
685 'num': fHits(l2_writes_sent),
686 }
687
688 return output
689
690
691 def _l2arc_summary(Kstat):
692
693 arc = get_l2arc_summary(Kstat)
694
695 if arc['l2_size'] > 0 and arc['l2_access_total'] > 0:
696 sys.stdout.write("L2 ARC Summary: ")
697 if arc['l2_health_count'] > 0:
698 sys.stdout.write("(DEGRADED)\n")
699 else:
700 sys.stdout.write("(HEALTHY)\n")
701 sys.stdout.write("\tLow Memory Aborts:\t\t\t%s\n" %
702 arc['low_memory_aborts'])
703 sys.stdout.write("\tFree on Write:\t\t\t\t%s\n" % arc['free_on_write'])
704 sys.stdout.write("\tR/W Clashes:\t\t\t\t%s\n" % arc['rw_clashes'])
705 sys.stdout.write("\tBad Checksums:\t\t\t\t%s\n" % arc['bad_checksums'])
706 sys.stdout.write("\tIO Errors:\t\t\t\t%s\n" % arc['io_errors'])
707 sys.stdout.write("\n")
708
709 sys.stdout.write("L2 ARC Size: (Adaptive)\t\t\t\t%s\n" %
710 arc["l2_arc_size"]["adative"])
711 sys.stdout.write("\tCompressed:\t\t\t%s\t%s\n" % (
712 arc["l2_arc_size"]["actual"]["per"],
713 arc["l2_arc_size"]["actual"]["num"],
714 )
715 )
716 sys.stdout.write("\tHeader Size:\t\t\t%s\t%s\n" % (
717 arc["l2_arc_size"]["head_size"]["per"],
718 arc["l2_arc_size"]["head_size"]["num"],
719 )
720 )
721 sys.stdout.write("\n")
722
723 if arc["l2_arc_evicts"]['lock_retries'] + \
724 arc["l2_arc_evicts"]["reading"] > 0:
725 sys.stdout.write("L2 ARC Evicts:\n")
726 sys.stdout.write("\tLock Retries:\t\t\t\t%s\n" %
727 arc["l2_arc_evicts"]['lock_retries'])
728 sys.stdout.write("\tUpon Reading:\t\t\t\t%s\n" %
729 arc["l2_arc_evicts"]["reading"])
730 sys.stdout.write("\n")
731
732 sys.stdout.write("L2 ARC Breakdown:\t\t\t\t%s\n" %
733 arc['l2_arc_breakdown']['value'])
734 sys.stdout.write("\tHit Ratio:\t\t\t%s\t%s\n" % (
735 arc['l2_arc_breakdown']['hit_ratio']['per'],
736 arc['l2_arc_breakdown']['hit_ratio']['num'],
737 )
738 )
739
740 sys.stdout.write("\tMiss Ratio:\t\t\t%s\t%s\n" % (
741 arc['l2_arc_breakdown']['miss_ratio']['per'],
742 arc['l2_arc_breakdown']['miss_ratio']['num'],
743 )
744 )
745
746 sys.stdout.write("\tFeeds:\t\t\t\t\t%s\n" %
747 arc['l2_arc_breakdown']['feeds'])
748 sys.stdout.write("\n")
749
750 sys.stdout.write("L2 ARC Writes:\n")
751 if arc['l2_writes_done'] != arc['l2_writes_sent']:
752 sys.stdout.write("\tWrites Sent: (%s)\t\t\t\t%s\n" % (
753 arc['l2_arc_writes']['writes_sent']['value'],
754 arc['l2_arc_writes']['writes_sent']['num'],
755 )
756 )
757 sys.stdout.write("\t Done Ratio:\t\t\t%s\t%s\n" % (
758 arc['l2_arc_writes']['done_ratio']['per'],
759 arc['l2_arc_writes']['done_ratio']['num'],
760 )
761 )
762 sys.stdout.write("\t Error Ratio:\t\t\t%s\t%s\n" % (
763 arc['l2_arc_writes']['error_ratio']['per'],
764 arc['l2_arc_writes']['error_ratio']['num'],
765 )
766 )
767 else:
768 sys.stdout.write("\tWrites Sent:\t\t\t%s\t%s\n" % (
769 arc['l2_arc_writes']['writes_sent']['per'],
770 arc['l2_arc_writes']['writes_sent']['num'],
771 )
772 )
773
774
775 def get_dmu_summary(Kstat):
776 output = {}
777
778 zfetch_bogus_streams = Kstat["kstat.zfs.misc.zfetchstats.bogus_streams"]
779 zfetch_colinear_hits = Kstat["kstat.zfs.misc.zfetchstats.colinear_hits"]
780 zfetch_colinear_misses = \
781 Kstat["kstat.zfs.misc.zfetchstats.colinear_misses"]
782 zfetch_hits = Kstat["kstat.zfs.misc.zfetchstats.hits"]
783 zfetch_misses = Kstat["kstat.zfs.misc.zfetchstats.misses"]
784 zfetch_reclaim_failures = \
785 Kstat["kstat.zfs.misc.zfetchstats.reclaim_failures"]
786 zfetch_reclaim_successes = \
787 Kstat["kstat.zfs.misc.zfetchstats.reclaim_successes"]
788 zfetch_streams_noresets = \
789 Kstat["kstat.zfs.misc.zfetchstats.streams_noresets"]
790 zfetch_streams_resets = Kstat["kstat.zfs.misc.zfetchstats.streams_resets"]
791 zfetch_stride_hits = Kstat["kstat.zfs.misc.zfetchstats.stride_hits"]
792 zfetch_stride_misses = Kstat["kstat.zfs.misc.zfetchstats.stride_misses"]
793
794 zfetch_access_total = (zfetch_hits + zfetch_misses)
795 zfetch_colinear_total = (zfetch_colinear_hits + zfetch_colinear_misses)
796 zfetch_health_count = (zfetch_bogus_streams)
797 zfetch_reclaim_total = (zfetch_reclaim_successes + zfetch_reclaim_failures)
798 zfetch_streams_total = (zfetch_streams_resets + zfetch_streams_noresets +
799 zfetch_bogus_streams)
800 zfetch_stride_total = (zfetch_stride_hits + zfetch_stride_misses)
801 output['zfetch_access_total'] = zfetch_access_total
802
803 if zfetch_access_total > 0:
804
805 output['file_level_prefetch'] = {}
806 if zfetch_health_count > 0:
807 output['file_level_prefetch']['health'] = 'DEGRADED'
808 else:
809 output['file_level_prefetch']['health'] = 'HEALTHY'
810
811 output['dmu'] = {}
812 output['dmu']['efficiency'] = {}
813 output['dmu']['efficiency']['value'] = fHits(zfetch_access_total)
814 output['dmu']['efficiency']['hit_ratio'] = {
815 'per': fPerc(zfetch_hits, zfetch_access_total),
816 'num': fHits(zfetch_hits),
817 }
818 output['dmu']['efficiency']['miss_ratio'] = {
819 'per': fPerc(zfetch_misses, zfetch_access_total),
820 'num': fHits(zfetch_misses),
821 }
822
823 output['dmu']['colinear'] = {}
824 output['dmu']['colinear']['value'] = fHits(zfetch_colinear_total)
825 output['dmu']['colinear']['hit_ratio'] = {
826 'per': fPerc(zfetch_colinear_hits, zfetch_colinear_total),
827 'num': fHits(zfetch_colinear_hits),
828 }
829 output['dmu']['colinear']['miss_ratio'] = {
830 'per': fPerc(zfetch_colinear_misses, zfetch_colinear_total),
831 'num': fHits(zfetch_colinear_misses),
832 }
833
834 output['dmu']['stride'] = {}
835 output['dmu']['stride']['value'] = fHits(zfetch_stride_total)
836 output['dmu']['stride']['hit_ratio'] = {
837 'per': fPerc(zfetch_stride_hits, zfetch_stride_total),
838 'num': fHits(zfetch_stride_hits),
839 }
840 output['dmu']['stride']['miss_ratio'] = {
841 'per': fPerc(zfetch_stride_misses, zfetch_stride_total),
842 'num': fHits(zfetch_stride_misses),
843 }
844
845 output['dmu_misc'] = {}
846 if zfetch_health_count > 0:
847 output['dmu_misc']['status'] = "FAULTED"
848 else:
849 output['dmu_misc']['status'] = ""
850
851 output['dmu_misc']['reclaim'] = {}
852 output['dmu_misc']['reclaim']['value'] = fHits(zfetch_reclaim_total)
853 output['dmu_misc']['reclaim']['successes'] = {
854 'per': fPerc(zfetch_reclaim_successes, zfetch_reclaim_total),
855 'num': fHits(zfetch_reclaim_successes),
856 }
857 output['dmu_misc']['reclaim']['failure'] = {
858 'per': fPerc(zfetch_reclaim_failures, zfetch_reclaim_total),
859 'num': fHits(zfetch_reclaim_failures),
860 }
861
862 output['dmu_misc']['streams'] = {}
863 output['dmu_misc']['streams']['value'] = fHits(zfetch_streams_total)
864 output['dmu_misc']['streams']['plus_resets'] = {
865 'per': fPerc(zfetch_streams_resets, zfetch_streams_total),
866 'num': fHits(zfetch_streams_resets),
867 }
868 output['dmu_misc']['streams']['neg_resets'] = {
869 'per': fPerc(zfetch_streams_noresets, zfetch_streams_total),
870 'num': fHits(zfetch_streams_noresets),
871 }
872 output['dmu_misc']['streams']['bogus'] = fHits(zfetch_bogus_streams)
873
874 return output
875
876
877 def _dmu_summary(Kstat):
878
879 arc = get_dmu_summary(Kstat)
880
881 if arc['zfetch_access_total'] > 0:
882 sys.stdout.write("File-Level Prefetch: (%s)" %
883 arc['file_level_prefetch']['health'])
884 sys.stdout.write("\n")
885
886 sys.stdout.write("DMU Efficiency:\t\t\t\t\t%s\n" %
887 arc['dmu']['efficiency']['value'])
888 sys.stdout.write("\tHit Ratio:\t\t\t%s\t%s\n" % (
889 arc['dmu']['efficiency']['hit_ratio']['per'],
890 arc['dmu']['efficiency']['hit_ratio']['num'],
891 )
892 )
893 sys.stdout.write("\tMiss Ratio:\t\t\t%s\t%s\n" % (
894 arc['dmu']['efficiency']['miss_ratio']['per'],
895 arc['dmu']['efficiency']['miss_ratio']['num'],
896 )
897 )
898
899 sys.stdout.write("\n")
900
901 sys.stdout.write("\tColinear:\t\t\t\t%s\n" %
902 arc['dmu']['colinear']['value'])
903 sys.stdout.write("\t Hit Ratio:\t\t\t%s\t%s\n" % (
904 arc['dmu']['colinear']['hit_ratio']['per'],
905 arc['dmu']['colinear']['hit_ratio']['num'],
906 )
907 )
908
909 sys.stdout.write("\t Miss Ratio:\t\t\t%s\t%s\n" % (
910 arc['dmu']['colinear']['miss_ratio']['per'],
911 arc['dmu']['colinear']['miss_ratio']['num'],
912 )
913 )
914
915 sys.stdout.write("\n")
916
917 sys.stdout.write("\tStride:\t\t\t\t\t%s\n" %
918 arc['dmu']['stride']['value'])
919 sys.stdout.write("\t Hit Ratio:\t\t\t%s\t%s\n" % (
920 arc['dmu']['stride']['hit_ratio']['per'],
921 arc['dmu']['stride']['hit_ratio']['num'],
922 )
923 )
924
925 sys.stdout.write("\t Miss Ratio:\t\t\t%s\t%s\n" % (
926 arc['dmu']['stride']['miss_ratio']['per'],
927 arc['dmu']['stride']['miss_ratio']['num'],
928 )
929 )
930
931 sys.stdout.write("\n")
932 sys.stdout.write("DMU Misc: %s\n" % arc['dmu_misc']['status'])
933
934 sys.stdout.write("\tReclaim:\t\t\t\t%s\n" %
935 arc['dmu_misc']['reclaim']['value'])
936 sys.stdout.write("\t Successes:\t\t\t%s\t%s\n" % (
937 arc['dmu_misc']['reclaim']['successes']['per'],
938 arc['dmu_misc']['reclaim']['successes']['num'],
939 )
940 )
941
942 sys.stdout.write("\t Failures:\t\t\t%s\t%s\n" % (
943 arc['dmu_misc']['reclaim']['failure']['per'],
944 arc['dmu_misc']['reclaim']['failure']['num'],
945 )
946 )
947
948 sys.stdout.write("\n\tStreams:\t\t\t\t%s\n" %
949 arc['dmu_misc']['streams']['value'])
950 sys.stdout.write("\t +Resets:\t\t\t%s\t%s\n" % (
951 arc['dmu_misc']['streams']['plus_resets']['per'],
952 arc['dmu_misc']['streams']['plus_resets']['num'],
953 )
954 )
955
956 sys.stdout.write("\t -Resets:\t\t\t%s\t%s\n" % (
957 arc['dmu_misc']['streams']['neg_resets']['per'],
958 arc['dmu_misc']['streams']['neg_resets']['num'],
959 )
960 )
961
962 sys.stdout.write("\t Bogus:\t\t\t\t%s\n" %
963 arc['dmu_misc']['streams']['bogus'])
964
965
966 def get_vdev_summary(Kstat):
967 output = {}
968
969 vdev_cache_delegations = \
970 Kstat["kstat.zfs.misc.vdev_cache_stats.delegations"]
971 vdev_cache_misses = Kstat["kstat.zfs.misc.vdev_cache_stats.misses"]
972 vdev_cache_hits = Kstat["kstat.zfs.misc.vdev_cache_stats.hits"]
973 vdev_cache_total = (vdev_cache_misses + vdev_cache_hits +
974 vdev_cache_delegations)
975
976 output['vdev_cache_total'] = vdev_cache_total
977
978 if vdev_cache_total > 0:
979 output['summary'] = fHits(vdev_cache_total)
980 output['hit_ratio'] = {
981 'per': fPerc(vdev_cache_hits, vdev_cache_total),
982 'num': fHits(vdev_cache_hits),
983 }
984 output['miss_ratio'] = {
985 'per': fPerc(vdev_cache_misses, vdev_cache_total),
986 'num': fHits(vdev_cache_misses),
987 }
988 output['delegations'] = {
989 'per': fPerc(vdev_cache_delegations, vdev_cache_total),
990 'num': fHits(vdev_cache_delegations),
991 }
992
993 return output
994
995
996 def _vdev_summary(Kstat):
997 arc = get_vdev_summary(Kstat)
998
999 if arc['vdev_cache_total'] > 0:
1000 sys.stdout.write("VDEV Cache Summary:\t\t\t\t%s\n" % arc['summary'])
1001 sys.stdout.write("\tHit Ratio:\t\t\t%s\t%s\n" % (
1002 arc['hit_ratio']['per'],
1003 arc['hit_ratio']['num'],
1004 ))
1005 sys.stdout.write("\tMiss Ratio:\t\t\t%s\t%s\n" % (
1006 arc['miss_ratio']['per'],
1007 arc['miss_ratio']['num'],
1008 ))
1009 sys.stdout.write("\tDelegations:\t\t\t%s\t%s\n" % (
1010 arc['delegations']['per'],
1011 arc['delegations']['num'],
1012 ))
1013
1014
1015 def _tunable_summary(Kstat):
1016 global show_tunable_descriptions
1017 global alternate_tunable_layout
1018
1019 names = listdir("/sys/module/zfs/parameters/")
1020
1021 values = {}
1022 for name in names:
1023 with open("/sys/module/zfs/parameters/" + name) as f: value = f.read()
1024 values[name] = value.strip()
1025
1026 descriptions = {}
1027
1028 if show_tunable_descriptions:
1029 try:
1030 command = ["/sbin/modinfo", "zfs", "-0"]
1031 p = Popen(command, stdin=PIPE, stdout=PIPE,
1032 stderr=PIPE, shell=False, close_fds=True)
1033 p.wait()
1034
1035 description_list = p.communicate()[0].strip().split('\0')
1036
1037 if p.returncode == 0:
1038 for tunable in description_list:
1039 if tunable[0:5] == 'parm:':
1040 tunable = tunable[5:].strip()
1041 name, description = tunable.split(':', 1)
1042 if not description:
1043 description = "Description unavailable"
1044 descriptions[name] = description
1045 else:
1046 sys.stderr.write("%s: '%s' exited with code %i\n" %
1047 (sys.argv[0], command[0], p.returncode))
1048 sys.stderr.write("Tunable descriptions will be disabled.\n")
1049 except OSError as e:
1050 sys.stderr.write("%s: Cannot run '%s': %s\n" %
1051 (sys.argv[0], command[0], e.strerror))
1052 sys.stderr.write("Tunable descriptions will be disabled.\n")
1053
1054 sys.stdout.write("ZFS Tunable:\n")
1055 for name in names:
1056 if not name:
1057 continue
1058
1059 format = "\t%-50s%s\n"
1060 if alternate_tunable_layout:
1061 format = "\t%s=%s\n"
1062
1063 if show_tunable_descriptions and descriptions.has_key(name):
1064 sys.stdout.write("\t# %s\n" % descriptions[name])
1065
1066 sys.stdout.write(format % (name, values[name]))
1067
1068
1069 unSub = [
1070 _arc_summary,
1071 _arc_efficiency,
1072 _l2arc_summary,
1073 _dmu_summary,
1074 _vdev_summary,
1075 _tunable_summary
1076 ]
1077
1078
1079 def zfs_header():
1080 daydate = time.strftime("%a %b %d %H:%M:%S %Y")
1081
1082 div1()
1083 sys.stdout.write("ZFS Subsystem Report\t\t\t\t%s" % daydate)
1084 div2()
1085
1086
1087 def usage():
1088 sys.stdout.write("Usage: arc_summary.py [-h] [-a] [-d] [-p PAGE]\n\n")
1089 sys.stdout.write("\t -h, --help : "
1090 "Print this help message and exit\n")
1091 sys.stdout.write("\t -a, --alternate : "
1092 "Show an alternate sysctl layout\n")
1093 sys.stdout.write("\t -d, --description : "
1094 "Show the sysctl descriptions\n")
1095 sys.stdout.write("\t -p PAGE, --page=PAGE : "
1096 "Select a single output page to display,\n")
1097 sys.stdout.write("\t "
1098 "should be an integer between 1 and " + str(len(unSub)) + "\n\n")
1099 sys.stdout.write("Examples:\n")
1100 sys.stdout.write("\tarc_summary.py -a\n")
1101 sys.stdout.write("\tarc_summary.py -p 4\n")
1102 sys.stdout.write("\tarc_summary.py -ad\n")
1103 sys.stdout.write("\tarc_summary.py --page=2\n")
1104
1105 def main():
1106 global show_tunable_descriptions
1107 global alternate_tunable_layout
1108
1109 opts, args = getopt.getopt(
1110 sys.argv[1:], "adp:h", ["alternate", "description", "page=", "help"]
1111 )
1112
1113 args = {}
1114 for opt, arg in opts:
1115 if opt in ('-a', '--alternate'):
1116 args['a'] = True
1117 if opt in ('-d', '--description'):
1118 args['d'] = True
1119 if opt in ('-p', '--page'):
1120 args['p'] = arg
1121 if opt in ('-h', '--help'):
1122 usage()
1123 sys.exit()
1124
1125 Kstat = get_Kstat()
1126
1127 alternate_tunable_layout = 'a' in args
1128 show_tunable_descriptions = 'd' in args
1129
1130 pages = []
1131
1132 if 'p' in args:
1133 try:
1134 pages.append(unSub[int(args['p']) - 1])
1135 except IndexError , e:
1136 sys.stderr.write('the argument to -p must be between 1 and ' +
1137 str(len(unSub)) + '\n')
1138 sys.exit()
1139 else:
1140 pages = unSub
1141
1142 zfs_header()
1143 for page in pages:
1144 page(Kstat)
1145 div2()
1146
1147 if __name__ == '__main__':
1148 main()