File Index
Files and directories
Sign in
FILE

drgn_dump_damon_status.py

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/damon/drgn_dump_damon_status.py PYTHON
  1#!/usr/bin/env drgn
  2# SPDX-License-Identifier: GPL-2.0
  3
  4'''
  5Read DAMON context data and dump as a json string.
  6'''
  7import drgn
  8from drgn import FaultError, NULL, Object, cast, container_of, execscript, offsetof, reinterpret, sizeof
  9from drgn.helpers.common import *
 10from drgn.helpers.linux import *
 11
 12import json
 13import sys
 14
 15if "prog" not in globals():
 16    try:
 17        prog = drgn.get_default_prog()
 18    except drgn.NoDefaultProgramError:
 19        prog = drgn.program_from_kernel()
 20        drgn.set_default_prog(prog)
 21
 22def to_dict(object, attr_name_converter):
 23    d = {}
 24    for attr_name, converter in attr_name_converter:
 25        d[attr_name] = converter(getattr(object, attr_name))
 26    return d
 27
 28def ops_to_dict(ops):
 29    return to_dict(ops, [
 30        ['id', int],
 31        ])
 32
 33def intervals_goal_to_dict(goal):
 34    return to_dict(goal, [
 35        ['access_bp', int],
 36        ['aggrs', int],
 37        ['min_sample_us', int],
 38        ['max_sample_us', int],
 39        ])
 40
 41def attrs_to_dict(attrs):
 42    return to_dict(attrs, [
 43        ['sample_interval', int],
 44        ['aggr_interval', int],
 45        ['ops_update_interval', int],
 46        ['intervals_goal', intervals_goal_to_dict],
 47        ['min_nr_regions', int],
 48        ['max_nr_regions', int],
 49        ])
 50
 51def addr_range_to_dict(addr_range):
 52    return to_dict(addr_range, [
 53        ['start', int],
 54        ['end', int],
 55        ])
 56
 57def region_to_dict(region):
 58    return to_dict(region, [
 59        ['ar', addr_range_to_dict],
 60        ['sampling_addr', int],
 61        ['nr_accesses', int],
 62        ['nr_accesses_bp', int],
 63        ['age', int],
 64        ])
 65
 66def regions_to_list(regions):
 67    return [region_to_dict(r)
 68            for r in list_for_each_entry(
 69                'struct damon_region', regions.address_of_(), 'list')]
 70
 71def target_to_dict(target):
 72    return to_dict(target, [
 73        ['pid', int],
 74        ['nr_regions', int],
 75        ['regions_list', regions_to_list],
 76        ['obsolete', bool],
 77        ])
 78
 79def targets_to_list(targets):
 80    return [target_to_dict(t)
 81            for t in list_for_each_entry(
 82                'struct damon_target', targets.address_of_(), 'list')]
 83
 84def damos_access_pattern_to_dict(pattern):
 85    return to_dict(pattern, [
 86        ['min_sz_region', int],
 87        ['max_sz_region', int],
 88        ['min_nr_accesses', int],
 89        ['max_nr_accesses', int],
 90        ['min_age_region', int],
 91        ['max_age_region', int],
 92        ])
 93
 94def damos_quota_goal_to_dict(goal):
 95    return to_dict(goal, [
 96        ['metric', int],
 97        ['target_value', int],
 98        ['current_value', int],
 99        ['last_psi_total', int],
100        ['nid', int],
101        ])
102
103def damos_quota_goals_to_list(goals):
104    return [damos_quota_goal_to_dict(g)
105            for g in list_for_each_entry(
106                'struct damos_quota_goal', goals.address_of_(), 'list')]
107
108def damos_quota_to_dict(quota):
109    return to_dict(quota, [
110        ['reset_interval', int],
111        ['ms', int], ['sz', int],
112        ['goals', damos_quota_goals_to_list],
113        ['esz', int],
114        ['weight_sz', int],
115        ['weight_nr_accesses', int],
116        ['weight_age', int],
117        ])
118
119def damos_watermarks_to_dict(watermarks):
120    return to_dict(watermarks, [
121        ['metric', int],
122        ['interval', int],
123        ['high', int], ['mid', int], ['low', int],
124        ])
125
126def damos_migrate_dests_to_dict(dests):
127    nr_dests = int(dests.nr_dests)
128    node_id_arr = []
129    weight_arr = []
130    for i in range(nr_dests):
131        node_id_arr.append(int(dests.node_id_arr[i]))
132        weight_arr.append(int(dests.weight_arr[i]))
133    return {
134            'node_id_arr': node_id_arr,
135            'weight_arr': weight_arr,
136            'nr_dests': nr_dests,
137            }
138
139def damos_filter_to_dict(damos_filter):
140    filter_type_keyword = {
141            0: 'anon',
142            1: 'active',
143            2: 'memcg',
144            3: 'young',
145            4: 'hugepage_size',
146            5: 'unmapped',
147            6: 'addr',
148            7: 'target'
149            }
150    dict_ = {
151            'type': filter_type_keyword[int(damos_filter.type)],
152            'matching': bool(damos_filter.matching),
153            'allow': bool(damos_filter.allow),
154            }
155    type_ = dict_['type']
156    if type_ == 'memcg':
157        dict_['memcg_id'] = int(damos_filter.memcg_id)
158    elif type_ == 'addr':
159        dict_['addr_range'] = [int(damos_filter.addr_range.start),
160                               int(damos_filter.addr_range.end)]
161    elif type_ == 'target':
162        dict_['target_idx'] = int(damos_filter.target_idx)
163    elif type_ == 'hugeapge_size':
164        dict_['sz_range'] = [int(damos_filter.sz_range.min),
165                             int(damos_filter.sz_range.max)]
166    return dict_
167
168def scheme_to_dict(scheme):
169    dict_ = to_dict(scheme, [
170        ['pattern', damos_access_pattern_to_dict],
171        ['action', int],
172        ['apply_interval_us', int],
173        ['quota', damos_quota_to_dict],
174        ['wmarks', damos_watermarks_to_dict],
175        ['target_nid', int],
176        ['migrate_dests', damos_migrate_dests_to_dict],
177        ])
178    core_filters = []
179    for f in list_for_each_entry(
180            'struct damos_filter', scheme.core_filters.address_of_(), 'list'):
181        core_filters.append(damos_filter_to_dict(f))
182    dict_['core_filters'] = core_filters
183    ops_filters = []
184    for f in list_for_each_entry(
185            'struct damos_filter', scheme.ops_filters.address_of_(), 'list'):
186        ops_filters.append(damos_filter_to_dict(f))
187    dict_['ops_filters'] = ops_filters
188
189    return dict_
190
191def schemes_to_list(schemes):
192    return [scheme_to_dict(s)
193            for s in list_for_each_entry(
194                'struct damos', schemes.address_of_(), 'list')]
195
196def damon_ctx_to_dict(ctx):
197    return to_dict(ctx, [
198        ['ops', ops_to_dict],
199        ['attrs', attrs_to_dict],
200        ['adaptive_targets', targets_to_list],
201        ['schemes', schemes_to_list],
202        ])
203
204def main():
205    if len(sys.argv) < 3:
206        print('Usage: %s <kdamond pid> <file>' % sys.argv[0])
207        exit(1)
208
209    pid = int(sys.argv[1])
210    file_to_store = sys.argv[2]
211
212    kthread_data = cast('struct kthread *',
213                        find_task(prog, pid).worker_private).data
214    ctx = cast('struct damon_ctx *', kthread_data)
215    status = {'contexts': [damon_ctx_to_dict(ctx)]}
216    if file_to_store == 'stdout':
217        print(json.dumps(status, indent=4))
218    else:
219        with open(file_to_store, 'w') as f:
220            json.dump(status, f, indent=4)
221
222if __name__ == '__main__':
223    main()
~/ Read-only file preview.