Path: blob/master/tools/testing/selftests/damon/drgn_dump_damon_status.py
51978 views
#!/usr/bin/env drgn1# SPDX-License-Identifier: GPL-2.023'''4Read DAMON context data and dump as a json string.5'''6import drgn7from drgn import FaultError, NULL, Object, cast, container_of, execscript, offsetof, reinterpret, sizeof8from drgn.helpers.common import *9from drgn.helpers.linux import *1011import json12import sys1314if "prog" not in globals():15try:16prog = drgn.get_default_prog()17except drgn.NoDefaultProgramError:18prog = drgn.program_from_kernel()19drgn.set_default_prog(prog)2021def to_dict(object, attr_name_converter):22d = {}23for attr_name, converter in attr_name_converter:24d[attr_name] = converter(getattr(object, attr_name))25return d2627def ops_to_dict(ops):28return to_dict(ops, [29['id', int],30])3132def intervals_goal_to_dict(goal):33return to_dict(goal, [34['access_bp', int],35['aggrs', int],36['min_sample_us', int],37['max_sample_us', int],38])3940def attrs_to_dict(attrs):41return to_dict(attrs, [42['sample_interval', int],43['aggr_interval', int],44['ops_update_interval', int],45['intervals_goal', intervals_goal_to_dict],46['min_nr_regions', int],47['max_nr_regions', int],48])4950def addr_range_to_dict(addr_range):51return to_dict(addr_range, [52['start', int],53['end', int],54])5556def region_to_dict(region):57return to_dict(region, [58['ar', addr_range_to_dict],59['sampling_addr', int],60['nr_accesses', int],61['nr_accesses_bp', int],62['age', int],63])6465def regions_to_list(regions):66return [region_to_dict(r)67for r in list_for_each_entry(68'struct damon_region', regions.address_of_(), 'list')]6970def target_to_dict(target):71return to_dict(target, [72['pid', int],73['nr_regions', int],74['regions_list', regions_to_list],75['obsolete', bool],76])7778def targets_to_list(targets):79return [target_to_dict(t)80for t in list_for_each_entry(81'struct damon_target', targets.address_of_(), 'list')]8283def damos_access_pattern_to_dict(pattern):84return to_dict(pattern, [85['min_sz_region', int],86['max_sz_region', int],87['min_nr_accesses', int],88['max_nr_accesses', int],89['min_age_region', int],90['max_age_region', int],91])9293def damos_quota_goal_to_dict(goal):94return to_dict(goal, [95['metric', int],96['target_value', int],97['current_value', int],98['last_psi_total', int],99['nid', int],100])101102def damos_quota_goals_to_list(goals):103return [damos_quota_goal_to_dict(g)104for g in list_for_each_entry(105'struct damos_quota_goal', goals.address_of_(), 'list')]106107def damos_quota_to_dict(quota):108return to_dict(quota, [109['reset_interval', int],110['ms', int], ['sz', int],111['goals', damos_quota_goals_to_list],112['esz', int],113['weight_sz', int],114['weight_nr_accesses', int],115['weight_age', int],116])117118def damos_watermarks_to_dict(watermarks):119return to_dict(watermarks, [120['metric', int],121['interval', int],122['high', int], ['mid', int], ['low', int],123])124125def damos_migrate_dests_to_dict(dests):126nr_dests = int(dests.nr_dests)127node_id_arr = []128weight_arr = []129for i in range(nr_dests):130node_id_arr.append(int(dests.node_id_arr[i]))131weight_arr.append(int(dests.weight_arr[i]))132return {133'node_id_arr': node_id_arr,134'weight_arr': weight_arr,135'nr_dests': nr_dests,136}137138def damos_filter_to_dict(damos_filter):139filter_type_keyword = {1400: 'anon',1411: 'active',1422: 'memcg',1433: 'young',1444: 'hugepage_size',1455: 'unmapped',1466: 'addr',1477: 'target'148}149dict_ = {150'type': filter_type_keyword[int(damos_filter.type)],151'matching': bool(damos_filter.matching),152'allow': bool(damos_filter.allow),153}154type_ = dict_['type']155if type_ == 'memcg':156dict_['memcg_id'] = int(damos_filter.memcg_id)157elif type_ == 'addr':158dict_['addr_range'] = [int(damos_filter.addr_range.start),159int(damos_filter.addr_range.end)]160elif type_ == 'target':161dict_['target_idx'] = int(damos_filter.target_idx)162elif type_ == 'hugeapge_size':163dict_['sz_range'] = [int(damos_filter.sz_range.min),164int(damos_filter.sz_range.max)]165return dict_166167def scheme_to_dict(scheme):168dict_ = to_dict(scheme, [169['pattern', damos_access_pattern_to_dict],170['action', int],171['apply_interval_us', int],172['quota', damos_quota_to_dict],173['wmarks', damos_watermarks_to_dict],174['target_nid', int],175['migrate_dests', damos_migrate_dests_to_dict],176])177core_filters = []178for f in list_for_each_entry(179'struct damos_filter', scheme.core_filters.address_of_(), 'list'):180core_filters.append(damos_filter_to_dict(f))181dict_['core_filters'] = core_filters182ops_filters = []183for f in list_for_each_entry(184'struct damos_filter', scheme.ops_filters.address_of_(), 'list'):185ops_filters.append(damos_filter_to_dict(f))186dict_['ops_filters'] = ops_filters187188return dict_189190def schemes_to_list(schemes):191return [scheme_to_dict(s)192for s in list_for_each_entry(193'struct damos', schemes.address_of_(), 'list')]194195def damon_ctx_to_dict(ctx):196return to_dict(ctx, [197['ops', ops_to_dict],198['attrs', attrs_to_dict],199['adaptive_targets', targets_to_list],200['schemes', schemes_to_list],201])202203def main():204if len(sys.argv) < 3:205print('Usage: %s <kdamond pid> <file>' % sys.argv[0])206exit(1)207208pid = int(sys.argv[1])209file_to_store = sys.argv[2]210211kthread_data = cast('struct kthread *',212find_task(prog, pid).worker_private).data213ctx = cast('struct damon_ctx *', kthread_data)214status = {'contexts': [damon_ctx_to_dict(ctx)]}215if file_to_store == 'stdout':216print(json.dumps(status, indent=4))217else:218with open(file_to_store, 'w') as f:219json.dump(status, f, indent=4)220221if __name__ == '__main__':222main()223224225