~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/cgroup/iocost_monitor.py

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/cgroup/iocost_monitor.py (Architecture ppc) and /tools/cgroup/iocost_monitor.py (Architecture sparc)


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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php