| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- #!/usr/bin/env drgn
- # SPDX-License-Identifier: GPL-2.0
- '''
- Read DAMON context data and dump as a json string.
- '''
- import drgn
- from drgn import FaultError, NULL, Object, cast, container_of, execscript, offsetof, reinterpret, sizeof
- from drgn.helpers.common import *
- from drgn.helpers.linux import *
- import json
- import sys
- if "prog" not in globals():
- try:
- prog = drgn.get_default_prog()
- except drgn.NoDefaultProgramError:
- prog = drgn.program_from_kernel()
- drgn.set_default_prog(prog)
- def to_dict(object, attr_name_converter):
- d = {}
- for attr_name, converter in attr_name_converter:
- d[attr_name] = converter(getattr(object, attr_name))
- return d
- def ops_to_dict(ops):
- return to_dict(ops, [
- ['id', int],
- ])
- def intervals_goal_to_dict(goal):
- return to_dict(goal, [
- ['access_bp', int],
- ['aggrs', int],
- ['min_sample_us', int],
- ['max_sample_us', int],
- ])
- def attrs_to_dict(attrs):
- return to_dict(attrs, [
- ['sample_interval', int],
- ['aggr_interval', int],
- ['ops_update_interval', int],
- ['intervals_goal', intervals_goal_to_dict],
- ['min_nr_regions', int],
- ['max_nr_regions', int],
- ])
- def addr_range_to_dict(addr_range):
- return to_dict(addr_range, [
- ['start', int],
- ['end', int],
- ])
- def region_to_dict(region):
- return to_dict(region, [
- ['ar', addr_range_to_dict],
- ['sampling_addr', int],
- ['nr_accesses', int],
- ['nr_accesses_bp', int],
- ['age', int],
- ])
- def regions_to_list(regions):
- return [region_to_dict(r)
- for r in list_for_each_entry(
- 'struct damon_region', regions.address_of_(), 'list')]
- def target_to_dict(target):
- return to_dict(target, [
- ['pid', int],
- ['nr_regions', int],
- ['regions_list', regions_to_list],
- ['obsolete', bool],
- ])
- def targets_to_list(targets):
- return [target_to_dict(t)
- for t in list_for_each_entry(
- 'struct damon_target', targets.address_of_(), 'list')]
- def damos_access_pattern_to_dict(pattern):
- return to_dict(pattern, [
- ['min_sz_region', int],
- ['max_sz_region', int],
- ['min_nr_accesses', int],
- ['max_nr_accesses', int],
- ['min_age_region', int],
- ['max_age_region', int],
- ])
- def damos_quota_goal_to_dict(goal):
- return to_dict(goal, [
- ['metric', int],
- ['target_value', int],
- ['current_value', int],
- ['last_psi_total', int],
- ['nid', int],
- ])
- def damos_quota_goals_to_list(goals):
- return [damos_quota_goal_to_dict(g)
- for g in list_for_each_entry(
- 'struct damos_quota_goal', goals.address_of_(), 'list')]
- def damos_quota_to_dict(quota):
- return to_dict(quota, [
- ['reset_interval', int],
- ['ms', int], ['sz', int],
- ['goals', damos_quota_goals_to_list],
- ['esz', int],
- ['weight_sz', int],
- ['weight_nr_accesses', int],
- ['weight_age', int],
- ])
- def damos_watermarks_to_dict(watermarks):
- return to_dict(watermarks, [
- ['metric', int],
- ['interval', int],
- ['high', int], ['mid', int], ['low', int],
- ])
- def damos_migrate_dests_to_dict(dests):
- nr_dests = int(dests.nr_dests)
- node_id_arr = []
- weight_arr = []
- for i in range(nr_dests):
- node_id_arr.append(int(dests.node_id_arr[i]))
- weight_arr.append(int(dests.weight_arr[i]))
- return {
- 'node_id_arr': node_id_arr,
- 'weight_arr': weight_arr,
- 'nr_dests': nr_dests,
- }
- def damos_filter_to_dict(damos_filter):
- filter_type_keyword = {
- 0: 'anon',
- 1: 'active',
- 2: 'memcg',
- 3: 'young',
- 4: 'hugepage_size',
- 5: 'unmapped',
- 6: 'addr',
- 7: 'target'
- }
- dict_ = {
- 'type': filter_type_keyword[int(damos_filter.type)],
- 'matching': bool(damos_filter.matching),
- 'allow': bool(damos_filter.allow),
- }
- type_ = dict_['type']
- if type_ == 'memcg':
- dict_['memcg_id'] = int(damos_filter.memcg_id)
- elif type_ == 'addr':
- dict_['addr_range'] = [int(damos_filter.addr_range.start),
- int(damos_filter.addr_range.end)]
- elif type_ == 'target':
- dict_['target_idx'] = int(damos_filter.target_idx)
- elif type_ == 'hugeapge_size':
- dict_['sz_range'] = [int(damos_filter.sz_range.min),
- int(damos_filter.sz_range.max)]
- return dict_
- def scheme_to_dict(scheme):
- dict_ = to_dict(scheme, [
- ['pattern', damos_access_pattern_to_dict],
- ['action', int],
- ['apply_interval_us', int],
- ['quota', damos_quota_to_dict],
- ['wmarks', damos_watermarks_to_dict],
- ['target_nid', int],
- ['migrate_dests', damos_migrate_dests_to_dict],
- ])
- core_filters = []
- for f in list_for_each_entry(
- 'struct damos_filter', scheme.core_filters.address_of_(), 'list'):
- core_filters.append(damos_filter_to_dict(f))
- dict_['core_filters'] = core_filters
- ops_filters = []
- for f in list_for_each_entry(
- 'struct damos_filter', scheme.ops_filters.address_of_(), 'list'):
- ops_filters.append(damos_filter_to_dict(f))
- dict_['ops_filters'] = ops_filters
- return dict_
- def schemes_to_list(schemes):
- return [scheme_to_dict(s)
- for s in list_for_each_entry(
- 'struct damos', schemes.address_of_(), 'list')]
- def damon_ctx_to_dict(ctx):
- return to_dict(ctx, [
- ['ops', ops_to_dict],
- ['attrs', attrs_to_dict],
- ['adaptive_targets', targets_to_list],
- ['schemes', schemes_to_list],
- ])
- def main():
- if len(sys.argv) < 3:
- print('Usage: %s <kdamond pid> <file>' % sys.argv[0])
- exit(1)
- pid = int(sys.argv[1])
- file_to_store = sys.argv[2]
- kthread_data = cast('struct kthread *',
- find_task(prog, pid).worker_private).data
- ctx = cast('struct damon_ctx *', kthread_data)
- status = {'contexts': [damon_ctx_to_dict(ctx)]}
- if file_to_store == 'stdout':
- print(json.dumps(status, indent=4))
- else:
- with open(file_to_store, 'w') as f:
- json.dump(status, f, indent=4)
- if __name__ == '__main__':
- main()
|