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 E2359C7115D for ; Sun, 22 Jun 2025 21:03:39 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 155F66B007B; Sun, 22 Jun 2025 17:03:39 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 0DFB96B0099; Sun, 22 Jun 2025 17:03:39 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 01C046B00AA; Sun, 22 Jun 2025 17:03:38 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id E5B016B007B for ; Sun, 22 Jun 2025 17:03:38 -0400 (EDT) Received: from smtpin22.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 6A4A2121C02 for ; Sun, 22 Jun 2025 21:03:38 +0000 (UTC) X-FDA: 83584262916.22.2BDC1D2 Received: from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254]) by imf04.hostedemail.com (Postfix) with ESMTP id CF9A840010 for ; Sun, 22 Jun 2025 21:03:36 +0000 (UTC) Authentication-Results: imf04.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=qeidBmbx; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf04.hostedemail.com: domain of sj@kernel.org designates 172.105.4.254 as permitted sender) smtp.mailfrom=sj@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1750626216; a=rsa-sha256; cv=none; b=QNDTgBzmWGrscGQPx99Ykn6l/4PVrgt6jPEem+kbasZX2V0yy1Eowz9hfHwUSw9evGAXCA e4FvqkfniI5g752XMQTBDaTuO4LOxjJnbz+J7Qa1GsNj/Jj+wFZmcLas6EoTvCaYqiIM4C XI/um6KsdWq5EJWFZRWbSiuYPOYPjoU= ARC-Authentication-Results: i=1; imf04.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=qeidBmbx; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf04.hostedemail.com: domain of sj@kernel.org designates 172.105.4.254 as permitted sender) smtp.mailfrom=sj@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1750626216; 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=oDRsxiD1r5C5Gz08ihZwpcd5teVkte1c6L+1N3xM89sWRbDfjdoA4SVj9K6M5aukS7aDSA v/fXbH4GJo+/uiuGDMnY/NEILcmjzZ98mMkJUH9cUTsBJQTF59OfRViXHXCDDmIkkBZ49z Jj9D4ETiVx2Oo5s3CSL3kgO5V3pvZ48= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 1BD0F61152; Sun, 22 Jun 2025 21:03:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 92A51C4CEE3; Sun, 22 Jun 2025 21:03:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750626215; bh=LQYj+y4NHRcCBylThRwztooldZRKZFHtpfiwZ2j/m2o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qeidBmbxkU6ngF7IBtFVu+zih2sxcShx+26Ils18iTjjo3npHIk8HmWLSrAod6gSV qLvYEF7/ME/PMIqWbWeYPkCpXjnBlZi1lQiA8lpj8f7ZbGpoySZfprOuVjfo/to63d GLIyKZZMTU+NwnwXouQCAw07vzo90OLAvtzdYCsTgF18tj13yf3H+bUH6KbZHdsYIt YV1crGBjVPxVHSrNWcEE/bLFKLiLbRNuLtmQBqxdqfwP0346HCVNL5x3qEWnrrI91o G6xKbqLroOpTioNGy8+meoe3rkSJmqwYWhxO9AM10wvKeU+nyYmroaaR000kOKX33q bd5dQ9/O1UyFg== From: SeongJae Park To: Cc: SeongJae Park , Andrew Morton , 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: [RFC PATCH 1/6] selftests/damon: add drgn script for extracting damon status Date: Sun, 22 Jun 2025 14:03:25 -0700 Message-Id: <20250622210330.40490-2-sj@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250622210330.40490-1-sj@kernel.org> References: <20250622210330.40490-1-sj@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspam-User: X-Rspamd-Server: rspam01 X-Rspamd-Queue-Id: CF9A840010 X-Stat-Signature: 1frfbwzpazkpaq8htfqpf3cms8njxr3x X-HE-Tag: 1750626216-758228 X-HE-Meta: U2FsdGVkX1+nX4BhLrKrvKCWYWbCmqjFRBUFT/od/tPfyvQxh9x0AggUCfxHbCJhJKVVO5dXpgYTJA9MURTrg0Usb4p2ZZygs/LAiqzzDClaaTMrpJR0L6M8Lr9dR3MZCXaVZzlKNnP5y6BSRwMRTOHsHOy+Difd26QNkQylkaMSTZuy6VpKx/NG4/hEF7C2UYQ5AjGEK9UnlRCuZ/8ZYyKUoZoHU6wx7Fx+nBlUVmQAy/TOGUpy3nJ/yJ9nUc3XLVvoT8Z4VsN4gcuP7GCk2rUtjbRHrNAthHS9cWhNk668OEgt8DwBIPJoxsCiaySdH3ypjApr30uGPwQOKQJmnBg68P/5BEepzNXs6cj8YyeI6KZmBZ7VqR64Gi93My5iyCpOHzIfSQUVACBFZh0p9N3FhIKyONiKfGA0E1deihmmgE0j9Iu3lVL9/IgCqPul6PzgdtcNm4nrrGdD2y0ymCbL3i/92YuKZz17nl0P00XKcUrDy8WmdS91TPAcenANpnZeVKPnYeLBwgnJITu4W4AgtDbNTAH3C53FDLiHSo/Fw+DO2r/kdzecEfKeVZvs4qiRHoGIW+8NTZ3qCk3VR99A4ySGkkpCrYGBADC2+Q/KpbRcTMqzWcrRcP84gF0dN3Q00FwHEpYDNiJM4QHvkXRmaUUaOIdU67YiivTGb/br2K+5u2CPo6CnOxuEB2Q1orDox9bEVljwyQohzySofeGBw6c4Ea8LMVhjpR6N+zpsWEyXiY0bf8qMTDXbAQlTpXfFFNL5tEIVVUxDAAZtabxEr0rU3HXvf33bluwoXVHoF0+2v2ld1Pz3L6rVG6MWS0mdQQZCz08O8JYNYXjAMAyQfMM2usK9qBo/bOJNfifhK6GyzgaJah313lIo4VEvHha36sswpOrU1lj4DepGa5TFcZwZi6sw4XPIL555Cq7d4wviiDhXbOPEsg4JCdj+jp6nFj116KttjVzOVcI yx0wrvER haZxauE4VPFmtVTVhb8GZnOlCgQa2GWxiKyNEsIqwhWpnWyEF8qSgs1XF+9jIEAVi//gyvD+qOWVKe1Mer4Ca8vqBLHgrUXRQsomL7lrY2icoYNVq/QHINTKNuQaHZ0hRFCDdGe6P4Gj5Lmipg1qIxo67d6nIr2IXy6mKFMrP4y4OlxYqomWlKgDW9hB7npsxhJbGlMUPUvjtEO+7UBgqxLxFMY0ODvF2Yt0UEjv1VzAgTBU= 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