From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 605BCC83026 for ; Sat, 28 Jun 2025 16:04:37 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 97D508D0003; Sat, 28 Jun 2025 12:04:36 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 907E58D0001; Sat, 28 Jun 2025 12:04:36 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6BD658D0003; Sat, 28 Jun 2025 12:04:36 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 555E58D0001 for ; Sat, 28 Jun 2025 12:04:36 -0400 (EDT) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id DA8051605CB for ; Sat, 28 Jun 2025 16:04:35 +0000 (UTC) X-FDA: 83605282110.25.719D0E7 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf19.hostedemail.com (Postfix) with ESMTP id 32E4E1A000A for ; Sat, 28 Jun 2025 16:04:34 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=cSNgq90N; spf=pass (imf19.hostedemail.com: domain of sj@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=sj@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1751126674; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=ubOiWaSAcWD/yFL/kVtWzhXJ4DyTpg2P772baSPqLRg=; b=1wU1Fxqw2NHO3pH09q+kzqYTKn1JEfdragkAzzCmEtJbYzEKzl7ymTU3n5Jnue726ZJHLa f+aa0ZuJa5gfau4VchR/R/lAiwGhgSUV+srStwGZoabvRrIeUL1LxN4aWD9iL8Y/eJxm9q 8URXnyEHZOYXwhXpe4oh9LQEGPgEtd4= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=cSNgq90N; spf=pass (imf19.hostedemail.com: domain of sj@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=sj@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1751126674; a=rsa-sha256; cv=none; b=XQXV+wsarOkuEkBYRR1Hl3bPTuw2MW3g0pBXhx7ehIF91XUiBkFhiHSyKRAnUgezcbRkA/ HnO11hzpYNo8Z0oE9rdwJyFK4Hq57pH6BqscLcgiR0dLmxk+bWDT35xcA6vMCBt/3GbJnD agONwRODAYI70eMU6wNHUG4xs0mglYw= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 7E8CE5C540E; Sat, 28 Jun 2025 16:04:33 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 02B30C4AF09; Sat, 28 Jun 2025 16:04:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751126673; bh=LQYj+y4NHRcCBylThRwztooldZRKZFHtpfiwZ2j/m2o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cSNgq90NiT1h2PlAU76fonhPwvTnVpXfKhea107Zxg/WgkS1m5B0HUbuX8v6xv3pc /Ks1xCGwDd+yjkcOLjTlVLxZ9PQrRHbGjrSPjnj6452nybIeFmYt88tSn8z2xrDqRu 97akYhFZwrTKu5jVQA6TBZdf9PSSZ+ldmVhvXb+FxakSVTKDCXLQy9PipwzrOj/dTP jVa3PNyMtH4+Kzo8dFOsubWQExw6shD4CjdasLe5GCiRHNMeTS8whyf6uCrKbfHPNL 0Kp1LVjAQtRb17pRT1e4SZ7Atee/57JankmYtNoCvtIXmwyw9GtYx5gxr43oLtfofo tbqWAxBs7Q+CQ== From: SeongJae Park To: Andrew Morton Cc: SeongJae Park , Shuah Khan , damon@lists.linux.dev, kernel-team@meta.com, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH 1/6] selftests/damon: add drgn script for extracting damon status Date: Sat, 28 Jun 2025 09:04:23 -0700 Message-Id: <20250628160428.53115-2-sj@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250628160428.53115-1-sj@kernel.org> References: <20250628160428.53115-1-sj@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspam-User: X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: 32E4E1A000A X-Stat-Signature: ar6hommucdgoeuygn7fnhmjqginpq3ot X-HE-Tag: 1751126674-572333 X-HE-Meta: U2FsdGVkX1/MzQcd3RI34t7SeTP8AnGXR+eL2JG7hLNQCkJygWn4nyCHlwmhPGNKLh+frhg0zkBKa4Q7o9KjfLGvX2+TEUA78GEUUelTMX/GwnZJvvDNAAECokIOX72wv0IxCPC0YZDjfoUzW2Xp06EfEIeICWtp08f87ROwy06d0pir9vm2XLlE4HGzSKGlsDD+WEzr9g4CIWAcdbf+jB+FN6vixejGkZb3+cWiSB9nb6x07AKimmnC53lkEwzp+EoldUPtJrVJ8x1U/Vtpog0aiFxwvwLzbgFz60jQOsXZDI0JkCErP92NQ887x+1JiMjU1NPcYTPgxsUm4WsH0Wa9HrUV1ijzxx0tcDoqjn/AJFpjZdSAyjdIHtnst6ea/ylDfwwJ3JYL98KnL6KTu6ccoZOuu5PD7/RPNrahUheUrcBkBpTSZrnWgjBrqVGITH8XqWW/0Z1YVy5Y3wK6fy/lhWf4BokfzMcftb90/AxspeNEHi60L8nvVWydYFpDcN0BklZb4zsj9JHg1x0Mhp4yZyOUuePDag6nlPPP4XjkkjZpSQ/C2veWgH4OVfmCbjva5gaU40B6f2sruLAYbtJFVfdB/PCpEMqit3qOlR6fEyUNMyjORvoahHeedRQ56c6a1yyXnSPIa74D56mcbKm3KENEeaKWVxrN6bm8dRFuwmZANKpWKIbpd7SnvViU8BWdpJuIAcgsHyggg7TeDro13jZewUvOA+eeNGpoBPz+Hh2korFz05yFaEMWIvnBJmH7nv3UG4wyBQks0b3tnUDq6jh95bJhw0/nTmUEzJyVOrSMv7UWyFLYdqagJvui4u+EAWC0IFs8UGgi7JquRszH8pUNw+GrOCdkNVkOTO5qpzXrB8f0mWGpYBgIutO7j8vyGVS2isMaDAR+c+2KYDMDRuW6to15sedtjz92WZO+XgM+4zx18C1r3vMUT4PYMrCXaDAXZ4dZPIvjVCv GfbJZA6H 3NxIoLlN4mgjEFedA26dccYxnMOhz/Y7ckrJdn8ysdcvn1Q2fC32t99javMc7DPPI5bW443+oZdDhkvoTWEL0A1c80qE3+QoDnE7+YAak/ZWRrODHaFXqDP6LfE07aspNIM+HRLfNlP//5r9p32RzvZFnZb2WeuoQMsaJBK91CMj66oV0owFP5AOiR793FFx8IB/NQzxV7VJBchEwDRbeMhp4Tl6/XblZGQjSV/P0cUrrpjE= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: 'drgn' is a useful tool for extracting kernel internal data structures such as DAMON's parameter and running status. Add a 'drgn' script that extracts such DAMON internal data at runtime, for using it as a tool for seeing if a test input has made expected results in the kernel. The script saves or prints out the DAMON internal data as a json file or string. This is for making use of it not very depends on 'drgn'. If 'drgn' is not available on a test setup and we find alternative tools for doing that, the json-based tests can be updated to use an alternative tool in future. Note that the script is tested with 'drgn v0.0.22'. Signed-off-by: SeongJae Park --- .../selftests/damon/drgn_dump_damon_status.py | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100755 tools/testing/selftests/damon/drgn_dump_damon_status.py diff --git a/tools/testing/selftests/damon/drgn_dump_damon_status.py b/tools/testing/selftests/damon/drgn_dump_damon_status.py new file mode 100755 index 000000000000..333a0d0c4bff --- /dev/null +++ b/tools/testing/selftests/damon/drgn_dump_damon_status.py @@ -0,0 +1,161 @@ +#!/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 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], + ]) + +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 scheme_to_dict(scheme): + return 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], + ]) + +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, [ + ['attrs', attrs_to_dict], + ['adaptive_targets', targets_to_list], + ['schemes', schemes_to_list], + ]) + +def main(): + if len(sys.argv) < 3: + print('Usage: %s ' % 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() -- 2.39.5