^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/usr/bin/env drgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) # Copyright (C) 2019 Tejun Heo <tj@kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) # Copyright (C) 2019 Facebook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) desc = """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) This is a drgn script to monitor the blk-iocost cgroup controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) See the comment at the top of block/blk-iocost.c for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) For drgn, visit https://github.com/osandov/drgn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) import sys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) import re
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) import time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) import json
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) import math
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) import drgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) from drgn import container_of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) from drgn.helpers.linux.list import list_for_each_entry,list_empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) from drgn.helpers.linux.radixtree import radix_tree_for_each,radix_tree_lookup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) import argparse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) parser = argparse.ArgumentParser(description=desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) formatter_class=argparse.RawTextHelpFormatter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) parser.add_argument('devname', metavar='DEV',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) help='Target block device name (e.g. sda)')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) parser.add_argument('--cgroup', action='append', metavar='REGEX',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) help='Regex for target cgroups, ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) parser.add_argument('--interval', '-i', metavar='SECONDS', type=float, default=1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) help='Monitoring interval in seconds (0 exits immediately '
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) 'after checking requirements)')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) parser.add_argument('--json', action='store_true',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) help='Output in json')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) args = parser.parse_args()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) def err(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) print(s, file=sys.stderr, flush=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) sys.exit(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) blkcg_root = prog['blkcg_root']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) plid = prog['blkcg_policy_iocost'].plid.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) except:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) err('The kernel does not have iocost enabled')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) IOC_RUNNING = prog['IOC_RUNNING'].value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) WEIGHT_ONE = prog['WEIGHT_ONE'].value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) VTIME_PER_SEC = prog['VTIME_PER_SEC'].value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) VTIME_PER_USEC = prog['VTIME_PER_USEC'].value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) AUTOP_SSD_FAST = prog['AUTOP_SSD_FAST'].value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) AUTOP_SSD_DFL = prog['AUTOP_SSD_DFL'].value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) AUTOP_SSD_QD1 = prog['AUTOP_SSD_QD1'].value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) AUTOP_HDD = prog['AUTOP_HDD'].value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) autop_names = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) AUTOP_SSD_FAST: 'ssd_fast',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) AUTOP_SSD_DFL: 'ssd_dfl',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) AUTOP_SSD_QD1: 'ssd_qd1',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) AUTOP_HDD: 'hdd',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) class BlkgIterator:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) def blkcg_name(blkcg):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return blkcg.css.cgroup.kn.name.string_().decode('utf-8')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) def walk(self, blkcg, q_id, parent_path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if not self.include_dying and \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) not (blkcg.css.flags.value_() & prog['CSS_ONLINE'].value_()):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) name = BlkgIterator.blkcg_name(blkcg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) path = parent_path + '/' + name if parent_path else name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) blkg = drgn.Object(prog, 'struct blkcg_gq',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) address=radix_tree_lookup(blkcg.blkg_tree.address_of_(), q_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if not blkg.address_:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) self.blkgs.append((path if path else '/', blkg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) for c in list_for_each_entry('struct blkcg',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) blkcg.css.children.address_of_(), 'css.sibling'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) self.walk(c, q_id, path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) def __init__(self, root_blkcg, q_id, include_dying=False):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) self.include_dying = include_dying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) self.blkgs = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) self.walk(root_blkcg, q_id, '')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) def __iter__(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return iter(self.blkgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) class IocStat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) def __init__(self, ioc):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) global autop_names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) self.enabled = ioc.enabled.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) self.running = ioc.running.value_() == IOC_RUNNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) self.period_ms = ioc.period_us.value_() / 1_000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) self.period_at = ioc.period_at.value_() / 1_000_000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) self.vperiod_at = ioc.period_at_vtime.value_() / VTIME_PER_SEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) self.vrate_pct = ioc.vtime_base_rate.value_() * 100 / VTIME_PER_USEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) self.busy_level = ioc.busy_level.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) self.autop_idx = ioc.autop_idx.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) self.user_cost_model = ioc.user_cost_model.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) self.user_qos_params = ioc.user_qos_params.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if self.autop_idx in autop_names:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) self.autop_name = autop_names[self.autop_idx]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) self.autop_name = '?'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) def dict(self, now):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return { 'device' : devname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 'timestamp' : now,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 'enabled' : self.enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 'running' : self.running,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 'period_ms' : self.period_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 'period_at' : self.period_at,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 'period_vtime_at' : self.vperiod_at,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 'busy_level' : self.busy_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 'vrate_pct' : self.vrate_pct, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) def table_preamble_str(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) state = ('RUN' if self.running else 'IDLE') if self.enabled else 'OFF'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) output = f'{devname} {state:4} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) f'per={self.period_ms}ms ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) f'cur_per={self.period_at:.3f}:v{self.vperiod_at:.3f} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) f'busy={self.busy_level:+3} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) f'vrate={self.vrate_pct:6.2f}% ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) f'params={self.autop_name}'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if self.user_cost_model or self.user_qos_params:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) output += f'({"C" if self.user_cost_model else ""}{"Q" if self.user_qos_params else ""})'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) def table_header_str(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return f'{"":25} active {"weight":>9} {"hweight%":>13} {"inflt%":>6} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) f'{"debt":>7} {"delay":>7} {"usage%"}'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) class IocgStat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) def __init__(self, iocg):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ioc = iocg.ioc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) blkg = iocg.pd.blkg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) self.is_active = not list_empty(iocg.active_list.address_of_())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) self.weight = iocg.weight.value_() / WEIGHT_ONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) self.active = iocg.active.value_() / WEIGHT_ONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) self.inuse = iocg.inuse.value_() / WEIGHT_ONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) self.hwa_pct = iocg.hweight_active.value_() * 100 / WEIGHT_ONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) self.hwi_pct = iocg.hweight_inuse.value_() * 100 / WEIGHT_ONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) self.address = iocg.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) vdone = iocg.done_vtime.counter.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) vtime = iocg.vtime.counter.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) vrate = ioc.vtime_rate.counter.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) period_vtime = ioc.period_us.value_() * vrate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if period_vtime:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) self.inflight_pct = (vtime - vdone) * 100 / period_vtime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) self.inflight_pct = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) self.usage = (100 * iocg.usage_delta_us.value_() /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ioc.period_us.value_()) if self.active else 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) self.debt_ms = iocg.abs_vdebt.value_() / VTIME_PER_USEC / 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if blkg.use_delay.counter.value_() != 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) self.delay_ms = blkg.delay_nsec.counter.value_() / 1_000_000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) self.delay_ms = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) def dict(self, now, path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) out = { 'cgroup' : path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 'timestamp' : now,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 'is_active' : self.is_active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 'weight' : self.weight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 'weight_active' : self.active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 'weight_inuse' : self.inuse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 'hweight_active_pct' : self.hwa_pct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 'hweight_inuse_pct' : self.hwi_pct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 'inflight_pct' : self.inflight_pct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 'debt_ms' : self.debt_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 'delay_ms' : self.delay_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 'usage_pct' : self.usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 'address' : self.address }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) def table_row_str(self, path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) out = f'{path[-28:]:28} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) f'{"*" if self.is_active else " "} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) f'{round(self.inuse):5}/{round(self.active):5} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) f'{self.hwi_pct:6.2f}/{self.hwa_pct:6.2f} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) f'{self.inflight_pct:6.2f} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) f'{self.debt_ms:7.2f} ' \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) f'{self.delay_ms:7.2f} '\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) f'{min(self.usage, 999):6.2f}'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) out = out.rstrip(':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) # handle args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) table_fmt = not args.json
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) interval = args.interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) devname = args.devname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if args.json:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) table_fmt = False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) re_str = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if args.cgroup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) for r in args.cgroup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if re_str is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) re_str = r
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) re_str += '|' + r
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) filter_re = re.compile(re_str) if re_str else None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) # Locate the roots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) q_id = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) root_iocg = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ioc = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) for i, ptr in radix_tree_for_each(blkcg_root.blkg_tree.address_of_()):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) blkg = drgn.Object(prog, 'struct blkcg_gq', address=ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if devname == blkg.q.kobj.parent.name.string_().decode('utf-8'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) q_id = blkg.q.id.value_()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if blkg.pd[plid]:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) root_iocg = container_of(blkg.pd[plid], 'struct ioc_gq', 'pd')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ioc = root_iocg.ioc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) except:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if ioc is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) err(f'Could not find ioc for {devname}');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if interval == 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) sys.exit(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) # Keep printing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) while True:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) now = time.time()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) iocstat = IocStat(ioc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) output = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if table_fmt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) output += '\n' + iocstat.table_preamble_str()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) output += '\n' + iocstat.table_header_str()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) output += json.dumps(iocstat.dict(now))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) for path, blkg in BlkgIterator(blkcg_root, q_id):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if filter_re and not filter_re.match(path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if not blkg.pd[plid]:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) iocg = container_of(blkg.pd[plid], 'struct ioc_gq', 'pd')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) iocg_stat = IocgStat(iocg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if not filter_re and not iocg_stat.is_active:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if table_fmt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) output += '\n' + iocg_stat.table_row_str(path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) output += '\n' + json.dumps(iocg_stat.dict(now, path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) print(output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sys.stdout.flush()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) time.sleep(interval)