From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f47.google.com (mail-pj1-f47.google.com [209.85.216.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5AC183E4510 for ; Tue, 18 Aug 2026 06:11:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.47 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787033466; cv=none; b=F+p+2eN/Y81FNlsay34vqPN4iTs6O73yZqnSUScJvja6UqXThLHHhO5hDMfQm/nFdmfi09S6u4Mzj9Fah7EsOqhmKQWfgHMXpEA3x/JFUsjNmpsKSKlVCVRdJhDwI4xPYl9mzW8dl0hg1ljLXGKpG2RCmUoNn5rg8YI790ug4hM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787033466; c=relaxed/simple; bh=mZKFwQauANDJ1gHu+gg8RedjLenlA7e9YJ8y+FF2WoU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=k9nbFaom3XMUrwmOGG7zqvPgTBLFm4OOqYXABtGCzttJjIzDm28a+C8ZycGL4xcANtK5Z0zsvUpjmmbh83sFA6krXSaDubLfcFF05TFy40EbDQuWhyJXf1BBrv6zP0ZAU1E0mKx0+UeaDJGwDPLAUQ/r8KuPnGQIfsNlb2i40cE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=M/fDfup6; arc=none smtp.client-ip=209.85.216.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="M/fDfup6" Received: by mail-pj1-f47.google.com with SMTP id 98e67ed59e1d1-38a0c7e841fso5492049a91.2 for ; Mon, 17 Aug 2026 23:11:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787033465; x=1787638265; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=PFTkBKzl9DDztkv9Ak+eApuO538I5zXX6YMBdyPiC24=; b=M/fDfup6yb5Ul3kWAVU5gN/854XlbjmxUj/vwLrIZ/S0C1NeLvdSG80xWbO6Vz0oAC SjoR9flU7n/TN2phwHYB3lACBPlM3KS3Kwev4+lfpmlez+vZPg1853ZJryEaNh2qLltf A1+pINquqFwjaLEEBDpmUN5/I5Zb95kZKnf4WYurJwed3qc6tgpBLgTl/bTf3UuBqR+m L1MB8cvYYpS9d5uw8sUBX06r2Ky8Bl0lU8YLaoLgnrxo4cNk4M7dj78BTZaIcOqix4Wu bwh2x6a4VZhD/qVfxBLtV1Kms88fiLPgUqmY0tGoF1tql9JFxo4nykvptKvMXs8i6rry BiIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787033465; x=1787638265; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=PFTkBKzl9DDztkv9Ak+eApuO538I5zXX6YMBdyPiC24=; b=KEtO4LVrO2C17db4wFDNvBsw2Kfq2L33q2vHJOb0JOAegAmY3WM2XhmC/sUViAu7pI Ehi+/lIDNY+HSdpM7+3sGtgNrR2Tf31M5tLPGo/bTIVOjQhLl7ZmZYFNDLuV25NUKA8W OjnAJd1A81QfQITRzRdJL5pYUBwCDPx8pfJTphY3OoEZV6LA2VHa5GiXI9jo1fCMf1f+ e3qA6WE/sfFrN81K0+HbGfNw5gsLTNvsZck2U6lcgW++DbPJOrnkUF4x59RkMiuT2mYe 4aaj6mtS8KbSnNJPIfN4UeYFSscXMZ44z4YLfov0EWVoIEm2LRd/4vAAJJHyZ58WMKU7 3vkg== X-Forwarded-Encrypted: i=1; AHgh+Rpkh3a/SB4Ss3XnhazIhYpZ4f3O+8DDaUYgBa0MxPT/TtmaykZ1pUR9HoeuCTZYmjxbCDXrIE0TUFdWYtI=@vger.kernel.org X-Gm-Message-State: AOJu0YxZteIJMbK1caFU6CPipxmKACqWZNblyByjzQRJArk8yFsL7KHn LtFud/1A+jVW1wAFARtpufXkTm0hhtQGrw29zVDsCeFABCrXSgtEwllK X-Gm-Gg: AR+sD13Dq2OpK0DeMgG9tC+B5G7XkQ1fPH03vz/w59n7F/YsOHk0QHypIy3pARrzAEW WTwF8y7IXT9ZAiuY7BgjKGkzmwjcFi1kG9gHmAcLRi9545Vub30Ro7U54yRdAKBf7JfaW7Ua55m kDaxBrNiwYyM42EOd5wKtXeRnJIymLTHkHyOt/MWTmmAqozOK+phUS6CaFilUKWlbS0SnwzKOhP pjq83N2Jyr6YNG/ZJLLrY0dBmCRwlFNNFBCzmihzDRwMZAdsofYWwXdeqmgsoH6ntorqz5v8YPT VargYnBad2qVkFI76LBuUzLY2wdVUNbpo/Ka91ioTpe4o2IN5bkp035XxRogy04xKmfT1rI6CZl A+wNfD2UJ8Mv1d5znve+O58gqNywf25S4sj9Pz8FhP8oGwJCDsjPblJD13KDRpMfc08+ptsCPT/ VmroM/aNELpVR/ILTRpVYrTXd00BMWPuKhc+cv3rBh4ivx9ubD518FseDNiT/cRWoSI7wPGZm4T bU/lIE= X-Received: by 2002:a17:90a:ec83:b0:381:e74f:8a6a with SMTP id 98e67ed59e1d1-3933b8c1041mr33609337a91.16.1787033464444; Mon, 17 Aug 2026 23:11:04 -0700 (PDT) Received: from kernel.tail6741c6.ts.net ([116.128.244.169]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3954d38bf94sm4633942a91.9.2026.08.17.23.10.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Aug 2026 23:11:04 -0700 (PDT) From: Kunwu Chan X-Google-Original-From: Kunwu Chan To: sj@kernel.org, akpm@linux-foundation.org Cc: damon@lists.linux.dev, linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, rostedt@goodmis.org, mhiramat@kernel.org, mathieu.desnoyers@efficios.com, shuah@kernel.org, lianux.mm@gmail.com, Kunwu Chan Subject: [RFC PATCH 3/7] mm/damon/perf: add debugfs statistics interface Date: Tue, 18 Aug 2026 14:10:27 +0800 Message-ID: <20260818061031.827057-4-kunwu.chan@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260818061031.827057-1-kunwu.chan@linux.dev> References: <20260818061031.827057-1-kunwu.chan@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Lian Wang Expose the aggregated per-CPU counters and the global event-stage in a debug-only debugfs perf_stats file. The format is explicitly unstable; tracepoints are the stable diagnostic interface. Co-developed-by: Kunwu Chan Signed-off-by: Kunwu Chan Signed-off-by: Lian Wang --- mm/damon/perf/Makefile | 2 +- mm/damon/perf/debugfs.c | 142 ++++++++++++++++++++++++++++++++++++++++ mm/damon/perf/stats.c | 2 +- 3 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 mm/damon/perf/debugfs.c diff --git a/mm/damon/perf/Makefile b/mm/damon/perf/Makefile index 5c46d3da7ef8..150cbaa875fa 100644 --- a/mm/damon/perf/Makefile +++ b/mm/damon/perf/Makefile @@ -2,4 +2,4 @@ # Observability: per-CPU counters, tracepoints, debugfs perf_stats obj-$(CONFIG_DAMON_PERF_OBSERVE) += damon-perf.o -damon-perf-objs := stats.o +damon-perf-objs := stats.o debugfs.o diff --git a/mm/damon/perf/debugfs.c b/mm/damon/perf/debugfs.c new file mode 100644 index 000000000000..c54dd7644ac3 --- /dev/null +++ b/mm/damon/perf/debugfs.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * DAMON Perf Observability — debugfs Interface + * + * Exposes one file under /sys/kernel/debug/damon/: + * + * perf_stats — per-CPU pipeline statistics in tabular form + * + * DEBUG ONLY — format may change without notice; do not parse in + * scripts. For stable diagnostics, use the tracepoints under + * /sys/kernel/debug/tracing/events/damon/ + */ + +#include +#include +#include +#include + +#include "perf.h" + +static struct dentry *damon_debugfs_dir; + +/* + * perf_stats + */ + +static const char *state_name(int s) +{ + switch (s) { + case DAMON_PERF_STATE_UNINIT: return "UNINIT"; + case DAMON_PERF_STATE_CREATED: return "CREATED"; + case DAMON_PERF_STATE_BOUND: return "BOUND"; + case DAMON_PERF_STATE_ENABLED: return "ENABLED"; + case DAMON_PERF_STATE_RUNNING: return "RUNNING"; + case DAMON_PERF_STATE_ERROR: return "ERROR"; + default: return "?"; + } +} + +static int perf_stats_show(struct seq_file *m, void *v) +{ + struct damon_perf_stats agg, st; + int cpu; + bool first = true; + + damon_perf_stats_aggregate(&agg); + + seq_puts(m, " -------------- ----------\n"); + seq_puts(m, " Counter Value\n"); + seq_puts(m, " -------------- ----------\n"); + +#define STAT_ROW(label, field) \ + seq_printf(m, " %-12s %8llu\n", label, agg.field) + + STAT_ROW("callback", callback); + STAT_ROW("valid", sample_valid); + STAT_ROW("null", sample_null); + STAT_ROW("addr_zero", sample_addr_zero); + STAT_ROW("kernel", sample_kernel); + STAT_ROW("inv_phys", sample_invalid_phys); + STAT_ROW("enqueue", enqueue); + STAT_ROW("dequeue", dequeue); + STAT_ROW("overflow", overflow); + STAT_ROW("ring_peak", ring_peak); + STAT_ROW("match", match); + STAT_ROW("miss_tgid", miss_tgid); + STAT_ROW("miss_region", miss_region); + STAT_ROW("miss_bound", miss_boundary); + STAT_ROW("update", update); + +#undef STAT_ROW + + seq_puts(m, " -------------- ----------\n\n"); + + /* Per-CPU breakdown */ + cpus_read_lock(); + for_each_online_cpu(cpu) { + damon_perf_stats_snapshot(cpu, &st); + + /* Skip truly idle CPUs */ + if (st.cpu_state == DAMON_PERF_STATE_UNINIT && + !st.callback && !st.enqueue && !st.dequeue) + continue; + + if (first) { + seq_puts(m, " Per-CPU (non-zero / non-UNINIT):\n"); + first = false; + } + + seq_printf(m, " CPU%02d: st=%-7s cb=%llu enq=%llu deq=%llu ovf=%llu match=%llu tgid=%llu noreg=%llu bound=%llu upd=%llu\n", + cpu, state_name(st.cpu_state), + st.callback, st.enqueue, st.dequeue, + st.overflow, st.match, + st.miss_tgid, st.miss_region, st.miss_boundary, + st.update); + } + cpus_read_unlock(); + + return 0; +} + +static int perf_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, perf_stats_show, NULL); +} + +static const struct file_operations perf_stats_fops = { + .open = perf_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * Init / teardown + */ + +int damon_perf_debugfs_init(void) +{ + if (!debugfs_initialized()) + return -ENODEV; + + /* + * Create the "damon" directory first. debugfs_create_dir() mounts + * debugfs via simple_pin_fs() before touching debugfs_mount, so it + * is safe to call during initcall time -- unlike debugfs_lookup(), + * which dereferences debugfs_mount unconditionally and crashes with + * a NULL mount. If the directory already exists (created by another + * DAMON interface) debugfs_create_dir() returns -EEXIST; fall back + * to debugfs_lookup(), which is now safe because the mount exists. + */ + damon_debugfs_dir = debugfs_create_dir("damon", NULL); + if (damon_debugfs_dir == ERR_PTR(-EEXIST)) + damon_debugfs_dir = debugfs_lookup("damon", NULL); + if (IS_ERR(damon_debugfs_dir)) + return PTR_ERR(damon_debugfs_dir); + + debugfs_create_file("perf_stats", 0400, damon_debugfs_dir, + NULL, &perf_stats_fops); + + return 0; +} diff --git a/mm/damon/perf/stats.c b/mm/damon/perf/stats.c index a869f115bb26..ae5b0037a31d 100644 --- a/mm/damon/perf/stats.c +++ b/mm/damon/perf/stats.c @@ -291,5 +291,5 @@ void damon_perf_stats_aggregate(struct damon_perf_stats *dst) int damon_perf_framework_init(void) { - return 0; + return damon_perf_debugfs_init(); } -- 2.43.0