Path: blob/master/tools/testing/selftests/damon/drgn_dump_damon_status.py
29268 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])7677def targets_to_list(targets):78return [target_to_dict(t)79for t in list_for_each_entry(80'struct damon_target', targets.address_of_(), 'list')]8182def damos_access_pattern_to_dict(pattern):83return to_dict(pattern, [84['min_sz_region', int],85['max_sz_region', int],86['min_nr_accesses', int],87['max_nr_accesses', int],88['min_age_region', int],89['max_age_region', int],90])9192def damos_quota_goal_to_dict(goal):93return to_dict(goal, [94['metric', int],95['target_value', int],96['current_value', int],97['last_psi_total', int],98['nid', int],99])100101def damos_quota_goals_to_list(goals):102return [damos_quota_goal_to_dict(g)103for g in list_for_each_entry(104'struct damos_quota_goal', goals.address_of_(), 'list')]105106def damos_quota_to_dict(quota):107return to_dict(quota, [108['reset_interval', int],109['ms', int], ['sz', int],110['goals', damos_quota_goals_to_list],111['esz', int],112['weight_sz', int],113['weight_nr_accesses', int],114['weight_age', int],115])116117def damos_watermarks_to_dict(watermarks):118return to_dict(watermarks, [119['metric', int],120['interval', int],121['high', int], ['mid', int], ['low', int],122])123124def damos_migrate_dests_to_dict(dests):125nr_dests = int(dests.nr_dests)126node_id_arr = []127weight_arr = []128for i in range(nr_dests):129node_id_arr.append(int(dests.node_id_arr[i]))130weight_arr.append(int(dests.weight_arr[i]))131return {132'node_id_arr': node_id_arr,133'weight_arr': weight_arr,134'nr_dests': nr_dests,135}136137def damos_filter_to_dict(damos_filter):138filter_type_keyword = {1390: 'anon',1401: 'active',1412: 'memcg',1423: 'young',1434: 'hugepage_size',1445: 'unmapped',1456: 'addr',1467: 'target'147}148dict_ = {149'type': filter_type_keyword[int(damos_filter.type)],150'matching': bool(damos_filter.matching),151'allow': bool(damos_filter.allow),152}153type_ = dict_['type']154if type_ == 'memcg':155dict_['memcg_id'] = int(damos_filter.memcg_id)156elif type_ == 'addr':157dict_['addr_range'] = [int(damos_filter.addr_range.start),158int(damos_filter.addr_range.end)]159elif type_ == 'target':160dict_['target_idx'] = int(damos_filter.target_idx)161elif type_ == 'hugeapge_size':162dict_['sz_range'] = [int(damos_filter.sz_range.min),163int(damos_filter.sz_range.max)]164return dict_165166def scheme_to_dict(scheme):167dict_ = to_dict(scheme, [168['pattern', damos_access_pattern_to_dict],169['action', int],170['apply_interval_us', int],171['quota', damos_quota_to_dict],172['wmarks', damos_watermarks_to_dict],173['target_nid', int],174['migrate_dests', damos_migrate_dests_to_dict],175])176filters = []177for f in list_for_each_entry(178'struct damos_filter', scheme.filters.address_of_(), 'list'):179filters.append(damos_filter_to_dict(f))180dict_['filters'] = filters181ops_filters = []182for f in list_for_each_entry(183'struct damos_filter', scheme.ops_filters.address_of_(), 'list'):184ops_filters.append(damos_filter_to_dict(f))185dict_['ops_filters'] = ops_filters186187return dict_188189def schemes_to_list(schemes):190return [scheme_to_dict(s)191for s in list_for_each_entry(192'struct damos', schemes.address_of_(), 'list')]193194def damon_ctx_to_dict(ctx):195return to_dict(ctx, [196['ops', ops_to_dict],197['attrs', attrs_to_dict],198['adaptive_targets', targets_to_list],199['schemes', schemes_to_list],200])201202def main():203if len(sys.argv) < 3:204print('Usage: %s <kdamond pid> <file>' % sys.argv[0])205exit(1)206207pid = int(sys.argv[1])208file_to_store = sys.argv[2]209210kthread_data = cast('struct kthread *',211find_task(prog, pid).worker_private).data212ctx = cast('struct damon_ctx *', kthread_data)213status = {'contexts': [damon_ctx_to_dict(ctx)]}214if file_to_store == 'stdout':215print(json.dumps(status, indent=4))216else:217with open(file_to_store, 'w') as f:218json.dump(status, f, indent=4)219220if __name__ == '__main__':221main()222223224