]> git.proxmox.com Git - mirror_zfs.git/blame - cmd/dbufstat/dbufstat.py
pyzfs: python3 support (unit tests)
[mirror_zfs.git] / cmd / dbufstat / dbufstat.py
CommitLineData
d738d34d
BB
1#!/usr/bin/python
2#
3# Print out statistics for all cached dmu buffers. This information
4# is available through the dbufs kstat and may be post-processed as
5# needed by the script.
6#
7# CDDL HEADER START
8#
9# The contents of this file are subject to the terms of the
10# Common Development and Distribution License, Version 1.0 only
11# (the "License"). You may not use this file except in compliance
12# with the License.
13#
14# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
15# or http://www.opensolaris.org/os/licensing.
16# See the License for the specific language governing permissions
17# and limitations under the License.
18#
19# When distributing Covered Code, include this CDDL HEADER in each
20# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
21# If applicable, add the following below this CDDL HEADER, with the
22# fields enclosed by brackets "[]" replaced with your own identifying
23# information: Portions Copyright [yyyy] [name of copyright owner]
24#
25# CDDL HEADER END
26#
27# Copyright (C) 2013 Lawrence Livermore National Security, LLC.
28# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
29#
30
31import sys
32import getopt
33import errno
5e021f56 34import re
d738d34d 35
23bc1f91 36bhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize"]
d738d34d 37bxhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize",
5e021f56 38 "meta", "state", "dbholds", "dbc", "list", "atype", "flags",
23bc1f91
MT
39 "count", "asize", "access", "mru", "gmru", "mfu", "gmfu", "l2",
40 "l2_dattr", "l2_asize", "l2_comp", "aholds", "dtype", "btype",
41 "data_bs", "meta_bs", "bsize", "lvls", "dholds", "blocks", "dsize"]
d738d34d
BB
42bincompat = ["cached", "direct", "indirect", "bonus", "spill"]
43
23bc1f91 44dhdr = ["pool", "objset", "object", "dtype", "cached"]
d738d34d 45dxhdr = ["pool", "objset", "object", "dtype", "btype", "data_bs", "meta_bs",
23bc1f91
MT
46 "bsize", "lvls", "dholds", "blocks", "dsize", "cached", "direct",
47 "indirect", "bonus", "spill"]
d738d34d 48dincompat = ["level", "blkid", "offset", "dbsize", "meta", "state", "dbholds",
5e021f56 49 "dbc", "list", "atype", "flags", "count", "asize", "access",
23bc1f91
MT
50 "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
51 "l2_comp", "aholds"]
d738d34d 52
23bc1f91 53thdr = ["pool", "objset", "dtype", "cached"]
d738d34d 54txhdr = ["pool", "objset", "dtype", "cached", "direct", "indirect",
23bc1f91 55 "bonus", "spill"]
d738d34d 56tincompat = ["object", "level", "blkid", "offset", "dbsize", "meta", "state",
5e021f56 57 "dbc", "dbholds", "list", "atype", "flags", "count", "asize",
23bc1f91
MT
58 "access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr",
59 "l2_asize", "l2_comp", "aholds", "btype", "data_bs", "meta_bs",
60 "bsize", "lvls", "dholds", "blocks", "dsize"]
d738d34d
BB
61
62cols = {
63 # hdr: [size, scale, description]
64 "pool": [15, -1, "pool name"],
65 "objset": [6, -1, "dataset identification number"],
66 "object": [10, -1, "object number"],
67 "level": [5, -1, "indirection level of buffer"],
68 "blkid": [8, -1, "block number of buffer"],
69 "offset": [12, 1024, "offset in object of buffer"],
70 "dbsize": [7, 1024, "size of buffer"],
71 "meta": [4, -1, "is this buffer metadata?"],
72 "state": [5, -1, "state of buffer (read, cached, etc)"],
73 "dbholds": [7, 1000, "number of holds on buffer"],
5e021f56 74 "dbc": [3, -1, "in dbuf cache"],
d738d34d
BB
75 "list": [4, -1, "which ARC list contains this buffer"],
76 "atype": [7, -1, "ARC header type (data or metadata)"],
5e021f56 77 "flags": [9, -1, "ARC read flags"],
d738d34d
BB
78 "count": [5, -1, "ARC data count"],
79 "asize": [7, 1024, "size of this ARC buffer"],
80 "access": [10, -1, "time this ARC buffer was last accessed"],
81 "mru": [5, 1000, "hits while on the ARC's MRU list"],
82 "gmru": [5, 1000, "hits while on the ARC's MRU ghost list"],
83 "mfu": [5, 1000, "hits while on the ARC's MFU list"],
84 "gmfu": [5, 1000, "hits while on the ARC's MFU ghost list"],
85 "l2": [5, 1000, "hits while on the L2ARC"],
86 "l2_dattr": [8, -1, "L2ARC disk address/offset"],
87 "l2_asize": [8, 1024, "L2ARC alloc'd size (depending on compression)"],
88 "l2_comp": [21, -1, "L2ARC compression algorithm for buffer"],
89 "aholds": [6, 1000, "number of holds on this ARC buffer"],
90 "dtype": [27, -1, "dnode type"],
91 "btype": [27, -1, "bonus buffer type"],
92 "data_bs": [7, 1024, "data block size"],
93 "meta_bs": [7, 1024, "metadata block size"],
94 "bsize": [6, 1024, "bonus buffer size"],
95 "lvls": [6, -1, "number of indirection levels"],
96 "dholds": [6, 1000, "number of holds on dnode"],
97 "blocks": [8, 1000, "number of allocated blocks"],
98 "dsize": [12, 1024, "size of dnode"],
99 "cached": [6, 1024, "bytes cached for all blocks"],
100 "direct": [6, 1024, "bytes cached for direct blocks"],
101 "indirect": [8, 1024, "bytes cached for indirect blocks"],
102 "bonus": [5, 1024, "bytes cached for bonus buffer"],
103 "spill": [5, 1024, "bytes cached for spill block"],
104}
105
23bc1f91 106hdr = None
d738d34d 107xhdr = None
23bc1f91 108sep = " " # Default separator is 2 spaces
5e021f56
GDN
109cmd = ("Usage: dbufstat.py [-bdhnrtvx] [-i file] [-f fields] [-o file] "
110 "[-s string] [-F filter]\n")
d738d34d
BB
111raw = 0
112
23bc1f91 113
d738d34d
BB
114def print_incompat_helper(incompat):
115 cnt = 0
116 for key in sorted(incompat):
117 if cnt is 0:
118 sys.stderr.write("\t")
119 elif cnt > 8:
120 sys.stderr.write(",\n\t")
121 cnt = 0
122 else:
123 sys.stderr.write(", ")
124
125 sys.stderr.write("%s" % key)
126 cnt += 1
127
128 sys.stderr.write("\n\n")
129
23bc1f91 130
d738d34d
BB
131def detailed_usage():
132 sys.stderr.write("%s\n" % cmd)
133
134 sys.stderr.write("Field definitions incompatible with '-b' option:\n")
135 print_incompat_helper(bincompat)
136
137 sys.stderr.write("Field definitions incompatible with '-d' option:\n")
138 print_incompat_helper(dincompat)
139
140 sys.stderr.write("Field definitions incompatible with '-t' option:\n")
141 print_incompat_helper(tincompat)
142
143 sys.stderr.write("Field definitions are as follows:\n")
144 for key in sorted(cols.keys()):
145 sys.stderr.write("%11s : %s\n" % (key, cols[key][2]))
146 sys.stderr.write("\n")
147
e169749f 148 sys.exit(0)
d738d34d 149
23bc1f91 150
d738d34d
BB
151def usage():
152 sys.stderr.write("%s\n" % cmd)
153 sys.stderr.write("\t -b : Print table of information for each dbuf\n")
154 sys.stderr.write("\t -d : Print table of information for each dnode\n")
155 sys.stderr.write("\t -h : Print this help message\n")
5e021f56 156 sys.stderr.write("\t -n : Exclude header from output\n")
d738d34d 157 sys.stderr.write("\t -r : Print raw values\n")
23bc1f91
MT
158 sys.stderr.write("\t -t : Print table of information for each dnode type"
159 "\n")
d738d34d 160 sys.stderr.write("\t -v : List all possible field headers and definitions"
23bc1f91 161 "\n")
d738d34d
BB
162 sys.stderr.write("\t -x : Print extended stats\n")
163 sys.stderr.write("\t -i : Redirect input from the specified file\n")
164 sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n")
165 sys.stderr.write("\t -o : Redirect output to the specified file\n")
166 sys.stderr.write("\t -s : Override default field separator with custom "
23bc1f91 167 "character or string\n")
5e021f56 168 sys.stderr.write("\t -F : Filter output by value or regex\n")
d738d34d
BB
169 sys.stderr.write("\nExamples:\n")
170 sys.stderr.write("\tdbufstat.py -d -o /tmp/d.log\n")
171 sys.stderr.write("\tdbufstat.py -t -s \",\" -o /tmp/t.log\n")
172 sys.stderr.write("\tdbufstat.py -v\n")
173 sys.stderr.write("\tdbufstat.py -d -f pool,object,objset,dsize,cached\n")
5e021f56 174 sys.stderr.write("\tdbufstat.py -bx -F dbc=1,objset=54,pool=testpool\n")
d738d34d
BB
175 sys.stderr.write("\n")
176
177 sys.exit(1)
178
23bc1f91 179
d738d34d
BB
180def prettynum(sz, scale, num=0):
181 global raw
182
183 suffix = [' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']
184 index = 0
185 save = 0
186
187 if raw or scale == -1:
188 return "%*s" % (sz, num)
189
190 # Rounding error, return 0
09d672d3 191 elif 0 < num < 1:
d738d34d
BB
192 num = 0
193
194 while num > scale and index < 5:
195 save = num
196 num = num / scale
197 index += 1
198
199 if index == 0:
200 return "%*d" % (sz, num)
201
202 if (save / scale) < 10:
203 return "%*.1f%s" % (sz - 1, num, suffix[index])
204 else:
205 return "%*d%s" % (sz - 1, num, suffix[index])
206
23bc1f91 207
d738d34d
BB
208def print_values(v):
209 global hdr
210 global sep
211
212 try:
213 for col in hdr:
214 sys.stdout.write("%s%s" % (
215 prettynum(cols[col][0], cols[col][1], v[col]), sep))
216 sys.stdout.write("\n")
217 except IOError as e:
218 if e.errno == errno.EPIPE:
219 sys.exit(1)
220
23bc1f91 221
d738d34d
BB
222def print_header():
223 global hdr
224 global sep
225
226 try:
227 for col in hdr:
228 sys.stdout.write("%*s%s" % (cols[col][0], col, sep))
229 sys.stdout.write("\n")
230 except IOError as e:
231 if e.errno == errno.EPIPE:
232 sys.exit(1)
233
23bc1f91 234
d738d34d 235def get_typestring(t):
db4c1ada 236 ot_strings = [
237 "DMU_OT_NONE",
23bc1f91
MT
238 # general:
239 "DMU_OT_OBJECT_DIRECTORY",
240 "DMU_OT_OBJECT_ARRAY",
241 "DMU_OT_PACKED_NVLIST",
242 "DMU_OT_PACKED_NVLIST_SIZE",
243 "DMU_OT_BPOBJ",
244 "DMU_OT_BPOBJ_HDR",
245 # spa:
246 "DMU_OT_SPACE_MAP_HEADER",
247 "DMU_OT_SPACE_MAP",
248 # zil:
249 "DMU_OT_INTENT_LOG",
250 # dmu:
251 "DMU_OT_DNODE",
252 "DMU_OT_OBJSET",
253 # dsl:
254 "DMU_OT_DSL_DIR",
255 "DMU_OT_DSL_DIR_CHILD_MAP",
256 "DMU_OT_DSL_DS_SNAP_MAP",
257 "DMU_OT_DSL_PROPS",
258 "DMU_OT_DSL_DATASET",
259 # zpl:
260 "DMU_OT_ZNODE",
261 "DMU_OT_OLDACL",
262 "DMU_OT_PLAIN_FILE_CONTENTS",
263 "DMU_OT_DIRECTORY_CONTENTS",
264 "DMU_OT_MASTER_NODE",
265 "DMU_OT_UNLINKED_SET",
266 # zvol:
267 "DMU_OT_ZVOL",
268 "DMU_OT_ZVOL_PROP",
269 # other; for testing only!
270 "DMU_OT_PLAIN_OTHER",
271 "DMU_OT_UINT64_OTHER",
272 "DMU_OT_ZAP_OTHER",
273 # new object types:
274 "DMU_OT_ERROR_LOG",
275 "DMU_OT_SPA_HISTORY",
276 "DMU_OT_SPA_HISTORY_OFFSETS",
277 "DMU_OT_POOL_PROPS",
278 "DMU_OT_DSL_PERMS",
279 "DMU_OT_ACL",
280 "DMU_OT_SYSACL",
281 "DMU_OT_FUID",
282 "DMU_OT_FUID_SIZE",
283 "DMU_OT_NEXT_CLONES",
284 "DMU_OT_SCAN_QUEUE",
285 "DMU_OT_USERGROUP_USED",
286 "DMU_OT_USERGROUP_QUOTA",
287 "DMU_OT_USERREFS",
288 "DMU_OT_DDT_ZAP",
289 "DMU_OT_DDT_STATS",
290 "DMU_OT_SA",
291 "DMU_OT_SA_MASTER_NODE",
292 "DMU_OT_SA_ATTR_REGISTRATION",
293 "DMU_OT_SA_ATTR_LAYOUTS",
294 "DMU_OT_SCAN_XLATE",
295 "DMU_OT_DEDUP",
296 "DMU_OT_DEADLIST",
297 "DMU_OT_DEADLIST_HDR",
298 "DMU_OT_DSL_CLONES",
299 "DMU_OT_BPOBJ_SUBOBJ"]
db4c1ada 300 otn_strings = {
301 0x80: "DMU_OTN_UINT8_DATA",
302 0xc0: "DMU_OTN_UINT8_METADATA",
303 0x81: "DMU_OTN_UINT16_DATA",
304 0xc1: "DMU_OTN_UINT16_METADATA",
305 0x82: "DMU_OTN_UINT32_DATA",
306 0xc2: "DMU_OTN_UINT32_METADATA",
307 0x83: "DMU_OTN_UINT64_DATA",
308 0xc3: "DMU_OTN_UINT64_METADATA",
309 0x84: "DMU_OTN_ZAP_DATA",
310 0xc4: "DMU_OTN_ZAP_METADATA",
311 0xa0: "DMU_OTN_UINT8_ENC_DATA",
312 0xe0: "DMU_OTN_UINT8_ENC_METADATA",
313 0xa1: "DMU_OTN_UINT16_ENC_DATA",
314 0xe1: "DMU_OTN_UINT16_ENC_METADATA",
315 0xa2: "DMU_OTN_UINT32_ENC_DATA",
316 0xe2: "DMU_OTN_UINT32_ENC_METADATA",
317 0xa3: "DMU_OTN_UINT64_ENC_DATA",
318 0xe3: "DMU_OTN_UINT64_ENC_METADATA",
319 0xa4: "DMU_OTN_ZAP_ENC_DATA",
320 0xe4: "DMU_OTN_ZAP_ENC_METADATA"}
d738d34d
BB
321
322 # If "-rr" option is used, don't convert to string representation
323 if raw > 1:
324 return "%i" % t
325
326 try:
db4c1ada 327 if t < len(ot_strings):
328 return ot_strings[t]
329 else:
330 return otn_strings[t]
331 except (IndexError, KeyError):
332 return "(UNKNOWN)"
d738d34d 333
23bc1f91 334
d738d34d
BB
335def get_compstring(c):
336 comp_strings = ["ZIO_COMPRESS_INHERIT", "ZIO_COMPRESS_ON",
337 "ZIO_COMPRESS_OFF", "ZIO_COMPRESS_LZJB",
338 "ZIO_COMPRESS_EMPTY", "ZIO_COMPRESS_GZIP_1",
339 "ZIO_COMPRESS_GZIP_2", "ZIO_COMPRESS_GZIP_3",
340 "ZIO_COMPRESS_GZIP_4", "ZIO_COMPRESS_GZIP_5",
341 "ZIO_COMPRESS_GZIP_6", "ZIO_COMPRESS_GZIP_7",
342 "ZIO_COMPRESS_GZIP_8", "ZIO_COMPRESS_GZIP_9",
343 "ZIO_COMPRESS_ZLE", "ZIO_COMPRESS_LZ4",
344 "ZIO_COMPRESS_FUNCTION"]
345
346 # If "-rr" option is used, don't convert to string representation
347 if raw > 1:
348 return "%i" % c
349
350 try:
23bc1f91 351 return comp_strings[c]
d738d34d
BB
352 except IndexError:
353 return "%i" % c
354
23bc1f91 355
d738d34d
BB
356def parse_line(line, labels):
357 global hdr
358
359 new = dict()
360 val = None
361 for col in hdr:
362 # These are "special" fields computed in the update_dict
363 # function, prevent KeyError exception on labels[col] for these.
364 if col not in ['bonus', 'cached', 'direct', 'indirect', 'spill']:
365 val = line[labels[col]]
366
367 if col in ['pool', 'flags']:
368 new[col] = str(val)
369 elif col in ['dtype', 'btype']:
370 new[col] = get_typestring(int(val))
371 elif col in ['l2_comp']:
372 new[col] = get_compstring(int(val))
373 else:
374 new[col] = int(val)
375
376 return new
377
23bc1f91 378
d738d34d 379def update_dict(d, k, line, labels):
23bc1f91 380 pool = line[labels['pool']]
d738d34d 381 objset = line[labels['objset']]
23bc1f91 382 key = line[labels[k]]
d738d34d
BB
383
384 dbsize = int(line[labels['dbsize']])
23bc1f91
MT
385 blkid = int(line[labels['blkid']])
386 level = int(line[labels['level']])
d738d34d
BB
387
388 if pool not in d:
389 d[pool] = dict()
390
391 if objset not in d[pool]:
392 d[pool][objset] = dict()
393
394 if key not in d[pool][objset]:
23bc1f91
MT
395 d[pool][objset][key] = parse_line(line, labels)
396 d[pool][objset][key]['bonus'] = 0
397 d[pool][objset][key]['cached'] = 0
398 d[pool][objset][key]['direct'] = 0
d738d34d 399 d[pool][objset][key]['indirect'] = 0
23bc1f91 400 d[pool][objset][key]['spill'] = 0
d738d34d
BB
401
402 d[pool][objset][key]['cached'] += dbsize
403
404 if blkid == -1:
405 d[pool][objset][key]['bonus'] += dbsize
406 elif blkid == -2:
407 d[pool][objset][key]['spill'] += dbsize
408 else:
409 if level == 0:
410 d[pool][objset][key]['direct'] += dbsize
411 else:
412 d[pool][objset][key]['indirect'] += dbsize
413
414 return d
415
09d672d3 416
5e021f56
GDN
417def skip_line(vals, filters):
418 '''
419 Determines if a line should be skipped during printing
420 based on a set of filters
421 '''
422 if len(filters) == 0:
423 return False
424
425 for key in vals:
426 if key in filters:
427 val = prettynum(cols[key][0], cols[key][1], vals[key]).strip()
428 # we want a full match here
429 if re.match("(?:" + filters[key] + r")\Z", val) is None:
430 return True
431
432 return False
433
434
435def print_dict(d, filters, noheader):
436 if not noheader:
437 print_header()
7cf2ffa0
HM
438 for pool in list(d.keys()):
439 for objset in list(d[pool].keys()):
440 for v in list(d[pool][objset].values()):
5e021f56
GDN
441 if not skip_line(v, filters):
442 print_values(v)
d738d34d 443
09d672d3 444
d738d34d
BB
445def dnodes_build_dict(filehandle):
446 labels = dict()
447 dnodes = dict()
448
449 # First 3 lines are header information, skip the first two
09d672d3 450 for i in range(2):
d738d34d
BB
451 next(filehandle)
452
453 # The third line contains the labels and index locations
454 for i, v in enumerate(next(filehandle).split()):
455 labels[v] = i
456
457 # The rest of the file is buffer information
458 for line in filehandle:
459 update_dict(dnodes, 'object', line.split(), labels)
460
461 return dnodes
462
09d672d3 463
d738d34d
BB
464def types_build_dict(filehandle):
465 labels = dict()
466 types = dict()
467
468 # First 3 lines are header information, skip the first two
09d672d3 469 for i in range(2):
d738d34d
BB
470 next(filehandle)
471
472 # The third line contains the labels and index locations
473 for i, v in enumerate(next(filehandle).split()):
474 labels[v] = i
475
476 # The rest of the file is buffer information
477 for line in filehandle:
478 update_dict(types, 'dtype', line.split(), labels)
479
480 return types
481
09d672d3 482
5e021f56 483def buffers_print_all(filehandle, filters, noheader):
d738d34d
BB
484 labels = dict()
485
486 # First 3 lines are header information, skip the first two
09d672d3 487 for i in range(2):
d738d34d
BB
488 next(filehandle)
489
490 # The third line contains the labels and index locations
491 for i, v in enumerate(next(filehandle).split()):
492 labels[v] = i
493
5e021f56
GDN
494 if not noheader:
495 print_header()
d738d34d
BB
496
497 # The rest of the file is buffer information
498 for line in filehandle:
5e021f56
GDN
499 vals = parse_line(line.split(), labels)
500 if not skip_line(vals, filters):
501 print_values(vals)
d738d34d 502
23bc1f91 503
d738d34d
BB
504def main():
505 global hdr
506 global sep
507 global raw
508
509 desired_cols = None
510 bflag = False
511 dflag = False
512 hflag = False
513 ifile = None
514 ofile = None
515 tflag = False
516 vflag = False
517 xflag = False
5e021f56
GDN
518 nflag = False
519 filters = dict()
d738d34d
BB
520
521 try:
522 opts, args = getopt.getopt(
523 sys.argv[1:],
5e021f56 524 "bdf:hi:o:rs:tvxF:n",
d738d34d
BB
525 [
526 "buffers",
527 "dnodes",
528 "columns",
529 "help",
530 "infile",
531 "outfile",
d699aaef 532 "separator",
d738d34d
BB
533 "types",
534 "verbose",
5e021f56
GDN
535 "extended",
536 "filter"
d738d34d
BB
537 ]
538 )
539 except getopt.error:
540 usage()
09d672d3 541 opts = None
d738d34d
BB
542
543 for opt, arg in opts:
544 if opt in ('-b', '--buffers'):
545 bflag = True
546 if opt in ('-d', '--dnodes'):
547 dflag = True
548 if opt in ('-f', '--columns'):
549 desired_cols = arg
550 if opt in ('-h', '--help'):
551 hflag = True
552 if opt in ('-i', '--infile'):
553 ifile = arg
554 if opt in ('-o', '--outfile'):
555 ofile = arg
556 if opt in ('-r', '--raw'):
557 raw += 1
d699aaef 558 if opt in ('-s', '--separator'):
d738d34d
BB
559 sep = arg
560 if opt in ('-t', '--types'):
561 tflag = True
562 if opt in ('-v', '--verbose'):
563 vflag = True
564 if opt in ('-x', '--extended'):
565 xflag = True
5e021f56
GDN
566 if opt in ('-n', '--noheader'):
567 nflag = True
568 if opt in ('-F', '--filter'):
569 fils = [x.strip() for x in arg.split(",")]
570
571 for fil in fils:
572 f = [x.strip() for x in fil.split("=")]
573
574 if len(f) != 2:
575 sys.stderr.write("Invalid filter '%s'.\n" % fil)
576 sys.exit(1)
577
578 if f[0] not in cols:
579 sys.stderr.write("Invalid field '%s' in filter.\n" % f[0])
580 sys.exit(1)
581
582 if f[0] in filters:
583 sys.stderr.write("Field '%s' specified multiple times in "
584 "filter.\n" % f[0])
585 sys.exit(1)
586
587 try:
588 re.compile("(?:" + f[1] + r")\Z")
589 except re.error:
590 sys.stderr.write("Invalid regex for field '%s' in "
591 "filter.\n" % f[0])
592 sys.exit(1)
593
594 filters[f[0]] = f[1]
d738d34d
BB
595
596 if hflag or (xflag and desired_cols):
597 usage()
598
599 if vflag:
600 detailed_usage()
601
602 # Ensure at most only one of b, d, or t flags are set
603 if (bflag and dflag) or (bflag and tflag) or (dflag and tflag):
604 usage()
605
606 if bflag:
23bc1f91 607 hdr = bxhdr if xflag else bhdr
d738d34d 608 elif tflag:
23bc1f91
MT
609 hdr = txhdr if xflag else thdr
610 else: # Even if dflag is False, it's the default if none set
d738d34d
BB
611 dflag = True
612 hdr = dxhdr if xflag else dhdr
613
614 if desired_cols:
615 hdr = desired_cols.split(",")
616
617 invalid = []
618 incompat = []
619 for ele in hdr:
620 if ele not in cols:
621 invalid.append(ele)
622 elif ((bflag and bincompat and ele in bincompat) or
623 (dflag and dincompat and ele in dincompat) or
624 (tflag and tincompat and ele in tincompat)):
625 incompat.append(ele)
626
627 if len(invalid) > 0:
628 sys.stderr.write("Invalid column definition! -- %s\n" % invalid)
629 usage()
630
631 if len(incompat) > 0:
23bc1f91
MT
632 sys.stderr.write("Incompatible field specified! -- %s\n" %
633 incompat)
d738d34d
BB
634 usage()
635
636 if ofile:
637 try:
638 tmp = open(ofile, "w")
639 sys.stdout = tmp
640
23bc1f91
MT
641 except IOError:
642 sys.stderr.write("Cannot open %s for writing\n" % ofile)
d738d34d
BB
643 sys.exit(1)
644
645 if not ifile:
646 ifile = '/proc/spl/kstat/zfs/dbufs'
647
648 if ifile is not "-":
649 try:
650 tmp = open(ifile, "r")
651 sys.stdin = tmp
09d672d3 652 except IOError:
d738d34d
BB
653 sys.stderr.write("Cannot open %s for reading\n" % ifile)
654 sys.exit(1)
655
656 if bflag:
5e021f56 657 buffers_print_all(sys.stdin, filters, nflag)
d738d34d
BB
658
659 if dflag:
5e021f56 660 print_dict(dnodes_build_dict(sys.stdin), filters, nflag)
d738d34d
BB
661
662 if tflag:
5e021f56 663 print_dict(types_build_dict(sys.stdin), filters, nflag)
d738d34d 664
c3d04381 665
d738d34d
BB
666if __name__ == '__main__':
667 main()