1716fd348SMartin Matuska#!/usr/bin/env @PYTHON_SHEBANG@ 2*61145dc2SMartin Matuska# SPDX-License-Identifier: CDDL-1.0 3716fd348SMartin Matuska# 4716fd348SMartin Matuska# Print out statistics for all cached dmu buffers. This information 5716fd348SMartin Matuska# is available through the dbufs kstat and may be post-processed as 6716fd348SMartin Matuska# needed by the script. 7716fd348SMartin Matuska# 8716fd348SMartin Matuska# CDDL HEADER START 9716fd348SMartin Matuska# 10716fd348SMartin Matuska# The contents of this file are subject to the terms of the 11716fd348SMartin Matuska# Common Development and Distribution License, Version 1.0 only 12716fd348SMartin Matuska# (the "License"). You may not use this file except in compliance 13716fd348SMartin Matuska# with the License. 14716fd348SMartin Matuska# 15716fd348SMartin Matuska# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 16271171e0SMartin Matuska# or https://opensource.org/licenses/CDDL-1.0. 17716fd348SMartin Matuska# See the License for the specific language governing permissions 18716fd348SMartin Matuska# and limitations under the License. 19716fd348SMartin Matuska# 20716fd348SMartin Matuska# When distributing Covered Code, include this CDDL HEADER in each 21716fd348SMartin Matuska# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 22716fd348SMartin Matuska# If applicable, add the following below this CDDL HEADER, with the 23716fd348SMartin Matuska# fields enclosed by brackets "[]" replaced with your own identifying 24716fd348SMartin Matuska# information: Portions Copyright [yyyy] [name of copyright owner] 25716fd348SMartin Matuska# 26716fd348SMartin Matuska# CDDL HEADER END 27716fd348SMartin Matuska# 28716fd348SMartin Matuska# Copyright (C) 2013 Lawrence Livermore National Security, LLC. 29716fd348SMartin Matuska# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 30716fd348SMartin Matuska# 31716fd348SMartin Matuska# This script must remain compatible with and Python 3.6+. 32716fd348SMartin Matuska# 33716fd348SMartin Matuska 34716fd348SMartin Matuskaimport sys 35716fd348SMartin Matuskaimport getopt 36716fd348SMartin Matuskaimport errno 37716fd348SMartin Matuskaimport re 38716fd348SMartin Matuska 39716fd348SMartin Matuskabhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize"] 40716fd348SMartin Matuskabxhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize", 41a2b560ccSMartin Matuska "usize", "meta", "state", "dbholds", "dbc", "list", "atype", "flags", 42716fd348SMartin Matuska "count", "asize", "access", "mru", "gmru", "mfu", "gmfu", "l2", 43716fd348SMartin Matuska "l2_dattr", "l2_asize", "l2_comp", "aholds", "dtype", "btype", 44716fd348SMartin Matuska "data_bs", "meta_bs", "bsize", "lvls", "dholds", "blocks", "dsize"] 45716fd348SMartin Matuskabincompat = ["cached", "direct", "indirect", "bonus", "spill"] 46716fd348SMartin Matuska 47716fd348SMartin Matuskadhdr = ["pool", "objset", "object", "dtype", "cached"] 48716fd348SMartin Matuskadxhdr = ["pool", "objset", "object", "dtype", "btype", "data_bs", "meta_bs", 49716fd348SMartin Matuska "bsize", "lvls", "dholds", "blocks", "dsize", "cached", "direct", 50716fd348SMartin Matuska "indirect", "bonus", "spill"] 51a2b560ccSMartin Matuskadincompat = ["level", "blkid", "offset", "dbsize", "usize", "meta", "state", 52a2b560ccSMartin Matuska "dbholds", "dbc", "list", "atype", "flags", "count", "asize", 53a2b560ccSMartin Matuska "access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", 54a2b560ccSMartin Matuska "l2_asize", "l2_comp", "aholds"] 55716fd348SMartin Matuska 56716fd348SMartin Matuskathdr = ["pool", "objset", "dtype", "cached"] 57716fd348SMartin Matuskatxhdr = ["pool", "objset", "dtype", "cached", "direct", "indirect", 58716fd348SMartin Matuska "bonus", "spill"] 59a2b560ccSMartin Matuskatincompat = ["object", "level", "blkid", "offset", "dbsize", "usize", "meta", 60a2b560ccSMartin Matuska "state", "dbc", "dbholds", "list", "atype", "flags", "count", 61a2b560ccSMartin Matuska "asize", "access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", 62716fd348SMartin Matuska "l2_asize", "l2_comp", "aholds", "btype", "data_bs", "meta_bs", 63716fd348SMartin Matuska "bsize", "lvls", "dholds", "blocks", "dsize"] 64716fd348SMartin Matuska 65716fd348SMartin Matuskacols = { 66716fd348SMartin Matuska # hdr: [size, scale, description] 67716fd348SMartin Matuska "pool": [15, -1, "pool name"], 68716fd348SMartin Matuska "objset": [6, -1, "dataset identification number"], 69716fd348SMartin Matuska "object": [10, -1, "object number"], 70716fd348SMartin Matuska "level": [5, -1, "indirection level of buffer"], 71716fd348SMartin Matuska "blkid": [8, -1, "block number of buffer"], 72716fd348SMartin Matuska "offset": [12, 1024, "offset in object of buffer"], 73716fd348SMartin Matuska "dbsize": [7, 1024, "size of buffer"], 74a2b560ccSMartin Matuska "usize": [7, 1024, "size of attached user data"], 75716fd348SMartin Matuska "meta": [4, -1, "is this buffer metadata?"], 76716fd348SMartin Matuska "state": [5, -1, "state of buffer (read, cached, etc)"], 77716fd348SMartin Matuska "dbholds": [7, 1000, "number of holds on buffer"], 78716fd348SMartin Matuska "dbc": [3, -1, "in dbuf cache"], 79716fd348SMartin Matuska "list": [4, -1, "which ARC list contains this buffer"], 80716fd348SMartin Matuska "atype": [7, -1, "ARC header type (data or metadata)"], 81716fd348SMartin Matuska "flags": [9, -1, "ARC read flags"], 82716fd348SMartin Matuska "count": [5, -1, "ARC data count"], 83716fd348SMartin Matuska "asize": [7, 1024, "size of this ARC buffer"], 84716fd348SMartin Matuska "access": [10, -1, "time this ARC buffer was last accessed"], 85716fd348SMartin Matuska "mru": [5, 1000, "hits while on the ARC's MRU list"], 86716fd348SMartin Matuska "gmru": [5, 1000, "hits while on the ARC's MRU ghost list"], 87716fd348SMartin Matuska "mfu": [5, 1000, "hits while on the ARC's MFU list"], 88716fd348SMartin Matuska "gmfu": [5, 1000, "hits while on the ARC's MFU ghost list"], 89716fd348SMartin Matuska "l2": [5, 1000, "hits while on the L2ARC"], 90716fd348SMartin Matuska "l2_dattr": [8, -1, "L2ARC disk address/offset"], 91716fd348SMartin Matuska "l2_asize": [8, 1024, "L2ARC alloc'd size (depending on compression)"], 92716fd348SMartin Matuska "l2_comp": [21, -1, "L2ARC compression algorithm for buffer"], 93716fd348SMartin Matuska "aholds": [6, 1000, "number of holds on this ARC buffer"], 94716fd348SMartin Matuska "dtype": [27, -1, "dnode type"], 95716fd348SMartin Matuska "btype": [27, -1, "bonus buffer type"], 96716fd348SMartin Matuska "data_bs": [7, 1024, "data block size"], 97716fd348SMartin Matuska "meta_bs": [7, 1024, "metadata block size"], 98716fd348SMartin Matuska "bsize": [6, 1024, "bonus buffer size"], 99716fd348SMartin Matuska "lvls": [6, -1, "number of indirection levels"], 100716fd348SMartin Matuska "dholds": [6, 1000, "number of holds on dnode"], 101716fd348SMartin Matuska "blocks": [8, 1000, "number of allocated blocks"], 102716fd348SMartin Matuska "dsize": [12, 1024, "size of dnode"], 103716fd348SMartin Matuska "cached": [6, 1024, "bytes cached for all blocks"], 104716fd348SMartin Matuska "direct": [6, 1024, "bytes cached for direct blocks"], 105716fd348SMartin Matuska "indirect": [8, 1024, "bytes cached for indirect blocks"], 106716fd348SMartin Matuska "bonus": [5, 1024, "bytes cached for bonus buffer"], 107716fd348SMartin Matuska "spill": [5, 1024, "bytes cached for spill block"], 108716fd348SMartin Matuska} 109716fd348SMartin Matuska 110716fd348SMartin Matuskahdr = None 111716fd348SMartin Matuskaxhdr = None 112716fd348SMartin Matuskasep = " " # Default separator is 2 spaces 113716fd348SMartin Matuskacmd = ("Usage: dbufstat [-bdhnrtvx] [-i file] [-f fields] [-o file] " 114716fd348SMartin Matuska "[-s string] [-F filter]\n") 115716fd348SMartin Matuskaraw = 0 116716fd348SMartin Matuska 117716fd348SMartin Matuska 118716fd348SMartin Matuskaif sys.platform.startswith("freebsd"): 119716fd348SMartin Matuska import io 120716fd348SMartin Matuska # Requires py-sysctl on FreeBSD 121716fd348SMartin Matuska import sysctl 122716fd348SMartin Matuska 123716fd348SMartin Matuska def default_ifile(): 124716fd348SMartin Matuska dbufs = sysctl.filter("kstat.zfs.misc.dbufs")[0].value 125716fd348SMartin Matuska sys.stdin = io.StringIO(dbufs) 126716fd348SMartin Matuska return "-" 127716fd348SMartin Matuska 128716fd348SMartin Matuskaelif sys.platform.startswith("linux"): 129716fd348SMartin Matuska def default_ifile(): 130716fd348SMartin Matuska return "/proc/spl/kstat/zfs/dbufs" 131716fd348SMartin Matuska 132716fd348SMartin Matuska 133716fd348SMartin Matuskadef print_incompat_helper(incompat): 134716fd348SMartin Matuska cnt = 0 135716fd348SMartin Matuska for key in sorted(incompat): 136716fd348SMartin Matuska if cnt == 0: 137716fd348SMartin Matuska sys.stderr.write("\t") 138716fd348SMartin Matuska elif cnt > 8: 139716fd348SMartin Matuska sys.stderr.write(",\n\t") 140716fd348SMartin Matuska cnt = 0 141716fd348SMartin Matuska else: 142716fd348SMartin Matuska sys.stderr.write(", ") 143716fd348SMartin Matuska 144716fd348SMartin Matuska sys.stderr.write("%s" % key) 145716fd348SMartin Matuska cnt += 1 146716fd348SMartin Matuska 147716fd348SMartin Matuska sys.stderr.write("\n\n") 148716fd348SMartin Matuska 149716fd348SMartin Matuska 150716fd348SMartin Matuskadef detailed_usage(): 151716fd348SMartin Matuska sys.stderr.write("%s\n" % cmd) 152716fd348SMartin Matuska 153716fd348SMartin Matuska sys.stderr.write("Field definitions incompatible with '-b' option:\n") 154716fd348SMartin Matuska print_incompat_helper(bincompat) 155716fd348SMartin Matuska 156716fd348SMartin Matuska sys.stderr.write("Field definitions incompatible with '-d' option:\n") 157716fd348SMartin Matuska print_incompat_helper(dincompat) 158716fd348SMartin Matuska 159716fd348SMartin Matuska sys.stderr.write("Field definitions incompatible with '-t' option:\n") 160716fd348SMartin Matuska print_incompat_helper(tincompat) 161716fd348SMartin Matuska 162716fd348SMartin Matuska sys.stderr.write("Field definitions are as follows:\n") 163716fd348SMartin Matuska for key in sorted(cols.keys()): 164716fd348SMartin Matuska sys.stderr.write("%11s : %s\n" % (key, cols[key][2])) 165716fd348SMartin Matuska sys.stderr.write("\n") 166716fd348SMartin Matuska 167716fd348SMartin Matuska sys.exit(0) 168716fd348SMartin Matuska 169716fd348SMartin Matuska 170716fd348SMartin Matuskadef usage(): 171716fd348SMartin Matuska sys.stderr.write("%s\n" % cmd) 172716fd348SMartin Matuska sys.stderr.write("\t -b : Print table of information for each dbuf\n") 173716fd348SMartin Matuska sys.stderr.write("\t -d : Print table of information for each dnode\n") 174716fd348SMartin Matuska sys.stderr.write("\t -h : Print this help message\n") 175716fd348SMartin Matuska sys.stderr.write("\t -n : Exclude header from output\n") 176716fd348SMartin Matuska sys.stderr.write("\t -r : Print raw values\n") 177716fd348SMartin Matuska sys.stderr.write("\t -t : Print table of information for each dnode type" 178716fd348SMartin Matuska "\n") 179716fd348SMartin Matuska sys.stderr.write("\t -v : List all possible field headers and definitions" 180716fd348SMartin Matuska "\n") 181716fd348SMartin Matuska sys.stderr.write("\t -x : Print extended stats\n") 182716fd348SMartin Matuska sys.stderr.write("\t -i : Redirect input from the specified file\n") 183716fd348SMartin Matuska sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n") 184716fd348SMartin Matuska sys.stderr.write("\t -o : Redirect output to the specified file\n") 185716fd348SMartin Matuska sys.stderr.write("\t -s : Override default field separator with custom " 186716fd348SMartin Matuska "character or string\n") 187716fd348SMartin Matuska sys.stderr.write("\t -F : Filter output by value or regex\n") 188716fd348SMartin Matuska sys.stderr.write("\nExamples:\n") 189716fd348SMartin Matuska sys.stderr.write("\tdbufstat -d -o /tmp/d.log\n") 190716fd348SMartin Matuska sys.stderr.write("\tdbufstat -t -s \",\" -o /tmp/t.log\n") 191716fd348SMartin Matuska sys.stderr.write("\tdbufstat -v\n") 192716fd348SMartin Matuska sys.stderr.write("\tdbufstat -d -f pool,object,objset,dsize,cached\n") 193716fd348SMartin Matuska sys.stderr.write("\tdbufstat -bx -F dbc=1,objset=54,pool=testpool\n") 194716fd348SMartin Matuska sys.stderr.write("\n") 195716fd348SMartin Matuska 196716fd348SMartin Matuska sys.exit(1) 197716fd348SMartin Matuska 198716fd348SMartin Matuska 199716fd348SMartin Matuskadef prettynum(sz, scale, num=0): 200716fd348SMartin Matuska global raw 201716fd348SMartin Matuska 202716fd348SMartin Matuska suffix = [' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'] 203716fd348SMartin Matuska index = 0 204716fd348SMartin Matuska save = 0 205716fd348SMartin Matuska 206716fd348SMartin Matuska if raw or scale == -1: 207716fd348SMartin Matuska return "%*s" % (sz, num) 208716fd348SMartin Matuska 209716fd348SMartin Matuska # Rounding error, return 0 210716fd348SMartin Matuska elif 0 < num < 1: 211716fd348SMartin Matuska num = 0 212716fd348SMartin Matuska 213716fd348SMartin Matuska while num > scale and index < 5: 214716fd348SMartin Matuska save = num 215716fd348SMartin Matuska num = num / scale 216716fd348SMartin Matuska index += 1 217716fd348SMartin Matuska 218716fd348SMartin Matuska if index == 0: 219716fd348SMartin Matuska return "%*d" % (sz, num) 220716fd348SMartin Matuska 221716fd348SMartin Matuska if (save / scale) < 10: 222716fd348SMartin Matuska return "%*.1f%s" % (sz - 1, num, suffix[index]) 223716fd348SMartin Matuska else: 224716fd348SMartin Matuska return "%*d%s" % (sz - 1, num, suffix[index]) 225716fd348SMartin Matuska 226716fd348SMartin Matuska 227716fd348SMartin Matuskadef print_values(v): 228716fd348SMartin Matuska global hdr 229716fd348SMartin Matuska global sep 230716fd348SMartin Matuska 231716fd348SMartin Matuska try: 232716fd348SMartin Matuska for col in hdr: 233716fd348SMartin Matuska sys.stdout.write("%s%s" % ( 234716fd348SMartin Matuska prettynum(cols[col][0], cols[col][1], v[col]), sep)) 235716fd348SMartin Matuska sys.stdout.write("\n") 236716fd348SMartin Matuska except IOError as e: 237716fd348SMartin Matuska if e.errno == errno.EPIPE: 238716fd348SMartin Matuska sys.exit(1) 239716fd348SMartin Matuska 240716fd348SMartin Matuska 241716fd348SMartin Matuskadef print_header(): 242716fd348SMartin Matuska global hdr 243716fd348SMartin Matuska global sep 244716fd348SMartin Matuska 245716fd348SMartin Matuska try: 246716fd348SMartin Matuska for col in hdr: 247716fd348SMartin Matuska sys.stdout.write("%*s%s" % (cols[col][0], col, sep)) 248716fd348SMartin Matuska sys.stdout.write("\n") 249716fd348SMartin Matuska except IOError as e: 250716fd348SMartin Matuska if e.errno == errno.EPIPE: 251716fd348SMartin Matuska sys.exit(1) 252716fd348SMartin Matuska 253716fd348SMartin Matuska 254716fd348SMartin Matuskadef get_typestring(t): 255716fd348SMartin Matuska ot_strings = [ 256716fd348SMartin Matuska "DMU_OT_NONE", 257716fd348SMartin Matuska # general: 258716fd348SMartin Matuska "DMU_OT_OBJECT_DIRECTORY", 259716fd348SMartin Matuska "DMU_OT_OBJECT_ARRAY", 260716fd348SMartin Matuska "DMU_OT_PACKED_NVLIST", 261716fd348SMartin Matuska "DMU_OT_PACKED_NVLIST_SIZE", 262716fd348SMartin Matuska "DMU_OT_BPOBJ", 263716fd348SMartin Matuska "DMU_OT_BPOBJ_HDR", 264716fd348SMartin Matuska # spa: 265716fd348SMartin Matuska "DMU_OT_SPACE_MAP_HEADER", 266716fd348SMartin Matuska "DMU_OT_SPACE_MAP", 267716fd348SMartin Matuska # zil: 268716fd348SMartin Matuska "DMU_OT_INTENT_LOG", 269716fd348SMartin Matuska # dmu: 270716fd348SMartin Matuska "DMU_OT_DNODE", 271716fd348SMartin Matuska "DMU_OT_OBJSET", 272716fd348SMartin Matuska # dsl: 273716fd348SMartin Matuska "DMU_OT_DSL_DIR", 274716fd348SMartin Matuska "DMU_OT_DSL_DIR_CHILD_MAP", 275716fd348SMartin Matuska "DMU_OT_DSL_DS_SNAP_MAP", 276716fd348SMartin Matuska "DMU_OT_DSL_PROPS", 277716fd348SMartin Matuska "DMU_OT_DSL_DATASET", 278716fd348SMartin Matuska # zpl: 279716fd348SMartin Matuska "DMU_OT_ZNODE", 280716fd348SMartin Matuska "DMU_OT_OLDACL", 281716fd348SMartin Matuska "DMU_OT_PLAIN_FILE_CONTENTS", 282716fd348SMartin Matuska "DMU_OT_DIRECTORY_CONTENTS", 283716fd348SMartin Matuska "DMU_OT_MASTER_NODE", 284716fd348SMartin Matuska "DMU_OT_UNLINKED_SET", 285716fd348SMartin Matuska # zvol: 286716fd348SMartin Matuska "DMU_OT_ZVOL", 287716fd348SMartin Matuska "DMU_OT_ZVOL_PROP", 288716fd348SMartin Matuska # other; for testing only! 289716fd348SMartin Matuska "DMU_OT_PLAIN_OTHER", 290716fd348SMartin Matuska "DMU_OT_UINT64_OTHER", 291716fd348SMartin Matuska "DMU_OT_ZAP_OTHER", 292716fd348SMartin Matuska # new object types: 293716fd348SMartin Matuska "DMU_OT_ERROR_LOG", 294716fd348SMartin Matuska "DMU_OT_SPA_HISTORY", 295716fd348SMartin Matuska "DMU_OT_SPA_HISTORY_OFFSETS", 296716fd348SMartin Matuska "DMU_OT_POOL_PROPS", 297716fd348SMartin Matuska "DMU_OT_DSL_PERMS", 298716fd348SMartin Matuska "DMU_OT_ACL", 299716fd348SMartin Matuska "DMU_OT_SYSACL", 300716fd348SMartin Matuska "DMU_OT_FUID", 301716fd348SMartin Matuska "DMU_OT_FUID_SIZE", 302716fd348SMartin Matuska "DMU_OT_NEXT_CLONES", 303716fd348SMartin Matuska "DMU_OT_SCAN_QUEUE", 304716fd348SMartin Matuska "DMU_OT_USERGROUP_USED", 305716fd348SMartin Matuska "DMU_OT_USERGROUP_QUOTA", 306716fd348SMartin Matuska "DMU_OT_USERREFS", 307716fd348SMartin Matuska "DMU_OT_DDT_ZAP", 308716fd348SMartin Matuska "DMU_OT_DDT_STATS", 309716fd348SMartin Matuska "DMU_OT_SA", 310716fd348SMartin Matuska "DMU_OT_SA_MASTER_NODE", 311716fd348SMartin Matuska "DMU_OT_SA_ATTR_REGISTRATION", 312716fd348SMartin Matuska "DMU_OT_SA_ATTR_LAYOUTS", 313716fd348SMartin Matuska "DMU_OT_SCAN_XLATE", 314716fd348SMartin Matuska "DMU_OT_DEDUP", 315716fd348SMartin Matuska "DMU_OT_DEADLIST", 316716fd348SMartin Matuska "DMU_OT_DEADLIST_HDR", 317716fd348SMartin Matuska "DMU_OT_DSL_CLONES", 318716fd348SMartin Matuska "DMU_OT_BPOBJ_SUBOBJ"] 319716fd348SMartin Matuska otn_strings = { 320716fd348SMartin Matuska 0x80: "DMU_OTN_UINT8_DATA", 321716fd348SMartin Matuska 0xc0: "DMU_OTN_UINT8_METADATA", 322716fd348SMartin Matuska 0x81: "DMU_OTN_UINT16_DATA", 323716fd348SMartin Matuska 0xc1: "DMU_OTN_UINT16_METADATA", 324716fd348SMartin Matuska 0x82: "DMU_OTN_UINT32_DATA", 325716fd348SMartin Matuska 0xc2: "DMU_OTN_UINT32_METADATA", 326716fd348SMartin Matuska 0x83: "DMU_OTN_UINT64_DATA", 327716fd348SMartin Matuska 0xc3: "DMU_OTN_UINT64_METADATA", 328716fd348SMartin Matuska 0x84: "DMU_OTN_ZAP_DATA", 329716fd348SMartin Matuska 0xc4: "DMU_OTN_ZAP_METADATA", 330716fd348SMartin Matuska 0xa0: "DMU_OTN_UINT8_ENC_DATA", 331716fd348SMartin Matuska 0xe0: "DMU_OTN_UINT8_ENC_METADATA", 332716fd348SMartin Matuska 0xa1: "DMU_OTN_UINT16_ENC_DATA", 333716fd348SMartin Matuska 0xe1: "DMU_OTN_UINT16_ENC_METADATA", 334716fd348SMartin Matuska 0xa2: "DMU_OTN_UINT32_ENC_DATA", 335716fd348SMartin Matuska 0xe2: "DMU_OTN_UINT32_ENC_METADATA", 336716fd348SMartin Matuska 0xa3: "DMU_OTN_UINT64_ENC_DATA", 337716fd348SMartin Matuska 0xe3: "DMU_OTN_UINT64_ENC_METADATA", 338716fd348SMartin Matuska 0xa4: "DMU_OTN_ZAP_ENC_DATA", 339716fd348SMartin Matuska 0xe4: "DMU_OTN_ZAP_ENC_METADATA"} 340716fd348SMartin Matuska 341716fd348SMartin Matuska # If "-rr" option is used, don't convert to string representation 342716fd348SMartin Matuska if raw > 1: 343716fd348SMartin Matuska return "%i" % t 344716fd348SMartin Matuska 345716fd348SMartin Matuska try: 346716fd348SMartin Matuska if t < len(ot_strings): 347716fd348SMartin Matuska return ot_strings[t] 348716fd348SMartin Matuska else: 349716fd348SMartin Matuska return otn_strings[t] 350716fd348SMartin Matuska except (IndexError, KeyError): 351716fd348SMartin Matuska return "(UNKNOWN)" 352716fd348SMartin Matuska 353716fd348SMartin Matuska 354716fd348SMartin Matuskadef get_compstring(c): 355716fd348SMartin Matuska comp_strings = ["ZIO_COMPRESS_INHERIT", "ZIO_COMPRESS_ON", 356716fd348SMartin Matuska "ZIO_COMPRESS_OFF", "ZIO_COMPRESS_LZJB", 357716fd348SMartin Matuska "ZIO_COMPRESS_EMPTY", "ZIO_COMPRESS_GZIP_1", 358716fd348SMartin Matuska "ZIO_COMPRESS_GZIP_2", "ZIO_COMPRESS_GZIP_3", 359716fd348SMartin Matuska "ZIO_COMPRESS_GZIP_4", "ZIO_COMPRESS_GZIP_5", 360716fd348SMartin Matuska "ZIO_COMPRESS_GZIP_6", "ZIO_COMPRESS_GZIP_7", 361716fd348SMartin Matuska "ZIO_COMPRESS_GZIP_8", "ZIO_COMPRESS_GZIP_9", 362716fd348SMartin Matuska "ZIO_COMPRESS_ZLE", "ZIO_COMPRESS_LZ4", 363716fd348SMartin Matuska "ZIO_COMPRESS_ZSTD", "ZIO_COMPRESS_FUNCTION"] 364716fd348SMartin Matuska 365716fd348SMartin Matuska # If "-rr" option is used, don't convert to string representation 366716fd348SMartin Matuska if raw > 1: 367716fd348SMartin Matuska return "%i" % c 368716fd348SMartin Matuska 369716fd348SMartin Matuska try: 370716fd348SMartin Matuska return comp_strings[c] 371716fd348SMartin Matuska except IndexError: 372716fd348SMartin Matuska return "%i" % c 373716fd348SMartin Matuska 374716fd348SMartin Matuska 375716fd348SMartin Matuskadef parse_line(line, labels): 376716fd348SMartin Matuska global hdr 377716fd348SMartin Matuska 378716fd348SMartin Matuska new = dict() 379716fd348SMartin Matuska val = None 380716fd348SMartin Matuska for col in hdr: 381716fd348SMartin Matuska # These are "special" fields computed in the update_dict 382716fd348SMartin Matuska # function, prevent KeyError exception on labels[col] for these. 383716fd348SMartin Matuska if col not in ['bonus', 'cached', 'direct', 'indirect', 'spill']: 384716fd348SMartin Matuska val = line[labels[col]] 385716fd348SMartin Matuska 386716fd348SMartin Matuska if col in ['pool', 'flags']: 387716fd348SMartin Matuska new[col] = str(val) 388716fd348SMartin Matuska elif col in ['dtype', 'btype']: 389716fd348SMartin Matuska new[col] = get_typestring(int(val)) 390716fd348SMartin Matuska elif col in ['l2_comp']: 391716fd348SMartin Matuska new[col] = get_compstring(int(val)) 392716fd348SMartin Matuska else: 393716fd348SMartin Matuska new[col] = int(val) 394716fd348SMartin Matuska 395716fd348SMartin Matuska return new 396716fd348SMartin Matuska 397716fd348SMartin Matuska 398716fd348SMartin Matuskadef update_dict(d, k, line, labels): 399716fd348SMartin Matuska pool = line[labels['pool']] 400716fd348SMartin Matuska objset = line[labels['objset']] 401716fd348SMartin Matuska key = line[labels[k]] 402716fd348SMartin Matuska 403716fd348SMartin Matuska dbsize = int(line[labels['dbsize']]) 404a2b560ccSMartin Matuska usize = int(line[labels['usize']]) 405716fd348SMartin Matuska blkid = int(line[labels['blkid']]) 406716fd348SMartin Matuska level = int(line[labels['level']]) 407716fd348SMartin Matuska 408716fd348SMartin Matuska if pool not in d: 409716fd348SMartin Matuska d[pool] = dict() 410716fd348SMartin Matuska 411716fd348SMartin Matuska if objset not in d[pool]: 412716fd348SMartin Matuska d[pool][objset] = dict() 413716fd348SMartin Matuska 414716fd348SMartin Matuska if key not in d[pool][objset]: 415716fd348SMartin Matuska d[pool][objset][key] = parse_line(line, labels) 416716fd348SMartin Matuska d[pool][objset][key]['bonus'] = 0 417716fd348SMartin Matuska d[pool][objset][key]['cached'] = 0 418716fd348SMartin Matuska d[pool][objset][key]['direct'] = 0 419716fd348SMartin Matuska d[pool][objset][key]['indirect'] = 0 420716fd348SMartin Matuska d[pool][objset][key]['spill'] = 0 421716fd348SMartin Matuska 422a2b560ccSMartin Matuska d[pool][objset][key]['cached'] += dbsize + usize 423716fd348SMartin Matuska 424716fd348SMartin Matuska if blkid == -1: 425716fd348SMartin Matuska d[pool][objset][key]['bonus'] += dbsize 426716fd348SMartin Matuska elif blkid == -2: 427716fd348SMartin Matuska d[pool][objset][key]['spill'] += dbsize 428716fd348SMartin Matuska else: 429716fd348SMartin Matuska if level == 0: 430716fd348SMartin Matuska d[pool][objset][key]['direct'] += dbsize 431716fd348SMartin Matuska else: 432716fd348SMartin Matuska d[pool][objset][key]['indirect'] += dbsize 433716fd348SMartin Matuska 434716fd348SMartin Matuska return d 435716fd348SMartin Matuska 436716fd348SMartin Matuska 437716fd348SMartin Matuskadef skip_line(vals, filters): 438716fd348SMartin Matuska ''' 439716fd348SMartin Matuska Determines if a line should be skipped during printing 440716fd348SMartin Matuska based on a set of filters 441716fd348SMartin Matuska ''' 442716fd348SMartin Matuska if len(filters) == 0: 443716fd348SMartin Matuska return False 444716fd348SMartin Matuska 445716fd348SMartin Matuska for key in vals: 446716fd348SMartin Matuska if key in filters: 447716fd348SMartin Matuska val = prettynum(cols[key][0], cols[key][1], vals[key]).strip() 448716fd348SMartin Matuska # we want a full match here 449716fd348SMartin Matuska if re.match("(?:" + filters[key] + r")\Z", val) is None: 450716fd348SMartin Matuska return True 451716fd348SMartin Matuska 452716fd348SMartin Matuska return False 453716fd348SMartin Matuska 454716fd348SMartin Matuska 455716fd348SMartin Matuskadef print_dict(d, filters, noheader): 456716fd348SMartin Matuska if not noheader: 457716fd348SMartin Matuska print_header() 458716fd348SMartin Matuska for pool in list(d.keys()): 459716fd348SMartin Matuska for objset in list(d[pool].keys()): 460716fd348SMartin Matuska for v in list(d[pool][objset].values()): 461716fd348SMartin Matuska if not skip_line(v, filters): 462716fd348SMartin Matuska print_values(v) 463716fd348SMartin Matuska 464716fd348SMartin Matuska 465716fd348SMartin Matuskadef dnodes_build_dict(filehandle): 466716fd348SMartin Matuska labels = dict() 467716fd348SMartin Matuska dnodes = dict() 468716fd348SMartin Matuska 469716fd348SMartin Matuska # First 3 lines are header information, skip the first two 470716fd348SMartin Matuska for i in range(2): 471716fd348SMartin Matuska next(filehandle) 472716fd348SMartin Matuska 473716fd348SMartin Matuska # The third line contains the labels and index locations 474716fd348SMartin Matuska for i, v in enumerate(next(filehandle).split()): 475716fd348SMartin Matuska labels[v] = i 476716fd348SMartin Matuska 477716fd348SMartin Matuska # The rest of the file is buffer information 478716fd348SMartin Matuska for line in filehandle: 479716fd348SMartin Matuska update_dict(dnodes, 'object', line.split(), labels) 480716fd348SMartin Matuska 481716fd348SMartin Matuska return dnodes 482716fd348SMartin Matuska 483716fd348SMartin Matuska 484716fd348SMartin Matuskadef types_build_dict(filehandle): 485716fd348SMartin Matuska labels = dict() 486716fd348SMartin Matuska types = dict() 487716fd348SMartin Matuska 488716fd348SMartin Matuska # First 3 lines are header information, skip the first two 489716fd348SMartin Matuska for i in range(2): 490716fd348SMartin Matuska next(filehandle) 491716fd348SMartin Matuska 492716fd348SMartin Matuska # The third line contains the labels and index locations 493716fd348SMartin Matuska for i, v in enumerate(next(filehandle).split()): 494716fd348SMartin Matuska labels[v] = i 495716fd348SMartin Matuska 496716fd348SMartin Matuska # The rest of the file is buffer information 497716fd348SMartin Matuska for line in filehandle: 498716fd348SMartin Matuska update_dict(types, 'dtype', line.split(), labels) 499716fd348SMartin Matuska 500716fd348SMartin Matuska return types 501716fd348SMartin Matuska 502716fd348SMartin Matuska 503716fd348SMartin Matuskadef buffers_print_all(filehandle, filters, noheader): 504716fd348SMartin Matuska labels = dict() 505716fd348SMartin Matuska 506716fd348SMartin Matuska # First 3 lines are header information, skip the first two 507716fd348SMartin Matuska for i in range(2): 508716fd348SMartin Matuska next(filehandle) 509716fd348SMartin Matuska 510716fd348SMartin Matuska # The third line contains the labels and index locations 511716fd348SMartin Matuska for i, v in enumerate(next(filehandle).split()): 512716fd348SMartin Matuska labels[v] = i 513716fd348SMartin Matuska 514716fd348SMartin Matuska if not noheader: 515716fd348SMartin Matuska print_header() 516716fd348SMartin Matuska 517716fd348SMartin Matuska # The rest of the file is buffer information 518716fd348SMartin Matuska for line in filehandle: 519716fd348SMartin Matuska vals = parse_line(line.split(), labels) 520716fd348SMartin Matuska if not skip_line(vals, filters): 521716fd348SMartin Matuska print_values(vals) 522716fd348SMartin Matuska 523716fd348SMartin Matuska 524716fd348SMartin Matuskadef main(): 525716fd348SMartin Matuska global hdr 526716fd348SMartin Matuska global sep 527716fd348SMartin Matuska global raw 528716fd348SMartin Matuska 529716fd348SMartin Matuska desired_cols = None 530716fd348SMartin Matuska bflag = False 531716fd348SMartin Matuska dflag = False 532716fd348SMartin Matuska hflag = False 533716fd348SMartin Matuska ifile = None 534716fd348SMartin Matuska ofile = None 535716fd348SMartin Matuska tflag = False 536716fd348SMartin Matuska vflag = False 537716fd348SMartin Matuska xflag = False 538716fd348SMartin Matuska nflag = False 539716fd348SMartin Matuska filters = dict() 540716fd348SMartin Matuska 541716fd348SMartin Matuska try: 542716fd348SMartin Matuska opts, args = getopt.getopt( 543716fd348SMartin Matuska sys.argv[1:], 544716fd348SMartin Matuska "bdf:hi:o:rs:tvxF:n", 545716fd348SMartin Matuska [ 546716fd348SMartin Matuska "buffers", 547716fd348SMartin Matuska "dnodes", 548716fd348SMartin Matuska "columns", 549716fd348SMartin Matuska "help", 550716fd348SMartin Matuska "infile", 551716fd348SMartin Matuska "outfile", 552716fd348SMartin Matuska "separator", 553716fd348SMartin Matuska "types", 554716fd348SMartin Matuska "verbose", 555716fd348SMartin Matuska "extended", 556716fd348SMartin Matuska "filter" 557716fd348SMartin Matuska ] 558716fd348SMartin Matuska ) 559716fd348SMartin Matuska except getopt.error: 560716fd348SMartin Matuska usage() 561716fd348SMartin Matuska opts = None 562716fd348SMartin Matuska 563716fd348SMartin Matuska for opt, arg in opts: 564716fd348SMartin Matuska if opt in ('-b', '--buffers'): 565716fd348SMartin Matuska bflag = True 566716fd348SMartin Matuska if opt in ('-d', '--dnodes'): 567716fd348SMartin Matuska dflag = True 568716fd348SMartin Matuska if opt in ('-f', '--columns'): 569716fd348SMartin Matuska desired_cols = arg 570716fd348SMartin Matuska if opt in ('-h', '--help'): 571716fd348SMartin Matuska hflag = True 572716fd348SMartin Matuska if opt in ('-i', '--infile'): 573716fd348SMartin Matuska ifile = arg 574716fd348SMartin Matuska if opt in ('-o', '--outfile'): 575716fd348SMartin Matuska ofile = arg 576716fd348SMartin Matuska if opt in ('-r', '--raw'): 577716fd348SMartin Matuska raw += 1 578716fd348SMartin Matuska if opt in ('-s', '--separator'): 579716fd348SMartin Matuska sep = arg 580716fd348SMartin Matuska if opt in ('-t', '--types'): 581716fd348SMartin Matuska tflag = True 582716fd348SMartin Matuska if opt in ('-v', '--verbose'): 583716fd348SMartin Matuska vflag = True 584716fd348SMartin Matuska if opt in ('-x', '--extended'): 585716fd348SMartin Matuska xflag = True 586716fd348SMartin Matuska if opt in ('-n', '--noheader'): 587716fd348SMartin Matuska nflag = True 588716fd348SMartin Matuska if opt in ('-F', '--filter'): 589716fd348SMartin Matuska fils = [x.strip() for x in arg.split(",")] 590716fd348SMartin Matuska 591716fd348SMartin Matuska for fil in fils: 592716fd348SMartin Matuska f = [x.strip() for x in fil.split("=")] 593716fd348SMartin Matuska 594716fd348SMartin Matuska if len(f) != 2: 595716fd348SMartin Matuska sys.stderr.write("Invalid filter '%s'.\n" % fil) 596716fd348SMartin Matuska sys.exit(1) 597716fd348SMartin Matuska 598716fd348SMartin Matuska if f[0] not in cols: 599716fd348SMartin Matuska sys.stderr.write("Invalid field '%s' in filter.\n" % f[0]) 600716fd348SMartin Matuska sys.exit(1) 601716fd348SMartin Matuska 602716fd348SMartin Matuska if f[0] in filters: 603716fd348SMartin Matuska sys.stderr.write("Field '%s' specified multiple times in " 604716fd348SMartin Matuska "filter.\n" % f[0]) 605716fd348SMartin Matuska sys.exit(1) 606716fd348SMartin Matuska 607716fd348SMartin Matuska try: 608716fd348SMartin Matuska re.compile("(?:" + f[1] + r")\Z") 609716fd348SMartin Matuska except re.error: 610716fd348SMartin Matuska sys.stderr.write("Invalid regex for field '%s' in " 611716fd348SMartin Matuska "filter.\n" % f[0]) 612716fd348SMartin Matuska sys.exit(1) 613716fd348SMartin Matuska 614716fd348SMartin Matuska filters[f[0]] = f[1] 615716fd348SMartin Matuska 616716fd348SMartin Matuska if hflag or (xflag and desired_cols): 617716fd348SMartin Matuska usage() 618716fd348SMartin Matuska 619716fd348SMartin Matuska if vflag: 620716fd348SMartin Matuska detailed_usage() 621716fd348SMartin Matuska 622716fd348SMartin Matuska # Ensure at most only one of b, d, or t flags are set 623716fd348SMartin Matuska if (bflag and dflag) or (bflag and tflag) or (dflag and tflag): 624716fd348SMartin Matuska usage() 625716fd348SMartin Matuska 626716fd348SMartin Matuska if bflag: 627716fd348SMartin Matuska hdr = bxhdr if xflag else bhdr 628716fd348SMartin Matuska elif tflag: 629716fd348SMartin Matuska hdr = txhdr if xflag else thdr 630716fd348SMartin Matuska else: # Even if dflag is False, it's the default if none set 631716fd348SMartin Matuska dflag = True 632716fd348SMartin Matuska hdr = dxhdr if xflag else dhdr 633716fd348SMartin Matuska 634716fd348SMartin Matuska if desired_cols: 635716fd348SMartin Matuska hdr = desired_cols.split(",") 636716fd348SMartin Matuska 637716fd348SMartin Matuska invalid = [] 638716fd348SMartin Matuska incompat = [] 639716fd348SMartin Matuska for ele in hdr: 640716fd348SMartin Matuska if ele not in cols: 641716fd348SMartin Matuska invalid.append(ele) 642716fd348SMartin Matuska elif ((bflag and bincompat and ele in bincompat) or 643716fd348SMartin Matuska (dflag and dincompat and ele in dincompat) or 644716fd348SMartin Matuska (tflag and tincompat and ele in tincompat)): 645716fd348SMartin Matuska incompat.append(ele) 646716fd348SMartin Matuska 647716fd348SMartin Matuska if len(invalid) > 0: 648716fd348SMartin Matuska sys.stderr.write("Invalid column definition! -- %s\n" % invalid) 649716fd348SMartin Matuska usage() 650716fd348SMartin Matuska 651716fd348SMartin Matuska if len(incompat) > 0: 652716fd348SMartin Matuska sys.stderr.write("Incompatible field specified! -- %s\n" % 653716fd348SMartin Matuska incompat) 654716fd348SMartin Matuska usage() 655716fd348SMartin Matuska 656716fd348SMartin Matuska if ofile: 657716fd348SMartin Matuska try: 658716fd348SMartin Matuska tmp = open(ofile, "w") 659716fd348SMartin Matuska sys.stdout = tmp 660716fd348SMartin Matuska 661716fd348SMartin Matuska except IOError: 662716fd348SMartin Matuska sys.stderr.write("Cannot open %s for writing\n" % ofile) 663716fd348SMartin Matuska sys.exit(1) 664716fd348SMartin Matuska 665716fd348SMartin Matuska if not ifile: 666716fd348SMartin Matuska ifile = default_ifile() 667716fd348SMartin Matuska 668716fd348SMartin Matuska if ifile != "-": 669716fd348SMartin Matuska try: 670716fd348SMartin Matuska tmp = open(ifile, "r") 671716fd348SMartin Matuska sys.stdin = tmp 672716fd348SMartin Matuska except IOError: 673716fd348SMartin Matuska sys.stderr.write("Cannot open %s for reading\n" % ifile) 674716fd348SMartin Matuska sys.exit(1) 675716fd348SMartin Matuska 676716fd348SMartin Matuska if bflag: 677716fd348SMartin Matuska buffers_print_all(sys.stdin, filters, nflag) 678716fd348SMartin Matuska 679716fd348SMartin Matuska if dflag: 680716fd348SMartin Matuska print_dict(dnodes_build_dict(sys.stdin), filters, nflag) 681716fd348SMartin Matuska 682716fd348SMartin Matuska if tflag: 683716fd348SMartin Matuska print_dict(types_build_dict(sys.stdin), filters, nflag) 684716fd348SMartin Matuska 685716fd348SMartin Matuska 686716fd348SMartin Matuskaif __name__ == '__main__': 687716fd348SMartin Matuska main() 688