From: Akinobu Mita <akinobu.mita@gmail.com>
To: damon@lists.linux.dev
Cc: linux-perf-users@vger.kernel.org, sj@kernel.org, akinobu.mita@gmail.com
Subject: [RFC PATCH v3 1/4] mm/damon/core: add code borrowed from report-based monitoring work
Date: Thu, 23 Apr 2026 09:42:07 +0900 [thread overview]
Message-ID: <20260423004211.7037-2-akinobu.mita@gmail.com> (raw)
In-Reply-To: <20260423004211.7037-1-akinobu.mita@gmail.com>
The perf event-based monitoring will be implemented on top of the
report-based monitoring infrastructure, but since the migration is
still in progress, only borrow the following necessary code for now.
* struct damon_access_report
* access_reported field in struct damon_region
* sample/primitives/ sysfs directory
[1] https://lore.kernel.org/linux-mm/20251208062943.68824-6-sj@kernel.org/T/
---
include/linux/damon.h | 68 ++++++
mm/damon/core.c | 1 +
mm/damon/sysfs.c | 499 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 568 insertions(+)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index f2cdb7c3f5e6..9ba26d8a0bce 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -85,6 +85,7 @@ struct damon_region {
unsigned int age;
/* private: Internal value for age calculation. */
unsigned int last_nr_accesses;
+ bool access_reported;
};
/**
@@ -112,6 +113,30 @@ struct damon_target {
bool obsolete;
};
+/**
+ * struct damon_access_report - Represent single access report information.
+ * @paddr: Start physical address of the accessed address range.
+ * @vaddr: Start virtual address of the accessed address range.
+ * @size: The size of the accessed address range.
+ * @cpu: The id of the CPU that made the access.
+ * @tid: The task id of the task that made the access.
+ * @is_write: Whether the access is write.
+ *
+ * Any DAMON API callers that notified access events can report the information
+ * to DAMON using damon_report_access(). This struct contains the reporting
+ * information. Refer to damon_report_access() for more details.
+ */
+struct damon_access_report {
+ unsigned long paddr;
+ unsigned long vaddr;
+ unsigned long size;
+ unsigned int cpu;
+ pid_t tid;
+ bool is_write;
+/* private: */
+ unsigned long report_jiffies; /* when this report is made */
+};
+
/**
* enum damos_action - Represents an action of a Data Access Monitoring-based
* Operation Scheme.
@@ -763,6 +788,49 @@ struct damon_attrs {
unsigned long aggr_samples;
};
+/**
+ * enum damon_sample_filter_type - Type of &struct damon_sample_filter.
+ *
+ * @DAMON_FILTER_TYPE_CPUMASK: Filter by access-generated CPUs.
+ * @DAMON_FILTER_TYPE_THREADS: Filter by access-generated threads.
+ * @DAMON_FILTER_TYPE_WRITE: Filter by whether the access was for writing.
+ *
+ * Read &struct damon_sample_control for more details.
+ */
+enum damon_sample_filter_type {
+ DAMON_FILTER_TYPE_CPUMASK,
+ DAMON_FILTER_TYPE_THREADS,
+ DAMON_FILTER_TYPE_WRITE,
+};
+
+/**
+ * struct damon_sample_filter - &struct damon_access_report filter.
+ *
+ * @type: The type of this filter.
+ * @matching: Whether it is for condition-matching reports.
+ * @allow: Whether to include or excludie the @matching reports.
+ * @cpumask: Access-generated CPUs if @type is DAMON_FILTER_TYPE_CPUMASK.
+ * @tid_arr: Array of access-generated thread ids, if @type is
+ * DAMON_FILTER_TYPE_THREADS.
+ * @nr_tids: Size of @tid_arr, if @type is DAMON_FILTER_TYPE_THREADS.
+ * @list: List head for siblings.
+ *
+ * Read &struct damon_sample_control for more details.
+ */
+struct damon_sample_filter {
+ enum damon_sample_filter_type type;
+ bool matching;
+ bool allow;
+ union {
+ cpumask_t cpumask;
+ struct {
+ pid_t *tid_arr;
+ int nr_tids;
+ };
+ };
+ struct list_head list;
+};
+
/**
* struct damon_ctx - Represents a context for each monitoring. This is the
* main interface that allows users to set the attributes and get the results
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 3dbbbfdeff71..a52b2962aa22 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -142,6 +142,7 @@ struct damon_region *damon_new_region(unsigned long start, unsigned long end)
region->age = 0;
region->last_nr_accesses = 0;
+ region->access_reported = false;
return region;
}
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index eefa959aa30a..c19556f2af3b 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -747,6 +747,483 @@ static const struct kobj_type damon_sysfs_intervals_ktype = {
.default_groups = damon_sysfs_intervals_groups,
};
+/*
+ * access check report filter directory
+ */
+
+struct damon_sysfs_sample_filter {
+ struct kobject kobj;
+ enum damon_sample_filter_type type;
+ bool matching;
+ bool allow;
+ cpumask_t cpumask;
+};
+
+static struct damon_sysfs_sample_filter *damon_sysfs_sample_filter_alloc(void)
+{
+ return kzalloc(sizeof(struct damon_sysfs_sample_filter), GFP_KERNEL);
+}
+
+struct damon_sysfs_sample_filter_type_name {
+ enum damon_sample_filter_type type;
+ char *name;
+};
+
+static const struct damon_sysfs_sample_filter_type_name
+damon_sysfs_sample_filter_type_names[] = {
+ {
+ .type = DAMON_FILTER_TYPE_CPUMASK,
+ .name = "cpumask",
+ },
+};
+
+static ssize_t type_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+ int i = 0;
+
+ for (; i < ARRAY_SIZE(damon_sysfs_sample_filter_type_names); i++) {
+ const struct damon_sysfs_sample_filter_type_name *type_name;
+
+ type_name = &damon_sysfs_sample_filter_type_names[i];
+ if (type_name->type == filter->type)
+ return sysfs_emit(buf, "%s\n", type_name->name);
+ }
+ return -EINVAL;
+}
+
+static ssize_t type_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+ ssize_t ret = -EINVAL;
+ int i = 0;
+
+ for (; i < ARRAY_SIZE(damon_sysfs_sample_filter_type_names); i++) {
+ const struct damon_sysfs_sample_filter_type_name *type_name;
+
+ type_name = &damon_sysfs_sample_filter_type_names[i];
+ if (sysfs_streq(buf, type_name->name)) {
+ filter->type = type_name->type;
+ ret = count;
+ break;
+ }
+ }
+ return ret;
+}
+
+static ssize_t matching_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+
+ return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
+}
+
+static ssize_t matching_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+ bool matching;
+ int err = kstrtobool(buf, &matching);
+
+ if (err)
+ return err;
+
+ filter->matching = matching;
+ return count;
+}
+
+static ssize_t allow_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+
+ return sysfs_emit(buf, "%c\n", filter->allow ? 'Y' : 'N');
+}
+
+static ssize_t allow_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+ bool allow;
+ int err = kstrtobool(buf, &allow);
+
+ if (err)
+ return err;
+
+ filter->allow = allow;
+ return count;
+}
+
+static ssize_t cpumask_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+
+ return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&filter->cpumask));
+}
+
+static ssize_t cpumask_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+ cpumask_t cpumask;
+ int err = cpulist_parse(buf, &cpumask);
+
+ if (err)
+ return err;
+ filter->cpumask = cpumask;
+ return count;
+}
+
+static void damon_sysfs_sample_filter_release(struct kobject *kobj)
+{
+ struct damon_sysfs_sample_filter *filter = container_of(kobj,
+ struct damon_sysfs_sample_filter, kobj);
+
+ kfree(filter);
+}
+
+static struct kobj_attribute damon_sysfs_sample_filter_type_attr =
+ __ATTR_RW_MODE(type, 0600);
+
+static struct kobj_attribute damon_sysfs_sample_filter_matching_attr =
+ __ATTR_RW_MODE(matching, 0600);
+
+static struct kobj_attribute damon_sysfs_sample_filter_allow_attr =
+ __ATTR_RW_MODE(allow, 0600);
+
+static struct kobj_attribute damon_sysfs_sample_filter_cpumask_attr =
+ __ATTR_RW_MODE(cpumask, 0600);
+
+static struct attribute *damon_sysfs_sample_filter_attrs[] = {
+ &damon_sysfs_sample_filter_type_attr.attr,
+ &damon_sysfs_sample_filter_matching_attr.attr,
+ &damon_sysfs_sample_filter_allow_attr.attr,
+ &damon_sysfs_sample_filter_cpumask_attr.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_sample_filter);
+
+static const struct kobj_type damon_sysfs_sample_filter_ktype = {
+ .release = damon_sysfs_sample_filter_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = damon_sysfs_sample_filter_groups,
+};
+
+/*
+ * access check report filters directory
+ */
+
+struct damon_sysfs_sample_filters {
+ struct kobject kobj;
+ struct damon_sysfs_sample_filter **filters_arr;
+ int nr;
+};
+
+static struct damon_sysfs_sample_filters *
+damon_sysfs_sample_filters_alloc(void)
+{
+ return kzalloc(sizeof(struct damon_sysfs_sample_filters), GFP_KERNEL);
+}
+
+static void damon_sysfs_sample_filters_rm_dirs(
+ struct damon_sysfs_sample_filters *filters)
+{
+ struct damon_sysfs_sample_filter **filters_arr = filters->filters_arr;
+ int i;
+
+ for (i = 0; i < filters->nr; i++)
+ kobject_put(&filters_arr[i]->kobj);
+ filters->nr = 0;
+ kfree(filters_arr);
+ filters->filters_arr = NULL;
+}
+
+static int damon_sysfs_sample_filters_add_dirs(
+ struct damon_sysfs_sample_filters *filters, int nr_filters)
+{
+ struct damon_sysfs_sample_filter **filters_arr, *filter;
+ int err, i;
+
+ damon_sysfs_sample_filters_rm_dirs(filters);
+ if (!nr_filters)
+ return 0;
+
+ filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
+ GFP_KERNEL | __GFP_NOWARN);
+ if (!filters_arr)
+ return -ENOMEM;
+ filters->filters_arr = filters_arr;
+
+ for (i = 0; i < nr_filters; i++) {
+ filter = damon_sysfs_sample_filter_alloc();
+ if (!filter) {
+ damon_sysfs_sample_filters_rm_dirs(filters);
+ return -ENOMEM;
+ }
+
+ err = kobject_init_and_add(&filter->kobj,
+ &damon_sysfs_sample_filter_ktype,
+ &filters->kobj, "%d", i);
+ if (err) {
+ kobject_put(&filter->kobj);
+ damon_sysfs_sample_filters_rm_dirs(filters);
+ return err;
+ }
+
+ filters_arr[i] = filter;
+ filters->nr++;
+ }
+ return 0;
+}
+
+static ssize_t nr_filters_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_sample_filters *filters = container_of(kobj,
+ struct damon_sysfs_sample_filters, kobj);
+
+ return sysfs_emit(buf, "%d\n", filters->nr);
+}
+
+static ssize_t nr_filters_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_sample_filters *filters;
+ int nr, err = kstrtoint(buf, 0, &nr);
+
+ if (err)
+ return err;
+ if (nr < 0)
+ return -EINVAL;
+
+ filters = container_of(kobj, struct damon_sysfs_sample_filters, kobj);
+
+ if (!mutex_trylock(&damon_sysfs_lock))
+ return -EBUSY;
+ err = damon_sysfs_sample_filters_add_dirs(filters, nr);
+ mutex_unlock(&damon_sysfs_lock);
+ if (err)
+ return err;
+
+ return count;
+}
+
+static void damon_sysfs_sample_filters_release(struct kobject *kobj)
+{
+ kfree(container_of(kobj, struct damon_sysfs_sample_filters, kobj));
+}
+
+static struct kobj_attribute damon_sysfs_sample_filters_nr_attr =
+ __ATTR_RW_MODE(nr_filters, 0600);
+
+static struct attribute *damon_sysfs_sample_filters_attrs[] = {
+ &damon_sysfs_sample_filters_nr_attr.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_sample_filters);
+
+static const struct kobj_type damon_sysfs_sample_filters_ktype = {
+ .release = damon_sysfs_sample_filters_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = damon_sysfs_sample_filters_groups,
+};
+
+/*
+ * access check primitives directory
+ */
+
+struct damon_sysfs_primitives {
+ struct kobject kobj;
+ bool page_table;
+ bool page_fault;
+};
+
+static struct damon_sysfs_primitives *damon_sysfs_primitives_alloc(
+ bool page_table, bool page_fault)
+{
+ struct damon_sysfs_primitives *primitives = kmalloc(
+ sizeof(*primitives), GFP_KERNEL);
+
+ if (!primitives)
+ return NULL;
+
+ primitives->kobj = (struct kobject){};
+ primitives->page_table = page_table;
+ primitives->page_fault = page_fault;
+ return primitives;
+}
+
+static ssize_t page_table_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_primitives *primitives = container_of(kobj,
+ struct damon_sysfs_primitives, kobj);
+
+ return sysfs_emit(buf, "%c\n", primitives->page_table ? 'Y' : 'N');
+}
+
+static ssize_t page_table_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_primitives *primitives = container_of(kobj,
+ struct damon_sysfs_primitives, kobj);
+ bool enable;
+ int err = kstrtobool(buf, &enable);
+
+ if (err)
+ return err;
+ primitives->page_table = enable;
+ return count;
+}
+
+static ssize_t page_fault_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_primitives *primitives = container_of(kobj,
+ struct damon_sysfs_primitives, kobj);
+
+ return sysfs_emit(buf, "%c\n", primitives->page_fault ? 'Y' : 'N');
+}
+
+static ssize_t page_fault_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_primitives *primitives = container_of(kobj,
+ struct damon_sysfs_primitives, kobj);
+ bool enable;
+ int err = kstrtobool(buf, &enable);
+
+ if (err)
+ return err;
+ primitives->page_fault = enable;
+ return count;
+}
+
+static void damon_sysfs_primitives_release(struct kobject *kobj)
+{
+ struct damon_sysfs_primitives *primitives = container_of(kobj,
+ struct damon_sysfs_primitives, kobj);
+
+ kfree(primitives);
+}
+
+static struct kobj_attribute damon_sysfs_primitives_page_table_attr =
+ __ATTR_RW_MODE(page_table, 0600);
+
+static struct kobj_attribute damon_sysfs_primitives_page_fault_attr =
+ __ATTR_RW_MODE(page_fault, 0600);
+
+static struct attribute *damon_sysfs_primitives_attrs[] = {
+ &damon_sysfs_primitives_page_table_attr.attr,
+ &damon_sysfs_primitives_page_fault_attr.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_primitives);
+
+static const struct kobj_type damon_sysfs_primitives_ktype = {
+ .release = damon_sysfs_primitives_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = damon_sysfs_primitives_groups,
+};
+
+/*
+ * sample directory
+ */
+
+struct damon_sysfs_sample {
+ struct kobject kobj;
+ struct damon_sysfs_primitives *primitives;
+ struct damon_sysfs_sample_filters *filters;
+};
+
+static struct damon_sysfs_sample *damon_sysfs_sample_alloc(void)
+{
+ struct damon_sysfs_sample *sample = kmalloc(
+ sizeof(*sample), GFP_KERNEL);
+
+ if (!sample)
+ return NULL;
+ sample->kobj = (struct kobject){};
+ return sample;
+}
+
+static int damon_sysfs_sample_add_dirs(
+ struct damon_sysfs_sample *sample)
+{
+ struct damon_sysfs_primitives *primitives;
+ struct damon_sysfs_sample_filters *filters;
+ int err;
+
+ primitives = damon_sysfs_primitives_alloc(true, false);
+ if (!primitives)
+ return -ENOMEM;
+ err = kobject_init_and_add(&primitives->kobj,
+ &damon_sysfs_primitives_ktype, &sample->kobj,
+ "primitives");
+ if (err)
+ goto put_primitives_out;
+ sample->primitives = primitives;
+
+ filters = damon_sysfs_sample_filters_alloc();
+ if (!filters) {
+ err = -ENOMEM;
+ goto put_primitives_out;
+ }
+ err = kobject_init_and_add(&filters->kobj,
+ &damon_sysfs_sample_filters_ktype, &sample->kobj,
+ "filters");
+ if (err)
+ goto put_filters_out;
+ sample->filters = filters;
+ return 0;
+put_filters_out:
+ kobject_put(&filters->kobj);
+ sample->filters = NULL;
+put_primitives_out:
+ kobject_put(&primitives->kobj);
+ sample->primitives = NULL;
+ return err;
+}
+
+static void damon_sysfs_sample_rm_dirs(
+ struct damon_sysfs_sample *sample)
+{
+ if (sample->primitives)
+ kobject_put(&sample->primitives->kobj);
+ if (sample->filters) {
+ damon_sysfs_sample_filters_rm_dirs(sample->filters);
+ kobject_put(&sample->filters->kobj);
+ }
+}
+
+static void damon_sysfs_sample_release(struct kobject *kobj)
+{
+ kfree(container_of(kobj, struct damon_sysfs_sample, kobj));
+}
+
+static struct attribute *damon_sysfs_sample_attrs[] = {
+ NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_sample);
+
+static const struct kobj_type damon_sysfs_sample_ktype = {
+ .release = damon_sysfs_sample_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = damon_sysfs_sample_groups,
+};
+
/*
* monitoring_attrs directory
*/
@@ -755,6 +1232,7 @@ struct damon_sysfs_attrs {
struct kobject kobj;
struct damon_sysfs_intervals *intervals;
struct damon_sysfs_ul_range *nr_regions_range;
+ struct damon_sysfs_sample *sample;
};
static struct damon_sysfs_attrs *damon_sysfs_attrs_alloc(void)
@@ -771,6 +1249,7 @@ static int damon_sysfs_attrs_add_dirs(struct damon_sysfs_attrs *attrs)
{
struct damon_sysfs_intervals *intervals;
struct damon_sysfs_ul_range *nr_regions_range;
+ struct damon_sysfs_sample *sample;
int err;
intervals = damon_sysfs_intervals_alloc(5000, 100000, 60000000);
@@ -799,8 +1278,26 @@ static int damon_sysfs_attrs_add_dirs(struct damon_sysfs_attrs *attrs)
if (err)
goto put_nr_regions_intervals_out;
attrs->nr_regions_range = nr_regions_range;
+
+ sample = damon_sysfs_sample_alloc();
+ if (!sample) {
+ err = -ENOMEM;
+ goto put_nr_regions_intervals_out;
+ }
+ err = kobject_init_and_add(&sample->kobj,
+ &damon_sysfs_sample_ktype, &attrs->kobj,
+ "sample");
+ if (err)
+ goto put_sample_out;
+ err = damon_sysfs_sample_add_dirs(sample);
+ if (err)
+ goto put_sample_out;
+ attrs->sample = sample;
return 0;
+put_sample_out:
+ kobject_put(&sample->kobj);
+ attrs->sample = NULL;
put_nr_regions_intervals_out:
kobject_put(&nr_regions_range->kobj);
attrs->nr_regions_range = NULL;
@@ -817,6 +1314,8 @@ static void damon_sysfs_attrs_rm_dirs(struct damon_sysfs_attrs *attrs)
kobject_put(&attrs->nr_regions_range->kobj);
damon_sysfs_intervals_rm_dirs(attrs->intervals);
kobject_put(&attrs->intervals->kobj);
+ damon_sysfs_sample_rm_dirs(attrs->sample);
+ kobject_put(&attrs->sample->kobj);
}
static void damon_sysfs_attrs_release(struct kobject *kobj)
--
2.43.0
next prev parent reply other threads:[~2026-04-23 0:43 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-23 0:42 [RFC PATCH v3 0/4] mm/damon: introduce perf event based access check Akinobu Mita
2026-04-23 0:42 ` Akinobu Mita [this message]
2026-04-23 1:21 ` [RFC PATCH v3 1/4] mm/damon/core: add code borrowed from report-based monitoring work sashiko-bot
2026-04-23 0:42 ` [RFC PATCH v3 2/4] mm/damon/core: add common code for perf event based access check Akinobu Mita
2026-04-23 1:58 ` sashiko-bot
2026-04-23 0:42 ` [RFC PATCH v3 3/4] mm/damon/vaddr: support " Akinobu Mita
2026-04-23 2:48 ` sashiko-bot
2026-04-23 0:42 ` [RFC PATCH v3 4/4] mm/damon/paddr: " Akinobu Mita
2026-04-23 3:22 ` sashiko-bot
2026-04-23 4:34 ` [RFC PATCH v3 0/4] mm/damon: introduce " SeongJae Park
2026-04-24 3:27 ` Akinobu Mita
2026-04-24 23:31 ` SeongJae Park
2026-04-25 12:33 ` Akinobu Mita
2026-04-25 15:33 ` SeongJae Park
2026-04-29 8:00 ` Namhyung Kim
2026-04-29 14:34 ` SeongJae Park
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260423004211.7037-2-akinobu.mita@gmail.com \
--to=akinobu.mita@gmail.com \
--cc=damon@lists.linux.dev \
--cc=linux-perf-users@vger.kernel.org \
--cc=sj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.