AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/07/26 18:53 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": [
    "DAMON_SYSFS",
    "DAMON_PADDR"
  ],
  "FocusSymbols": [
    "damon_new_prep",
    "damon_add_prep"
  ],
  "Reasoning": "The patch introduces a new feature to the DAMON subsystem, allowing users to configure probing preparation actions (e.g., `set_pgidle`) and a new filter type (`pgidle_unset`) via sysfs. This modifies the core DAMON logic and physical address monitoring operations, making it a functional change that is reachable from user space and worth fuzzing.",
  "WorthFuzzing": true
}

1/1 2026/07/26 18:53 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit dcab8f13145b36eaa5257ee42bf8c65ff9503420\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Sun Jul 26 18:53:55 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/Documentation/ABI/testing/sysfs-kernel-mm-damon b/Documentation/ABI/testing/sysfs-kernel-mm-damon\nindex e675a57145e36d..6d596fb7fa1ffa 100644\n--- a/Documentation/ABI/testing/sysfs-kernel-mm-damon\n+++ b/Documentation/ABI/testing/sysfs-kernel-mm-damon\n@@ -173,6 +173,19 @@ Contact:\tSJ Park \u003csj@kernel.org\u003e\n Description:\tWriting to and reading from this file sets and gets the\n \t\tper-probe attribute weight.\n \n+What:\t\t/sys/kernel/mm/damon/admin/kdamonds/\u003cK\u003e/contexts/\u003cC\u003e/monitoring_attrs/probes/\u003cP\u003e/preps/nr_preps\n+Date:\t\tJun 2026\n+Contact:\tSJ Park \u003csj@kernel.org\u003e\n+Description:\tWriting a number 'N' to this file creates the number of\n+\t\tdirectories for each DAMON probing preparation action named '0'\n+\t\tto 'N-1' under the preps/ directory.\n+\n+What:\t\t/sys/kernel/mm/damon/admin/kdamonds/\u003cK\u003e/contexts/\u003cC\u003e/monitoring_attrs/probes/\u003cP\u003e/prep/\u003cR\u003e/action\n+Date:\t\tJun 2026\n+Contact:\tSJ Park \u003csj@kernel.org\u003e\n+Description:\tWriting to and reading from this file sets and gets the probing\n+\t\tpreeparation action.\n+\n What:\t\t/sys/kernel/mm/damon/admin/kdamonds/\u003cK\u003e/contexts/\u003cC\u003e/monitoring_attrs/probes/\u003cP\u003e/filters/nr_filters\n Date:\t\tMay 2026\n Contact:\tSJ Park \u003csj@kernel.org\u003e\ndiff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst\nindex da5f9afd08aef8..1f5a39e1fc38da 100644\n--- a/Documentation/admin-guide/mm/damon/usage.rst\n+++ b/Documentation/admin-guide/mm/damon/usage.rst\n@@ -74,6 +74,9 @@ comma (\",\").\n     │ │ │ │ │ │ nr_regions/min,max\n     │ │ │ │ │ │ :ref:`probes \u003cdamon_usage_sysfs_probes\u003e`/nr_probes\n     │ │ │ │ │ │ │ 0/weight\n+    │ │ │ │ │ │ │ │ preps/nr_preps\n+    │ │ │ │ │ │ │ │ │ 0/prep_action\n+    │ │ │ │ │ │ │ │ │ ...\n     │ │ │ │ │ │ │ │ filters/nr_filters\n     │ │ │ │ │ │ │ │ │ 0/type,matching,allow,path\n     │ │ │ │ │ │ │ │ │ ...\n@@ -283,9 +286,18 @@ In the beginning, this directory has only one file, ``nr_probes``.  Writing a\n number (``N``) to the file creates the number of child directories named ``0``\n to ``N-1``.  Each directory represents each monitoring probe.\n \n-In each probe directory, one directory, ``filters`` exists.  The directory\n-contains files for installing filters for the probe, that is used to determine\n-the data attribute for the probe.\n+In each probe directory, two directories, ``preps`` and ``filters`` exists.\n+The directories contains files for installing probing preparation actions and\n+filters for the probe, that is used to determine the data attribute for the\n+probe.\n+\n+In the beginning, ``preps`` directory has only one file, ``nr_preps``.\n+Writiing a number (``N``) to the file creates the number of child directories\n+names ``0`` to ``N-1``.  Each directory represents each preparation action.\n+Each directory has one file, ``prep_action``.  The preparation action can be\n+selected by writing the name of the action to the ``prep_action`` file.  Refer\n+to the :ref:`design doc \u003cdamon_design_data_attrs_monitoring\u003e` for the list of\n+supported actions.\n \n Each probe directory also contains ``weight`` file.  Reading from and writing\n to the file gets and sets the :ref:`attributes-only monitoring\ndiff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst\nindex aed6cb1cf48310..06fffe5e37819e 100644\n--- a/Documentation/mm/damon/design.rst\n+++ b/Documentation/mm/damon/design.rst\n@@ -293,8 +293,14 @@ registration is made by specifying a probe per attribute.  Each of the probe\n specifies a rule to determine if a given memory region has the related\n attribute.  The rule is constructed with multiple filters.  The filters work\n same to :ref:`DAMOS filters \u003cdamon_design_damos_filters\u003e` except the supported\n-filter types.  Currently only ``anon`` and ``memcg`` filter types are supported\n-for data attributes monitoring.\n+filter types.  Currently below fitler types are supported.\n+\n+- ``anon``: Same to that for DAMOS filters.\n+- ``memcg``: Same to that for DAMOS filters.\n+- ``pgidle_unset``: Matches if the page for the memory is marked as not\n+  access-idle.\n+  Matches if the memory is not backed by pages that DAMON can idnetify\n+  idleness.\n \n If such probes are registered, DAMON executes the probes for each region's\n sampling memory when it does the access :ref:`sampling\n@@ -305,6 +311,13 @@ Users can therefore know how much of a given DAMON region has a specific data\n attribute by reading the per-region per-probe probe hits counter after each\n aggregation interval.\n \n+Users can optionally register probing preparation actions per probe.  If such\n+actions are registered, DAMON applies the actions to each region's sampling\n+memory before starting the next sampling interval.  Currently only one action,\n+``set_pgidle`` is supported.  The action marks the page for the probing target\n+memory as access-idle.  This can be useful to be used together with\n+``pgidle_unset`` probe filter.\n+\n This is a sampling based mechanism.  Hence, it is lightweight but the output\n may include some measurement errors.  The output should be used with good\n understanding of statistics.\ndiff --git a/include/linux/damon.h b/include/linux/damon.h\nindex 0c8b7ddef9abb3..fe2c6b56d1d530 100644\n--- a/include/linux/damon.h\n+++ b/include/linux/damon.h\n@@ -627,6 +627,7 @@ enum damon_ops_id {\n  * @update:\t\t\tUpdate operations-related data structures.\n  * @prepare_access_checks:\tPrepare next access check of target regions.\n  * @check_accesses:\t\tCheck the accesses to target regions.\n+ * @prep_probes:\t\tPrepare applying probes for each region.\n  * @apply_probes:\t\tApply probes for each region.\n  * @get_scheme_score:\t\tGet the score of a region for a scheme.\n  * @apply_scheme:\t\tApply a DAMON-based operation scheme.\n@@ -654,6 +655,8 @@ enum damon_ops_id {\n  * last preparation and update the number of observed accesses of each region.\n  * It should also return max number of observed accesses that made as a result\n  * of its update.  The value will be used for regions adjustment threshold.\n+ * @prep_probes should execute required \u0026struct damon_prep for next \u0026struct\n+ * damon_probe applications to each region.\n  * @apply_probes should apply the data attribute probes to each region and\n  * accordingly update the probe hits counter of the region.  It should also\n  * set \u0026damon_region-\u003esampling_addr of each region if ``set_samples`` is true.\n@@ -676,6 +679,7 @@ struct damon_operations {\n \tvoid (*update)(struct damon_ctx *context);\n \tvoid (*prepare_access_checks)(struct damon_ctx *context);\n \tunsigned int (*check_accesses)(struct damon_ctx *context);\n+\tvoid (*prep_probes)(struct damon_ctx *context, bool set_samples);\n \tunsigned int (*apply_probes)(struct damon_ctx *context,\n \t\t\tbool set_samples, bool return_max_wsum);\n \tint (*get_scheme_score)(struct damon_ctx *context,\n@@ -739,15 +743,38 @@ struct damon_intervals_goal {\n \tunsigned long max_sample_us;\n };\n \n+/**\n+ * enum damon_prep_action - DAMON probing preparation action.\n+ *\n+ * @DAMON_PREP_SET_PGIDLE:\tSet the probing memory as idle page.\n+ */\n+enum damon_prep_action {\n+\tDAMON_PREP_SET_PGIDLE,\n+};\n+\n+/**\n+ * struct damon_prep - DAMON probing preparation request.\n+ *\n+ * @action:\tAction to do to the probing memory for the preparation.\n+ */\n+struct damon_prep {\n+\tenum damon_prep_action action;\n+/* private: */\n+\t/* siblings list. */\n+\tstruct list_head list;\n+};\n+\n /**\n  * enum damon_filter_type - Type of \u0026struct damon_filter\n  *\n- * @DAMON_FILTER_TYPE_ANON:\tAnonymous pages.\n- * @DAMON_FILTER_TYPE_MEMCG:\tSpecific memcg's pages.\n+ * @DAMON_FILTER_TYPE_ANON:\t\tAnonymous pages.\n+ * @DAMON_FILTER_TYPE_MEMCG:\t\tSpecific memcg's pages.\n+ * @DAMON_FILTER_TYPE_PGIDLE_UNSET:\tPgidle is unset.\n  */\n enum damon_filter_type {\n \tDAMON_FILTER_TYPE_ANON,\n \tDAMON_FILTER_TYPE_MEMCG,\n+\tDAMON_FILTER_TYPE_PGIDLE_UNSET,\n };\n \n /**\n@@ -778,6 +805,8 @@ struct damon_filter {\n struct damon_probe {\n \tunsigned int weight;\n /* private: */\n+\t/* Preparation actions to apply to each probing memory. */\n+\tstruct list_head preps;\n \t/* Filters for assessing if a given region is for this probe. */\n \tstruct list_head filters;\n \t/* Siblings list. */\n@@ -957,6 +986,12 @@ static inline unsigned long damon_sz_region(struct damon_region *r)\n \treturn r-\u003ear.end - r-\u003ear.start;\n }\n \n+#define damon_for_each_prep(p, prep) \\\n+\tlist_for_each_entry(p, \u0026(prep)-\u003epreps, list)\n+\n+#define damon_for_each_prep_safe(p, next, prep) \\\n+\tlist_for_each_entry_safe(p, next, \u0026(prep)-\u003epreps, list)\n+\n #define damon_for_each_filter(f, p) \\\n \tlist_for_each_entry(f, \u0026(p)-\u003efilters, list)\n \n@@ -1010,6 +1045,9 @@ static inline unsigned long damon_sz_region(struct damon_region *r)\n \n #ifdef CONFIG_DAMON\n \n+struct damon_prep *damon_new_prep(enum damon_prep_action action);\n+void damon_add_prep(struct damon_probe *p, struct damon_prep *prep);\n+\n struct damon_filter *damon_new_filter(enum damon_filter_type type,\n \t\tbool matching, bool allow);\n void damon_add_filter(struct damon_probe *probe, struct damon_filter *f);\ndiff --git a/mm/damon/core.c b/mm/damon/core.c\nindex 644daf5a165606..d5b1e0b5851a1a 100644\n--- a/mm/damon/core.c\n+++ b/mm/damon/core.c\n@@ -111,6 +111,63 @@ int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id)\n \treturn err;\n }\n \n+struct damon_prep *damon_new_prep(enum damon_prep_action action)\n+{\n+\tstruct damon_prep *prep;\n+\n+\tprep = kmalloc_obj(*prep);\n+\tif (!prep)\n+\t\treturn NULL;\n+\tprep-\u003eaction = action;\n+\tINIT_LIST_HEAD(\u0026prep-\u003elist);\n+\treturn prep;\n+}\n+\n+void damon_add_prep(struct damon_probe *p, struct damon_prep *prep)\n+{\n+\tlist_add_tail(\u0026prep-\u003elist, \u0026p-\u003epreps);\n+}\n+\n+static void damon_del_prep(struct damon_prep *p)\n+{\n+\tlist_del(\u0026p-\u003elist);\n+}\n+\n+static void damon_free_prep(struct damon_prep *p)\n+{\n+\tkfree(p);\n+}\n+\n+static void damon_destroy_prep(struct damon_prep *p)\n+{\n+\tdamon_del_prep(p);\n+\tdamon_free_prep(p);\n+}\n+\n+static struct damon_prep *damon_nth_prep(int n, struct damon_probe *p)\n+{\n+\tstruct damon_prep *prep;\n+\tint i = 0;\n+\n+\tdamon_for_each_prep(prep, p) {\n+\t\tif (i++ == n)\n+\t\t\treturn prep;\n+\t}\n+\treturn NULL;\n+}\n+\n+static bool damon_has_prep(struct damon_ctx *c)\n+{\n+\tstruct damon_prep *prep;\n+\tstruct damon_probe *probe;\n+\n+\tdamon_for_each_probe(probe, c) {\n+\t\tdamon_for_each_prep(prep, probe)\n+\t\t\treturn true;\n+\t}\n+\treturn false;\n+}\n+\n struct damon_filter *damon_new_filter(enum damon_filter_type type,\n \t\tbool matching, bool allow)\n {\n@@ -167,6 +224,7 @@ struct damon_probe *damon_new_probe(void)\n \tif (!p)\n \t\treturn NULL;\n \tp-\u003eweight = 0;\n+\tINIT_LIST_HEAD(\u0026p-\u003epreps);\n \tINIT_LIST_HEAD(\u0026p-\u003efilters);\n \tINIT_LIST_HEAD(\u0026p-\u003elist);\n \treturn p;\n@@ -184,8 +242,11 @@ static void damon_del_probe(struct damon_probe *p)\n \n static void damon_free_probe(struct damon_probe *p)\n {\n+\tstruct damon_prep *prep, *prep_next;\n \tstruct damon_filter *f, *next;\n \n+\tdamon_for_each_prep_safe(prep, prep_next, p)\n+\t\tdamon_free_prep(prep);\n \tdamon_for_each_filter_safe(f, next, p)\n \t\tdamon_free_filter(f);\n \tkfree(p);\n@@ -1666,6 +1727,36 @@ static int damon_commit_targets(\n \treturn err;\n }\n \n+static void damon_commit_prep(struct damon_prep *dst, struct damon_prep *src)\n+{\n+\tdst-\u003eaction = src-\u003eaction;\n+}\n+\n+static int damon_commit_preps(struct damon_probe *dst, struct damon_probe *src)\n+{\n+\tstruct damon_prep *dst_prep, *next, *src_prep, *new_prep;\n+\tint i = 0, j = 0;\n+\n+\tdamon_for_each_prep_safe(dst_prep, next, dst) {\n+\t\tsrc_prep = damon_nth_prep(i++, src);\n+\t\tif (src_prep)\n+\t\t\tdamon_commit_prep(dst_prep, src_prep);\n+\t\telse\n+\t\t\tdamon_destroy_prep(dst_prep);\n+\t}\n+\n+\tdamon_for_each_prep_safe(src_prep, next, src) {\n+\t\tif (j++ \u003c i)\n+\t\t\tcontinue;\n+\n+\t\tnew_prep = damon_new_prep(src_prep-\u003eaction);\n+\t\tif (!new_prep)\n+\t\t\treturn -ENOMEM;\n+\t\tdamon_add_prep(dst, new_prep);\n+\t}\n+\treturn 0;\n+}\n+\n static void damon_commit_filter(struct damon_filter *dst,\n \t\tstruct damon_filter *src)\n {\n@@ -1724,6 +1815,9 @@ static int damon_commit_probes(struct damon_ctx *dst, struct damon_ctx *src)\n \t\tsrc_probe = damon_nth_probe(i++, src);\n \t\tif (src_probe) {\n \t\t\tdst_probe-\u003eweight = src_probe-\u003eweight;\n+\t\t\terr = damon_commit_preps(dst_probe, src_probe);\n+\t\t\tif (err)\n+\t\t\t\treturn err;\n \t\t\terr = damon_commit_filters(dst_probe, src_probe);\n \t\t\tif (err)\n \t\t\t\treturn err;\n@@ -1741,6 +1835,9 @@ static int damon_commit_probes(struct damon_ctx *dst, struct damon_ctx *src)\n \t\t\treturn -ENOMEM;\n \t\tdamon_add_probe(dst, new_probe);\n \t\tnew_probe-\u003eweight = src_probe-\u003eweight;\n+\t\terr = damon_commit_preps(new_probe, src_probe);\n+\t\tif (err)\n+\t\t\treturn err;\n \t\terr = damon_commit_filters(new_probe, src_probe);\n \t\tif (err)\n \t\t\treturn err;\n@@ -3785,6 +3882,7 @@ static int kdamond_fn(void *data)\n \t\tunsigned long next_ops_update_sis = ctx-\u003enext_ops_update_sis;\n \t\tunsigned long sample_interval = ctx-\u003eattrs.sample_interval;\n \t\tbool access_check_disabled = damon_has_probe_weights(ctx);\n+\t\tbool has_prep = damon_has_prep(ctx);\n \t\tunsigned int max_merge_score = 0, max_wsum;\n \t\tbool get_max_wsum;\n \n@@ -3793,6 +3891,8 @@ static int kdamond_fn(void *data)\n \n \t\tif (!access_check_disabled \u0026\u0026 ctx-\u003eops.prepare_access_checks)\n \t\t\tctx-\u003eops.prepare_access_checks(ctx);\n+\t\tif (ctx-\u003eops.prep_probes)\n+\t\t\tctx-\u003eops.prep_probes(ctx, has_prep);\n \n \t\tkdamond_usleep(sample_interval);\n \t\tctx-\u003epassed_sample_intervals++;\n@@ -3807,7 +3907,8 @@ static int kdamond_fn(void *data)\n \t\t\telse\n \t\t\t\tget_max_wsum = false;\n \t\t\tmax_wsum = ctx-\u003eops.apply_probes(ctx,\n-\t\t\t\t\taccess_check_disabled, get_max_wsum);\n+\t\t\t\t\taccess_check_disabled \u0026\u0026 !has_prep,\n+\t\t\t\t\tget_max_wsum);\n \t\t\tif (get_max_wsum)\n \t\t\t\tmax_merge_score = max_wsum;\n \t\t}\ndiff --git a/mm/damon/paddr.c b/mm/damon/paddr.c\nindex 5a6a78054784af..8d8fcd1369e568 100644\n--- a/mm/damon/paddr.c\n+++ b/mm/damon/paddr.c\n@@ -105,6 +105,40 @@ static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx)\n \treturn max_nr_accesses;\n }\n \n+static void damon_pa_prep_probes_region(struct damon_region *r,\n+\t\tstruct damon_probe *probe, struct damon_ctx *ctx)\n+{\n+\tstruct damon_prep *p;\n+\n+\tdamon_for_each_prep(p, probe) {\n+\t\tswitch (p-\u003eaction) {\n+\t\tcase DAMON_PREP_SET_PGIDLE:\n+\t\t\tdamon_pa_mkold(damon_pa_phys_addr(r-\u003esampling_addr,\n+\t\t\t\t\t\tctx-\u003eaddr_unit));\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n+static void damon_pa_prep_probes(struct damon_ctx *ctx, bool set_samples)\n+{\n+\tstruct damon_target *t;\n+\tstruct damon_region *r;\n+\tstruct damon_probe *p;\n+\n+\tdamon_for_each_target(t, ctx) {\n+\t\tdamon_for_each_region(r, t) {\n+\t\t\tif (set_samples)\n+\t\t\t\tr-\u003esampling_addr = damon_rand(ctx, r-\u003ear.start,\n+\t\t\t\t\t\tr-\u003ear.end);\n+\t\t\tdamon_for_each_probe(p, ctx)\n+\t\t\t\tdamon_pa_prep_probes_region(r, p, ctx);\n+\t\t}\n+\t}\n+}\n+\n static bool damon_pa_filter_match(struct damon_filter *filter,\n \t\tstruct folio *folio)\n {\n@@ -132,6 +166,12 @@ static bool damon_pa_filter_match(struct damon_filter *filter,\n \t\t\tmatched = filter-\u003ememcg_id == mem_cgroup_id(memcg);\n \t\trcu_read_unlock();\n \t\tbreak;\n+\tcase DAMON_FILTER_TYPE_PGIDLE_UNSET:\n+\t\tif (!folio)\n+\t\t\tmatched = false;\n+\t\telse\n+\t\t\tmatched = damon_folio_young(folio);\n+\t\tbreak;\n \tdefault:\n \t\tbreak;\n \t}\n@@ -440,6 +480,7 @@ static int __init damon_pa_initcall(void)\n \t\t.update = NULL,\n \t\t.prepare_access_checks = damon_pa_prepare_access_checks,\n \t\t.check_accesses = damon_pa_check_accesses,\n+\t\t.prep_probes = damon_pa_prep_probes,\n \t\t.apply_probes = damon_pa_apply_probes,\n \t\t.target_valid = NULL,\n \t\t.apply_scheme = damon_pa_apply_scheme,\ndiff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c\nindex e3858ffab4b227..d44d5bb9e8fbf8 100644\n--- a/mm/damon/sysfs.c\n+++ b/mm/damon/sysfs.c\n@@ -750,6 +750,219 @@ static const struct kobj_type damon_sysfs_intervals_ktype = {\n \t.default_groups = damon_sysfs_intervals_groups,\n };\n \n+/*\n+ * prep directory\n+ */\n+\n+struct damon_sysfs_prep {\n+\tstruct kobject kobj;\n+\tenum damon_prep_action action;\n+};\n+\n+static struct damon_sysfs_prep *damon_sysfs_prep_alloc(void)\n+{\n+\tstruct damon_sysfs_prep *prep;\n+\n+\tprep = kzalloc_obj(struct damon_sysfs_prep);\n+\tif (!prep)\n+\t\treturn prep;\n+\tprep-\u003eaction = DAMON_PREP_SET_PGIDLE;\n+\treturn prep;\n+}\n+\n+struct damon_sysfs_prep_action_name {\n+\tenum damon_prep_action action;\n+\tchar *name;\n+};\n+\n+static const struct damon_sysfs_prep_action_name\n+damon_sysfs_prep_action_names[] = {\n+\t{\n+\t\t.action = DAMON_PREP_SET_PGIDLE,\n+\t\t.name = \"set_pgidle\",\n+\t},\n+};\n+\n+static ssize_t prep_action_show(struct kobject *kobj,\n+\t\tstruct kobj_attribute *attr, char *buf)\n+{\n+\tstruct damon_sysfs_prep *prep = container_of(kobj,\n+\t\t\tstruct damon_sysfs_prep, kobj);\n+\tint i;\n+\n+\tfor (i = 0; i \u003c ARRAY_SIZE(damon_sysfs_prep_action_names); i++) {\n+\t\tconst struct damon_sysfs_prep_action_name *action_name;\n+\n+\t\taction_name = \u0026damon_sysfs_prep_action_names[i];\n+\t\tif (action_name-\u003eaction == prep-\u003eaction)\n+\t\t\treturn sysfs_emit(buf, \"%s\\n\", action_name-\u003ename);\n+\t}\n+\treturn -EINVAL;\n+}\n+\n+static ssize_t prep_action_store(struct kobject *kobj,\n+\t\tstruct kobj_attribute *attr, const char *buf, size_t count)\n+{\n+\tstruct damon_sysfs_prep *prep = container_of(kobj,\n+\t\t\tstruct damon_sysfs_prep, kobj);\n+\tssize_t ret = -EINVAL;\n+\tint i;\n+\n+\tfor (i = 0; i \u003c ARRAY_SIZE(damon_sysfs_prep_action_names); i++) {\n+\t\tconst struct damon_sysfs_prep_action_name *action_name;\n+\n+\t\taction_name = \u0026damon_sysfs_prep_action_names[i];\n+\t\tif (sysfs_streq(buf, action_name-\u003ename)) {\n+\t\t\tprep-\u003eaction = action_name-\u003eaction;\n+\t\t\tret = count;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn ret;\n+}\n+\n+static void damon_sysfs_prep_release(struct kobject *kobj)\n+{\n+\tstruct damon_sysfs_prep *prep = container_of(kobj,\n+\t\t\tstruct damon_sysfs_prep, kobj);\n+\n+\tkfree(prep);\n+}\n+\n+static struct kobj_attribute damon_sysfs_prep_prep_action_attr =\n+\t\t__ATTR_RW_MODE(prep_action, 0600);\n+\n+static struct attribute *damon_sysfs_prep_attrs[] = {\n+\t\u0026damon_sysfs_prep_prep_action_attr.attr,\n+\tNULL,\n+};\n+ATTRIBUTE_GROUPS(damon_sysfs_prep);\n+\n+static const struct kobj_type damon_sysfs_prep_ktype = {\n+\t.release = damon_sysfs_prep_release,\n+\t.sysfs_ops = \u0026kobj_sysfs_ops,\n+\t.default_groups = damon_sysfs_prep_groups,\n+};\n+\n+/*\n+ * preps directory\n+ */\n+\n+struct damon_sysfs_preps {\n+\tstruct kobject kobj;\n+\tstruct damon_sysfs_prep **preps_arr;\n+\tint nr;\n+};\n+\n+static struct damon_sysfs_preps *damon_sysfs_preps_alloc(void)\n+{\n+\treturn kzalloc_obj(struct damon_sysfs_preps);\n+}\n+\n+static void damon_sysfs_preps_rm_dirs(struct damon_sysfs_preps *preps)\n+{\n+\tstruct damon_sysfs_prep **preps_arr = preps-\u003epreps_arr;\n+\tint i;\n+\n+\tfor (i = 0; i \u003c preps-\u003enr; i++) {\n+\t\tkobject_del(\u0026preps_arr[i]-\u003ekobj);\n+\t\tkobject_put(\u0026preps_arr[i]-\u003ekobj);\n+\t}\n+\tpreps-\u003enr = 0;\n+\tkfree(preps_arr);\n+\tpreps-\u003epreps_arr = NULL;\n+}\n+\n+static int damon_sysfs_preps_add_dirs(struct damon_sysfs_preps *preps,\n+\t\tint nr_preps)\n+{\n+\tstruct damon_sysfs_prep **preps_arr, *prep;\n+\tint err, i;\n+\n+\tdamon_sysfs_preps_rm_dirs(preps);\n+\tif (!nr_preps)\n+\t\treturn 0;\n+\n+\tpreps_arr = kmalloc_objs(*preps_arr, nr_preps,\n+\t\t\t\t   GFP_KERNEL | __GFP_NOWARN);\n+\tif (!preps_arr)\n+\t\treturn -ENOMEM;\n+\tpreps-\u003epreps_arr = preps_arr;\n+\n+\tfor (i = 0; i \u003c nr_preps; i++) {\n+\t\tprep = damon_sysfs_prep_alloc();\n+\t\tif (!prep) {\n+\t\t\tdamon_sysfs_preps_rm_dirs(preps);\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\n+\t\terr = kobject_init_and_add(\u0026prep-\u003ekobj,\n+\t\t\t\t\u0026damon_sysfs_prep_ktype, \u0026preps-\u003ekobj, \"%d\",\n+\t\t\t\ti);\n+\t\tif (err) {\n+\t\t\tkobject_put(\u0026prep-\u003ekobj);\n+\t\t\tdamon_sysfs_preps_rm_dirs(preps);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\tpreps_arr[i] = prep;\n+\t\tpreps-\u003enr++;\n+\t}\n+\treturn 0;\n+}\n+\n+static ssize_t nr_preps_show(struct kobject *kobj, struct kobj_attribute *attr,\n+\t\tchar *buf)\n+{\n+\tstruct damon_sysfs_preps *preps = container_of(kobj,\n+\t\t\tstruct damon_sysfs_preps, kobj);\n+\n+\treturn sysfs_emit(buf, \"%d\\n\", preps-\u003enr);\n+}\n+\n+static ssize_t nr_preps_store(struct kobject *kobj,\n+\t\tstruct kobj_attribute *attr, const char *buf, size_t count)\n+{\n+\tstruct damon_sysfs_preps *preps;\n+\tint nr, err = kstrtoint(buf, 0, \u0026nr);\n+\n+\tif (err)\n+\t\treturn err;\n+\tif (nr \u003c 0)\n+\t\treturn -EINVAL;\n+\n+\tpreps = container_of(kobj, struct damon_sysfs_preps, kobj);\n+\n+\tif (!mutex_trylock(\u0026damon_sysfs_lock))\n+\t\treturn -EBUSY;\n+\terr = damon_sysfs_preps_add_dirs(preps, nr);\n+\tmutex_unlock(\u0026damon_sysfs_lock);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn count;\n+}\n+\n+static void damon_sysfs_preps_release(struct kobject *kobj)\n+{\n+\tkfree(container_of(kobj, struct damon_sysfs_preps, kobj));\n+}\n+\n+static struct kobj_attribute damon_sysfs_preps_nr_attr =\n+\t\t__ATTR_RW_MODE(nr_preps, 0600);\n+\n+static struct attribute *damon_sysfs_preps_attrs[] = {\n+\t\u0026damon_sysfs_preps_nr_attr.attr,\n+\tNULL,\n+};\n+ATTRIBUTE_GROUPS(damon_sysfs_preps);\n+\n+static const struct kobj_type damon_sysfs_preps_ktype = {\n+\t.release = damon_sysfs_preps_release,\n+\t.sysfs_ops = \u0026kobj_sysfs_ops,\n+\t.default_groups = damon_sysfs_preps_groups,\n+};\n+\n /*\n  * filter directory\n  */\n@@ -782,6 +995,10 @@ damon_sysfs_filter_type_names[] = {\n \t\t.type = DAMON_FILTER_TYPE_MEMCG,\n \t\t.name = \"memcg\",\n \t},\n+\t{\n+\t\t.type = DAMON_FILTER_TYPE_PGIDLE_UNSET,\n+\t\t.name = \"pgidle_unset\",\n+\t},\n };\n \n static ssize_t type_show(struct kobject *kobj,\n@@ -1066,6 +1283,7 @@ static const struct kobj_type damon_sysfs_filters_ktype = {\n struct damon_sysfs_probe {\n \tstruct kobject kobj;\n \tunsigned int weight;\n+\tstruct damon_sysfs_preps *preps;\n \tstruct damon_sysfs_filters *filters;\n };\n \n@@ -1076,25 +1294,50 @@ static struct damon_sysfs_probe *damon_sysfs_probe_alloc(void)\n \n static int damon_sysfs_probe_add_dirs(struct damon_sysfs_probe *probe)\n {\n+\tstruct damon_sysfs_preps *preps;\n \tstruct damon_sysfs_filters *filters;\n \tint err;\n \n-\tfilters = damon_sysfs_filters_alloc();\n-\tif (!filters)\n+\tpreps = damon_sysfs_preps_alloc();\n+\tif (!preps)\n \t\treturn -ENOMEM;\n+\tprobe-\u003epreps = preps;\n+\n+\terr = kobject_init_and_add(\u0026preps-\u003ekobj, \u0026damon_sysfs_preps_ktype,\n+\t\t\t\u0026probe-\u003ekobj, \"preps\");\n+\tif (err)\n+\t\tgoto put_preps_out;\n+\n+\tfilters = damon_sysfs_filters_alloc();\n+\tif (!filters) {\n+\t\terr = -ENOMEM;\n+\t\tgoto del_preps_out;\n+\t}\n \tprobe-\u003efilters = filters;\n \n \terr = kobject_init_and_add(\u0026filters-\u003ekobj, \u0026damon_sysfs_filters_ktype,\n \t\t\t\u0026probe-\u003ekobj, \"filters\");\n-\tif (err) {\n-\t\tkobject_put(\u0026filters-\u003ekobj);\n-\t\tprobe-\u003efilters = NULL;\n-\t}\n+\tif (err)\n+\t\tgoto put_filters_out;\n+\treturn err;\n+\n+put_filters_out:\n+\tkobject_put(\u0026filters-\u003ekobj);\n+\tprobe-\u003efilters = NULL;\n+del_preps_out:\n+\tkobject_del(\u0026preps-\u003ekobj);\n+put_preps_out:\n+\tkobject_put(\u0026preps-\u003ekobj);\n+\tprobe-\u003epreps = NULL;\n \treturn err;\n }\n \n static void damon_sysfs_probe_rm_dirs(struct damon_sysfs_probe *probe)\n {\n+\tif (probe-\u003epreps) {\n+\t\tdamon_sysfs_preps_rm_dirs(probe-\u003epreps);\n+\t\tkobject_put(\u0026probe-\u003epreps-\u003ekobj);\n+\t}\n \tif (probe-\u003efilters) {\n \t\tdamon_sysfs_filters_rm_dirs(probe-\u003efilters);\n \t\tkobject_put(\u0026probe-\u003efilters-\u003ekobj);\n@@ -1933,6 +2176,23 @@ static int damon_sysfs_set_attrs(struct damon_ctx *ctx,\n \treturn damon_set_attrs(ctx, \u0026attrs);\n }\n \n+static int damon_sysfs_set_preps(struct damon_probe *probe,\n+\t\tstruct damon_sysfs_preps *sys_preps)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i \u003c sys_preps-\u003enr; i++) {\n+\t\tstruct damon_sysfs_prep *sys_prep = sys_preps-\u003epreps_arr[i];\n+\t\tstruct damon_prep *prep;\n+\n+\t\tprep = damon_new_prep(sys_prep-\u003eaction);\n+\t\tif (!prep)\n+\t\t\treturn -ENOMEM;\n+\t\tdamon_add_prep(probe, prep);\n+\t}\n+\treturn 0;\n+}\n+\n static int damon_sysfs_set_filters(struct damon_probe *probe,\n \t\tstruct damon_sysfs_filters *sys_filters)\n {\n@@ -1968,7 +2228,15 @@ static int damon_sysfs_set_probe(struct damon_probe *probe,\n \t\tstruct damon_sysfs_probe *sys_probe)\n {\n \tstruct damon_sysfs_filters *sys_filters;\n+\tstruct damon_sysfs_preps *sys_preps;\n+\tint err;\n \n+\tsys_preps = sys_probe-\u003epreps;\n+\tif (sys_preps) {\n+\t\terr = damon_sysfs_set_preps(probe, sys_preps);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n \tsys_filters = sys_probe-\u003efilters;\n \tif (!sys_filters)\n \t\treturn 0;\ndiff --git a/tools/testing/selftests/damon/sysfs.sh b/tools/testing/selftests/damon/sysfs.sh\nindex f7fb94b84e716d..ddebde6edabe4e 100755\n--- a/tools/testing/selftests/damon/sysfs.sh\n+++ b/tools/testing/selftests/damon/sysfs.sh\n@@ -361,6 +361,32 @@ test_intervals()\n \ttest_intervals_goal \"$intervals_dir/intervals_goal\"\n }\n \n+test_damon_prep()\n+{\n+\tdamon_prep_dir=$1\n+\tensure_file \"$damon_prep_dir/prep_action\" \"exist\" \"600\"\n+\tensure_write_succ \"$damon_prep_dir/prep_action\" \"set_pgidle\" \\\n+\t\t\"valid input\"\n+\tensure_write_fail \"$damon_prep_dir/prep_action\" \"foo\" \"invalid input\"\n+}\n+\n+test_damon_preps()\n+{\n+\tpreps_dir=$1\n+\tensure_dir \"$preps_dir\" \"exist\"\n+\tensure_file \"$preps_dir/nr_preps\" \"exist\" \"600\"\n+\tensure_write_succ \"$preps_dir/nr_preps\" \"1\" \"valid input\"\n+\ttest_damon_prep \"$preps_dir/0\"\n+\n+\tensure_write_succ  \"$preps_dir/nr_preps\" \"2\" \"valid input\"\n+\ttest_damon_prep \"$preps_dir/0\"\n+\ttest_damon_prep \"$preps_dir/1\"\n+\n+\tensure_write_succ \"$preps_dir/nr_preps\" \"0\" \"valid input\"\n+\tensure_dir \"$preps_dir/0\" \"not_exist\"\n+\tensure_dir \"$preps_dir/1\" \"not_exist\"\n+}\n+\n test_damon_filter()\n {\n \tdamon_filter_dir=$1\n@@ -392,6 +418,7 @@ test_probe()\n {\n \tprobe_dir=$1\n \tensure_dir \"$probe_dir\" \"exist\"\n+\ttest_damon_preps \"$probe_dir/preps\"\n \ttest_damon_filters \"$probe_dir/filters\"\n }\n \n"
}

2/1 2026/07/26 18:53 agent patch-evaluator
1m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": [
    "DAMON_SYSFS",
    "DAMON_PADDR"
  ],
  "FocusSymbols": [
    "damon_new_prep",
    "damon_add_prep"
  ],
  "Reasoning": "The patch introduces a new feature to the DAMON subsystem, allowing users to configure probing preparation actions (e.g., `set_pgidle`) and a new filter type (`pgidle_unset`) via sysfs. This modifies the core DAMON logic and physical address monitoring operations, making it a functional change that is reachable from user space and worth fuzzing.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
  even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs
   output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit dcab8f13145b36eaa5257ee42bf8c65ff9503420
Author: syz-cluster <triage@syzkaller.com>
Date:   Sun Jul 26 18:53:55 2026 +0000

    syz-cluster: applied patch under review

diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-damon b/Documentation/ABI/testing/sysfs-kernel-mm-damon
index e675a57145e36d..6d596fb7fa1ffa 100644
--- a/Documentation/ABI/testing/sysfs-kernel-mm-damon
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-damon
@@ -173,6 +173,19 @@ Contact:	SJ Park <sj@kernel.org>
 Description:	Writing to and reading from this file sets and gets the
 		per-probe attribute weight.
 
+What:		/sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/probes/<P>/preps/nr_preps
+Date:		Jun 2026
+Contact:	SJ Park <sj@kernel.org>
+Description:	Writing a number 'N' to this file creates the number of
+		directories for each DAMON probing preparation action named '0'
+		to 'N-1' under the preps/ directory.
+
+What:		/sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/probes/<P>/prep/<R>/action
+Date:		Jun 2026
+Contact:	SJ Park <sj@kernel.org>
+Description:	Writing to and reading from this file sets and gets the probing
+		preeparation action.
+
 What:		/sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/probes/<P>/filters/nr_filters
 Date:		May 2026
 Contact:	SJ Park <sj@kernel.org>
diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst
index da5f9afd08aef8..1f5a39e1fc38da 100644
--- a/Documentation/admin-guide/mm/damon/usage.rst
+++ b/Documentation/admin-guide/mm/damon/usage.rst
@@ -74,6 +74,9 @@ comma (",").
     │ │ │ │ │ │ nr_regions/min,max
     │ │ │ │ │ │ :ref:`probes <damon_usage_sysfs_probes>`/nr_probes
     │ │ │ │ │ │ │ 0/weight
+    │ │ │ │ │ │ │ │ preps/nr_preps
+    │ │ │ │ │ │ │ │ │ 0/prep_action
+    │ │ │ │ │ │ │ │ │ ...
     │ │ │ │ │ │ │ │ filters/nr_filters
     │ │ │ │ │ │ │ │ │ 0/type,matching,allow,path
     │ │ │ │ │ │ │ │ │ ...
@@ -283,9 +286,18 @@ In the beginning, this directory has only one file, ``nr_probes``.  Writing a
 number (``N``) to the file creates the number of child directories named ``0``
 to ``N-1``.  Each directory represents each monitoring probe.
 
-In each probe directory, one directory, ``filters`` exists.  The directory
-contains files for installing filters for the probe, that is used to determine
-the data attribute for the probe.
+In each probe directory, two directories, ``preps`` and ``filters`` exists.
+The directories contains files for installing probing preparation actions and
+filters for the probe, that is used to determine the data attribute for the
+probe.
+
+In the beginning, ``preps`` directory has only one file, ``nr_preps``.
+Writiing a number (``N``) to the file creates the number of child directories
+names ``0`` to ``N-1``.  Each directory represents each preparation action.
+Each directory has one file, ``prep_action``.  The preparation action can be
+selected by writing the name of the action to the ``prep_action`` file.  Refer
+to the :ref:`design doc <damon_design_data_attrs_monitoring>` for the list of
+supported actions.
 
 Each probe directory also contains ``weight`` file.  Reading from and writing
 to the file gets and sets the :ref:`attributes-only monitoring
diff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst
index aed6cb1cf48310..06fffe5e37819e 100644
--- a/Documentation/mm/damon/design.rst
+++ b/Documentation/mm/damon/design.rst
@@ -293,8 +293,14 @@ registration is made by specifying a probe per attribute.  Each of the probe
 specifies a rule to determine if a given memory region has the related
 attribute.  The rule is constructed with multiple filters.  The filters work
 same to :ref:`DAMOS filters <damon_design_damos_filters>` except the supported
-filter types.  Currently only ``anon`` and ``memcg`` filter types are supported
-for data attributes monitoring.
+filter types.  Currently below fitler types are supported.
+
+- ``anon``: Same to that for DAMOS filters.
+- ``memcg``: Same to that for DAMOS filters.
+- ``pgidle_unset``: Matches if the page for the memory is marked as not
+  access-idle.
+  Matches if the memory is not backed by pages that DAMON can idnetify
+  idleness.
 
 If such probes are registered, DAMON executes the probes for each region's
 sampling memory when it does the access :ref:`sampling
@@ -305,6 +311,13 @@ Users can therefore know how much of a given DAMON region has a specific data
 attribute by reading the per-region per-probe probe hits counter after each
 aggregation interval.
 
+Users can optionally register probing preparation actions per probe.  If such
+actions are registered, DAMON applies the actions to each region's sampling
+memory before starting the next sampling interval.  Currently only one action,
+``set_pgidle`` is supported.  The action marks the page for the probing target
+memory as access-idle.  This can be useful to be used together with
+``pgidle_unset`` probe filter.
+
 This is a sampling based mechanism.  Hence, it is lightweight but the output
 may include some measurement errors.  The output should be used with good
 understanding of statistics.
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 0c8b7ddef9abb3..fe2c6b56d1d530 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -627,6 +627,7 @@ enum damon_ops_id {
  * @update:			Update operations-related data structures.
  * @prepare_access_checks:	Prepare next access check of target regions.
  * @check_accesses:		Check the accesses to target regions.
+ * @prep_probes:		Prepare applying probes for each region.
  * @apply_probes:		Apply probes for each region.
  * @get_scheme_score:		Get the score of a region for a scheme.
  * @apply_scheme:		Apply a DAMON-based operation scheme.
@@ -654,6 +655,8 @@ enum damon_ops_id {
  * last preparation and update the number of observed accesses of each region.
  * It should also return max number of observed accesses that made as a result
  * of its update.  The value will be used for regions adjustment threshold.
+ * @prep_probes should execute required &struct damon_prep for next &struct
+ * damon_probe applications to each region.
  * @apply_probes should apply the data attribute probes to each region and
  * accordingly update the probe hits counter of the region.  It should also
  * set &damon_region->sampling_addr of each region if ``set_samples`` is true.
@@ -676,6 +679,7 @@ struct damon_operations {
 	void (*update)(struct damon_ctx *context);
 	void (*prepare_access_checks)(struct damon_ctx *context);
 	unsigned int (*check_accesses)(struct damon_ctx *context);
+	void (*prep_probes)(struct damon_ctx *context, bool set_samples);
 	unsigned int (*apply_probes)(struct damon_ctx *context,
 			bool set_samples, bool return_max_wsum);
 	int (*get_scheme_score)(struct damon_ctx *context,
@@ -739,15 +743,38 @@ struct damon_intervals_goal {
 	unsigned long max_sample_us;
 };
 
+/**
+ * enum damon_prep_action - DAMON probing preparation action.
+ *
+ * @DAMON_PREP_SET_PGIDLE:	Set the probing memory as idle page.
+ */
+enum damon_prep_action {
+	DAMON_PREP_SET_PGIDLE,
+};
+
+/**
+ * struct damon_prep - DAMON probing preparation request.
+ *
+ * @action:	Action to do to the probing memory for the preparation.
+ */
+struct damon_prep {
+	enum damon_prep_action action;
+/* private: */
+	/* siblings list. */
+	struct list_head list;
+};
+
 /**
  * enum damon_filter_type - Type of &struct damon_filter
  *
- * @DAMON_FILTER_TYPE_ANON:	Anonymous pages.
- * @DAMON_FILTER_TYPE_MEMCG:	Specific memcg's pages.
+ * @DAMON_FILTER_TYPE_ANON:		Anonymous pages.
+ * @DAMON_FILTER_TYPE_MEMCG:		Specific memcg's pages.
+ * @DAMON_FILTER_TYPE_PGIDLE_UNSET:	Pgidle is unset.
  */
 enum damon_filter_type {
 	DAMON_FILTER_TYPE_ANON,
 	DAMON_FILTER_TYPE_MEMCG,
+	DAMON_FILTER_TYPE_PGIDLE_UNSET,
 };
 
 /**
@@ -778,6 +805,8 @@ struct damon_filter {
 struct damon_probe {
 	unsigned int weight;
 /* private: */
+	/* Preparation actions to apply to each probing memory. */
+	struct list_head preps;
 	/* Filters for assessing if a given region is for this probe. */
 	struct list_head filters;
 	/* Siblings list. */
@@ -957,6 +986,12 @@ static inline unsigned long damon_sz_region(struct damon_region *r)
 	return r->ar.end - r->ar.start;
 }
 
+#define damon_for_each_prep(p, prep) \
+	list_for_each_entry(p, &(prep)->preps, list)
+
+#define damon_for_each_prep_safe(p, next, prep) \
+	list_for_each_entry_safe(p, next, &(prep)->preps, list)
+
 #define damon_for_each_filter(f, p) \
 	list_for_each_entry(f, &(p)->filters, list)
 
@@ -1010,6 +1045,9 @@ static inline unsigned long damon_sz_region(struct damon_region *r)
 
 #ifdef CONFIG_DAMON
 
+struct damon_prep *damon_new_prep(enum damon_prep_action action);
+void damon_add_prep(struct damon_probe *p, struct damon_prep *prep);
+
 struct damon_filter *damon_new_filter(enum damon_filter_type type,
 		bool matching, bool allow);
 void damon_add_filter(struct damon_probe *probe, struct damon_filter *f);
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 644daf5a165606..d5b1e0b5851a1a 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -111,6 +111,63 @@ int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id)
 	return err;
 }
 
+struct damon_prep *damon_new_prep(enum damon_prep_action action)
+{
+	struct damon_prep *prep;
+
+	prep = kmalloc_obj(*prep);
+	if (!prep)
+		return NULL;
+	prep->action = action;
+	INIT_LIST_HEAD(&prep->list);
+	return prep;
+}
+
+void damon_add_prep(struct damon_probe *p, struct damon_prep *prep)
+{
+	list_add_tail(&prep->list, &p->preps);
+}
+
+static void damon_del_prep(struct damon_prep *p)
+{
+	list_del(&p->list);
+}
+
+static void damon_free_prep(struct damon_prep *p)
+{
+	kfree(p);
+}
+
+static void damon_destroy_prep(struct damon_prep *p)
+{
+	damon_del_prep(p);
+	damon_free_prep(p);
+}
+
+static struct damon_prep *damon_nth_prep(int n, struct damon_probe *p)
+{
+	struct damon_prep *prep;
+	int i = 0;
+
+	damon_for_each_prep(prep, p) {
+		if (i++ == n)
+			return prep;
+	}
+	return NULL;
+}
+
+static bool damon_has_prep(struct damon_ctx *c)
+{
+	struct damon_prep *prep;
+	struct damon_probe *probe;
+
+	damon_for_each_probe(probe, c) {
+		damon_for_each_prep(prep, probe)
+			return true;
+	}
+	return false;
+}
+
 struct damon_filter *damon_new_filter(enum damon_filter_type type,
 		bool matching, bool allow)
 {
@@ -167,6 +224,7 @@ struct damon_probe *damon_new_probe(void)
 	if (!p)
 		return NULL;
 	p->weight = 0;
+	INIT_LIST_HEAD(&p->preps);
 	INIT_LIST_HEAD(&p->filters);
 	INIT_LIST_HEAD(&p->list);
 	return p;
@@ -184,8 +242,11 @@ static void damon_del_probe(struct damon_probe *p)
 
 static void damon_free_probe(struct damon_probe *p)
 {
+	struct damon_prep *prep, *prep_next;
 	struct damon_filter *f, *next;
 
+	damon_for_each_prep_safe(prep, prep_next, p)
+		damon_free_prep(prep);
 	damon_for_each_filter_safe(f, next, p)
 		damon_free_filter(f);
 	kfree(p);
@@ -1666,6 +1727,36 @@ static int damon_commit_targets(
 	return err;
 }
 
+static void damon_commit_prep(struct damon_prep *dst, struct damon_prep *src)
+{
+	dst->action = src->action;
+}
+
+static int damon_commit_preps(struct damon_probe *dst, struct damon_probe *src)
+{
+	struct damon_prep *dst_prep, *next, *src_prep, *new_prep;
+	int i = 0, j = 0;
+
+	damon_for_each_prep_safe(dst_prep, next, dst) {
+		src_prep = damon_nth_prep(i++, src);
+		if (src_prep)
+			damon_commit_prep(dst_prep, src_prep);
+		else
+			damon_destroy_prep(dst_prep);
+	}
+
+	damon_for_each_prep_safe(src_prep, next, src) {
+		if (j++ < i)
+			continue;
+
+		new_prep = damon_new_prep(src_prep->action);
+		if (!new_prep)
+			return -ENOMEM;
+		damon_add_prep(dst, new_prep);
+	}
+	return 0;
+}
+
 static void damon_commit_filter(struct damon_filter *dst,
 		struct damon_filter *src)
 {
@@ -1724,6 +1815,9 @@ static int damon_commit_probes(struct damon_ctx *dst, struct damon_ctx *src)
 		src_probe = damon_nth_probe(i++, src);
 		if (src_probe) {
 			dst_probe->weight = src_probe->weight;
+			err = damon_commit_preps(dst_probe, src_probe);
+			if (err)
+				return err;
 			err = damon_commit_filters(dst_probe, src_probe);
 			if (err)
 				return err;
@@ -1741,6 +1835,9 @@ static int damon_commit_probes(struct damon_ctx *dst, struct damon_ctx *src)
 			return -ENOMEM;
 		damon_add_probe(dst, new_probe);
 		new_probe->weight = src_probe->weight;
+		err = damon_commit_preps(new_probe, src_probe);
+		if (err)
+			return err;
 		err = damon_commit_filters(new_probe, src_probe);
 		if (err)
 			return err;
@@ -3785,6 +3882,7 @@ static int kdamond_fn(void *data)
 		unsigned long next_ops_update_sis = ctx->next_ops_update_sis;
 		unsigned long sample_interval = ctx->attrs.sample_interval;
 		bool access_check_disabled = damon_has_probe_weights(ctx);
+		bool has_prep = damon_has_prep(ctx);
 		unsigned int max_merge_score = 0, max_wsum;
 		bool get_max_wsum;
 
@@ -3793,6 +3891,8 @@ static int kdamond_fn(void *data)
 
 		if (!access_check_disabled && ctx->ops.prepare_access_checks)
 			ctx->ops.prepare_access_checks(ctx);
+		if (ctx->ops.prep_probes)
+			ctx->ops.prep_probes(ctx, has_prep);
 
 		kdamond_usleep(sample_interval);
 		ctx->passed_sample_intervals++;
@@ -3807,7 +3907,8 @@ static int kdamond_fn(void *data)
 			else
 				get_max_wsum = false;
 			max_wsum = ctx->ops.apply_probes(ctx,
-					access_check_disabled, get_max_wsum);
+					access_check_disabled && !has_prep,
+					get_max_wsum);
 			if (get_max_wsum)
 				max_merge_score = max_wsum;
 		}
diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index 5a6a78054784af..8d8fcd1369e568 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -105,6 +105,40 @@ static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx)
 	return max_nr_accesses;
 }
 
+static void damon_pa_prep_probes_region(struct damon_region *r,
+		struct damon_probe *probe, struct damon_ctx *ctx)
+{
+	struct damon_prep *p;
+
+	damon_for_each_prep(p, probe) {
+		switch (p->action) {
+		case DAMON_PREP_SET_PGIDLE:
+			damon_pa_mkold(damon_pa_phys_addr(r->sampling_addr,
+						ctx->addr_unit));
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static void damon_pa_prep_probes(struct damon_ctx *ctx, bool set_samples)
+{
+	struct damon_target *t;
+	struct damon_region *r;
+	struct damon_probe *p;
+
+	damon_for_each_target(t, ctx) {
+		damon_for_each_region(r, t) {
+			if (set_samples)
+				r->sampling_addr = damon_rand(ctx, r->ar.start,
+						r->ar.end);
+			damon_for_each_probe(p, ctx)
+				damon_pa_prep_probes_region(r, p, ctx);
+		}
+	}
+}
+
 static bool damon_pa_filter_match(struct damon_filter *filter,
 		struct folio *folio)
 {
@@ -132,6 +166,12 @@ static bool damon_pa_filter_match(struct damon_filter *filter,
 			matched = filter->memcg_id == mem_cgroup_id(memcg);
 		rcu_read_unlock();
 		break;
+	case DAMON_FILTER_TYPE_PGIDLE_UNSET:
+		if (!folio)
+			matched = false;
+		else
+			matched = damon_folio_young(folio);
+		break;
 	default:
 		break;
 	}
@@ -440,6 +480,7 @@ static int __init damon_pa_initcall(void)
 		.update = NULL,
 		.prepare_access_checks = damon_pa_prepare_access_checks,
 		.check_accesses = damon_pa_check_accesses,
+		.prep_probes = damon_pa_prep_probes,
 		.apply_probes = damon_pa_apply_probes,
 		.target_valid = NULL,
 		.apply_scheme = damon_pa_apply_scheme,
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index e3858ffab4b227..d44d5bb9e8fbf8 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -750,6 +750,219 @@ static const struct kobj_type damon_sysfs_intervals_ktype = {
 	.default_groups = damon_sysfs_intervals_groups,
 };
 
+/*
+ * prep directory
+ */
+
+struct damon_sysfs_prep {
+	struct kobject kobj;
+	enum damon_prep_action action;
+};
+
+static struct damon_sysfs_prep *damon_sysfs_prep_alloc(void)
+{
+	struct damon_sysfs_prep *prep;
+
+	prep = kzalloc_obj(struct damon_sysfs_prep);
+	if (!prep)
+		return prep;
+	prep->action = DAMON_PREP_SET_PGIDLE;
+	return prep;
+}
+
+struct damon_sysfs_prep_action_name {
+	enum damon_prep_action action;
+	char *name;
+};
+
+static const struct damon_sysfs_prep_action_name
+damon_sysfs_prep_action_names[] = {
+	{
+		.action = DAMON_PREP_SET_PGIDLE,
+		.name = "set_pgidle",
+	},
+};
+
+static ssize_t prep_action_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	struct damon_sysfs_prep *prep = container_of(kobj,
+			struct damon_sysfs_prep, kobj);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(damon_sysfs_prep_action_names); i++) {
+		const struct damon_sysfs_prep_action_name *action_name;
+
+		action_name = &damon_sysfs_prep_action_names[i];
+		if (action_name->action == prep->action)
+			return sysfs_emit(buf, "%s\n", action_name->name);
+	}
+	return -EINVAL;
+}
+
+static ssize_t prep_action_store(struct kobject *kobj,
+		struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	struct damon_sysfs_prep *prep = container_of(kobj,
+			struct damon_sysfs_prep, kobj);
+	ssize_t ret = -EINVAL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(damon_sysfs_prep_action_names); i++) {
+		const struct damon_sysfs_prep_action_name *action_name;
+
+		action_name = &damon_sysfs_prep_action_names[i];
+		if (sysfs_streq(buf, action_name->name)) {
+			prep->action = action_name->action;
+			ret = count;
+			break;
+		}
+	}
+	return ret;
+}
+
+static void damon_sysfs_prep_release(struct kobject *kobj)
+{
+	struct damon_sysfs_prep *prep = container_of(kobj,
+			struct damon_sysfs_prep, kobj);
+
+	kfree(prep);
+}
+
+static struct kobj_attribute damon_sysfs_prep_prep_action_attr =
+		__ATTR_RW_MODE(prep_action, 0600);
+
+static struct attribute *damon_sysfs_prep_attrs[] = {
+	&damon_sysfs_prep_prep_action_attr.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_prep);
+
+static const struct kobj_type damon_sysfs_prep_ktype = {
+	.release = damon_sysfs_prep_release,
+	.sysfs_ops = &kobj_sysfs_ops,
+	.default_groups = damon_sysfs_prep_groups,
+};
+
+/*
+ * preps directory
+ */
+
+struct damon_sysfs_preps {
+	struct kobject kobj;
+	struct damon_sysfs_prep **preps_arr;
+	int nr;
+};
+
+static struct damon_sysfs_preps *damon_sysfs_preps_alloc(void)
+{
+	return kzalloc_obj(struct damon_sysfs_preps);
+}
+
+static void damon_sysfs_preps_rm_dirs(struct damon_sysfs_preps *preps)
+{
+	struct damon_sysfs_prep **preps_arr = preps->preps_arr;
+	int i;
+
+	for (i = 0; i < preps->nr; i++) {
+		kobject_del(&preps_arr[i]->kobj);
+		kobject_put(&preps_arr[i]->kobj);
+	}
+	preps->nr = 0;
+	kfree(preps_arr);
+	preps->preps_arr = NULL;
+}
+
+static int damon_sysfs_preps_add_dirs(struct damon_sysfs_preps *preps,
+		int nr_preps)
+{
+	struct damon_sysfs_prep **preps_arr, *prep;
+	int err, i;
+
+	damon_sysfs_preps_rm_dirs(preps);
+	if (!nr_preps)
+		return 0;
+
+	preps_arr = kmalloc_objs(*preps_arr, nr_preps,
+				   GFP_KERNEL | __GFP_NOWARN);
+	if (!preps_arr)
+		return -ENOMEM;
+	preps->preps_arr = preps_arr;
+
+	for (i = 0; i < nr_preps; i++) {
+		prep = damon_sysfs_prep_alloc();
+		if (!prep) {
+			damon_sysfs_preps_rm_dirs(preps);
+			return -ENOMEM;
+		}
+
+		err = kobject_init_and_add(&prep->kobj,
+				&damon_sysfs_prep_ktype, &preps->kobj, "%d",
+				i);
+		if (err) {
+			kobject_put(&prep->kobj);
+			damon_sysfs_preps_rm_dirs(preps);
+			return err;
+		}
+
+		preps_arr[i] = prep;
+		preps->nr++;
+	}
+	return 0;
+}
+
+static ssize_t nr_preps_show(struct kobject *kobj, struct kobj_attribute *attr,
+		char *buf)
+{
+	struct damon_sysfs_preps *preps = container_of(kobj,
+			struct damon_sysfs_preps, kobj);
+
+	return sysfs_emit(buf, "%d\n", preps->nr);
+}
+
+static ssize_t nr_preps_store(struct kobject *kobj,
+		struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	struct damon_sysfs_preps *preps;
+	int nr, err = kstrtoint(buf, 0, &nr);
+
+	if (err)
+		return err;
+	if (nr < 0)
+		return -EINVAL;
+
+	preps = container_of(kobj, struct damon_sysfs_preps, kobj);
+
+	if (!mutex_trylock(&damon_sysfs_lock))
+		return -EBUSY;
+	err = damon_sysfs_preps_add_dirs(preps, nr);
+	mutex_unlock(&damon_sysfs_lock);
+	if (err)
+		return err;
+
+	return count;
+}
+
+static void damon_sysfs_preps_release(struct kobject *kobj)
+{
+	kfree(container_of(kobj, struct damon_sysfs_preps, kobj));
+}
+
+static struct kobj_attribute damon_sysfs_preps_nr_attr =
+		__ATTR_RW_MODE(nr_preps, 0600);
+
+static struct attribute *damon_sysfs_preps_attrs[] = {
+	&damon_sysfs_preps_nr_attr.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_preps);
+
+static const struct kobj_type damon_sysfs_preps_ktype = {
+	.release = damon_sysfs_preps_release,
+	.sysfs_ops = &kobj_sysfs_ops,
+	.default_groups = damon_sysfs_preps_groups,
+};
+
 /*
  * filter directory
  */
@@ -782,6 +995,10 @@ damon_sysfs_filter_type_names[] = {
 		.type = DAMON_FILTER_TYPE_MEMCG,
 		.name = "memcg",
 	},
+	{
+		.type = DAMON_FILTER_TYPE_PGIDLE_UNSET,
+		.name = "pgidle_unset",
+	},
 };
 
 static ssize_t type_show(struct kobject *kobj,
@@ -1066,6 +1283,7 @@ static const struct kobj_type damon_sysfs_filters_ktype = {
 struct damon_sysfs_probe {
 	struct kobject kobj;
 	unsigned int weight;
+	struct damon_sysfs_preps *preps;
 	struct damon_sysfs_filters *filters;
 };
 
@@ -1076,25 +1294,50 @@ static struct damon_sysfs_probe *damon_sysfs_probe_alloc(void)
 
 static int damon_sysfs_probe_add_dirs(struct damon_sysfs_probe *probe)
 {
+	struct damon_sysfs_preps *preps;
 	struct damon_sysfs_filters *filters;
 	int err;
 
-	filters = damon_sysfs_filters_alloc();
-	if (!filters)
+	preps = damon_sysfs_preps_alloc();
+	if (!preps)
 		return -ENOMEM;
+	probe->preps = preps;
+
+	err = kobject_init_and_add(&preps->kobj, &damon_sysfs_preps_ktype,
+			&probe->kobj, "preps");
+	if (err)
+		goto put_preps_out;
+
+	filters = damon_sysfs_filters_alloc();
+	if (!filters) {
+		err = -ENOMEM;
+		goto del_preps_out;
+	}
 	probe->filters = filters;
 
 	err = kobject_init_and_add(&filters->kobj, &damon_sysfs_filters_ktype,
 			&probe->kobj, "filters");
-	if (err) {
-		kobject_put(&filters->kobj);
-		probe->filters = NULL;
-	}
+	if (err)
+		goto put_filters_out;
+	return err;
+
+put_filters_out:
+	kobject_put(&filters->kobj);
+	probe->filters = NULL;
+del_preps_out:
+	kobject_del(&preps->kobj);
+put_preps_out:
+	kobject_put(&preps->kobj);
+	probe->preps = NULL;
 	return err;
 }
 
 static void damon_sysfs_probe_rm_dirs(struct damon_sysfs_probe *probe)
 {
+	if (probe->preps) {
+		damon_sysfs_preps_rm_dirs(probe->preps);
+		kobject_put(&probe->preps->kobj);
+	}
 	if (probe->filters) {
 		damon_sysfs_filters_rm_dirs(probe->filters);
 		kobject_put(&probe->filters->kobj);
@@ -1933,6 +2176,23 @@ static int damon_sysfs_set_attrs(struct damon_ctx *ctx,
 	return damon_set_attrs(ctx, &attrs);
 }
 
+static int damon_sysfs_set_preps(struct damon_probe *probe,
+		struct damon_sysfs_preps *sys_preps)
+{
+	int i;
+
+	for (i = 0; i < sys_preps->nr; i++) {
+		struct damon_sysfs_prep *sys_prep = sys_preps->preps_arr[i];
+		struct damon_prep *prep;
+
+		prep = damon_new_prep(sys_prep->action);
+		if (!prep)
+			return -ENOMEM;
+		damon_add_prep(probe, prep);
+	}
+	return 0;
+}
+
 static int damon_sysfs_set_filters(struct damon_probe *probe,
 		struct damon_sysfs_filters *sys_filters)
 {
@@ -1968,7 +2228,15 @@ static int damon_sysfs_set_probe(struct damon_probe *probe,
 		struct damon_sysfs_probe *sys_probe)
 {
 	struct damon_sysfs_filters *sys_filters;
+	struct damon_sysfs_preps *sys_preps;
+	int err;
 
+	sys_preps = sys_probe->preps;
+	if (sys_preps) {
+		err = damon_sysfs_set_preps(probe, sys_preps);
+		if (err)
+			return err;
+	}
 	sys_filters = sys_probe->filters;
 	if (!sys_filters)
 		return 0;
diff --git a/tools/testing/selftests/damon/sysfs.sh b/tools/testing/selftests/damon/sysfs.sh
index f7fb94b84e716d..ddebde6edabe4e 100755
--- a/tools/testing/selftests/damon/sysfs.sh
+++ b/tools/testing/selftests/damon/sysfs.sh
@@ -361,6 +361,32 @@ test_intervals()
 	test_intervals_goal "$intervals_dir/intervals_goal"
 }
 
+test_damon_prep()
+{
+	damon_prep_dir=$1
+	ensure_file "$damon_prep_dir/prep_action" "exist" "600"
+	ensure_write_succ "$damon_prep_dir/prep_action" "set_pgidle" \
+		"valid input"
+	ensure_write_fail "$damon_prep_dir/prep_action" "foo" "invalid input"
+}
+
+test_damon_preps()
+{
+	preps_dir=$1
+	ensure_dir "$preps_dir" "exist"
+	ensure_file "$preps_dir/nr_preps" "exist" "600"
+	ensure_write_succ "$preps_dir/nr_preps" "1" "valid input"
+	test_damon_prep "$preps_dir/0"
+
+	ensure_write_succ  "$preps_dir/nr_preps" "2" "valid input"
+	test_damon_prep "$preps_dir/0"
+	test_damon_prep "$preps_dir/1"
+
+	ensure_write_succ "$preps_dir/nr_preps" "0" "valid input"
+	ensure_dir "$preps_dir/0" "not_exist"
+	ensure_dir "$preps_dir/1" "not_exist"
+}
+
 test_damon_filter()
 {
 	damon_filter_dir=$1
@@ -392,6 +418,7 @@ test_probe()
 {
 	probe_dir=$1
 	ensure_dir "$probe_dir" "exist"
+	test_damon_preps "$probe_dir/preps"
 	test_damon_filters "$probe_dir/filters"
 }
 

3/2 2026/07/26 18:53 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 11860
							output: 33
							thoughts: 523
						

Thoughts:
**DAMON Probe Prep Patch Analysis**

Okay, so I've got a patch here that adds "probing preparation actions" or "preps" to the Data Access Monitor (DAMON) subsystem in the Linux kernel. It looks like a functional change, modifying core kernel logic. The changes are spread across several files: the documentation, `damon.h`, the core DAMON files (`core.c`, `paddr.c`, `sysfs.c`), and a selftest script (`sysfs.sh`). That's a reasonable distribution of modifications for a feature like this.

My first thought is always, "Is this reachable and fuzzable?" DAMON is definitely reachable via sysfs, which is good. That opens it up nicely for fuzzing. These new sysfs interfaces are in `mm/damon/sysfs.c`. I need to figure out which functions are the key targets here.

I've identified a few key functions across the modified files. In `mm/damon/core.c`, I need to pay attention to `damon_new_prep`, `damon_add_prep`, `damon_commit_preps`, `damon_commit_probes` (which is modified), and `kdamond_fn` (also modified). Then, in `mm/damon/paddr.c`, the `damon_pa_prep_probes_region`, `damon_pa_prep_probes`, and modified `damon_pa_filter_match` are of interest. Finally, in `mm/damon/sysfs.c`, the functions dealing with prep configuration like `prep_action_show`, `prep_action_store`, `damon_sysfs_preps_add_dirs`, `nr_preps_show`, `nr_preps_store`, `damon_sysfs_set_preps` and the modified `damon_sysfs_set_probe` are definitely on the list.

Now, I need to confirm the required configs for sysfs. It looks like `CONFIG_DAMON_SYSFS` is needed, so I should double-check that in `mm/damon/Kconfig`. I'll also ensure all the relevant config options are set. This is critical for actually being able to use and fuzz the new interfaces. I'll need to figure out what values and combinations will yield the most coverage.



4/2 2026/07/26 18:54 tool grepper
0m Args:
{
  "Expression": "config DAMON_SYSFS",
  "PathPrefix": "mm/damon/Kconfig"
}

Results:
{
  "Output": "mm/damon/Kconfig=56=config DAMON_VADDR_KUNIT_TEST\n--\nmm/damon/Kconfig-67-\nmm/damon/Kconfig:68:config DAMON_SYSFS\nmm/damon/Kconfig-69-\tbool \"DAMON sysfs interface\"\n--\nmm/damon/Kconfig-75-\nmm/damon/Kconfig:76:config DAMON_SYSFS_KUNIT_TEST\nmm/damon/Kconfig-77-\tbool \"Test for damon sysfs interface\" if !KUNIT_ALL_TESTS\n"
}

5/2 2026/07/26 18:54 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 13090
							output: 30
							thoughts: 13
						

Thoughts:
Okay, let's dive into this. Here's my thought process on figuring out what `DAMON_SYSFS` depends on, presented as if it's my own.

**Investigating DAMON_SYSFS Dependencies**

Right, let's get down to brass tacks. I need to understand the dependencies of `DAMON_SYSFS`. I know it's a critical part of dynamic memory management, specifically, this thing called Dynamic Adaptive Memory Optimizer. So, where does this functionality sit in the grand scheme? What other kernel modules, subsystems, or configurations does it lean on to operate correctly? That's the question I need answered. I'll need to trace the connections and understand the requirements for it.



6/2 2026/07/26 18:54 tool grepper
0m Args:
{
  "Expression": "depends on.*",
  "PathPrefix": "mm/damon/Kconfig"
}

Results:
{
  "Output": "mm/damon/Kconfig=15=config DAMON_DEBUG_SANITY\nmm/damon/Kconfig-16-\tbool \"Check sanity of DAMON code\"\nmm/damon/Kconfig:17:\tdepends on DAMON\nmm/damon/Kconfig-18-\thelp\n--\nmm/damon/Kconfig=26=config DAMON_KUNIT_TEST\nmm/damon/Kconfig-27-\tbool \"Test for damon\" if !KUNIT_ALL_TESTS\nmm/damon/Kconfig:28:\tdepends on DAMON \u0026\u0026 KUNIT=y\nmm/damon/Kconfig-29-\tdefault KUNIT_ALL_TESTS\n--\nmm/damon/Kconfig=38=config DAMON_VADDR\nmm/damon/Kconfig-39-\tbool \"Data access monitoring operations for virtual address spaces\"\nmm/damon/Kconfig:40:\tdepends on DAMON \u0026\u0026 MMU\nmm/damon/Kconfig-41-\tselect PAGE_IDLE_FLAG\n--\nmm/damon/Kconfig=47=config DAMON_PADDR\nmm/damon/Kconfig-48-\tbool \"Data access monitoring operations for the physical address space\"\nmm/damon/Kconfig:49:\tdepends on DAMON \u0026\u0026 MMU\nmm/damon/Kconfig-50-\tselect PAGE_IDLE_FLAG\n--\nmm/damon/Kconfig=56=config DAMON_VADDR_KUNIT_TEST\nmm/damon/Kconfig-57-\tbool \"Test for DAMON operations\" if !KUNIT_ALL_TESTS\nmm/damon/Kconfig:58:\tdepends on DAMON_VADDR \u0026\u0026 KUNIT=y\nmm/damon/Kconfig-59-\tdefault KUNIT_ALL_TESTS\n--\nmm/damon/Kconfig=68=config DAMON_SYSFS\nmm/damon/Kconfig-69-\tbool \"DAMON sysfs interface\"\nmm/damon/Kconfig:70:\tdepends on DAMON \u0026\u0026 SYSFS\nmm/damon/Kconfig-71-\tdefault DAMON\n--\nmm/damon/Kconfig=76=config DAMON_SYSFS_KUNIT_TEST\nmm/damon/Kconfig-77-\tbool \"Test for damon sysfs interface\" if !KUNIT_ALL_TESTS\nmm/damon/Kconfig:78:\tdepends on DAMON_SYSFS \u0026\u0026 KUNIT=y\nmm/damon/Kconfig-79-\tdefault KUNIT_ALL_TESTS\n--\nmm/damon/Kconfig=88=config DAMON_RECLAIM\nmm/damon/Kconfig-89-\tbool \"Build DAMON-based reclaim (DAMON_RECLAIM)\"\nmm/damon/Kconfig:90:\tdepends on DAMON_PADDR\nmm/damon/Kconfig-91-\thelp\n--\nmm/damon/Kconfig=100=config DAMON_LRU_SORT\nmm/damon/Kconfig-101-\tbool \"Build DAMON-based LRU-lists sorting (DAMON_LRU_SORT)\"\nmm/damon/Kconfig:102:\tdepends on DAMON_PADDR\nmm/damon/Kconfig-103-\thelp\n--\nmm/damon/Kconfig=108=config DAMON_STAT\nmm/damon/Kconfig-109-\tbool \"Build data access monitoring stat (DAMON_STAT)\"\nmm/damon/Kconfig:110:\tdepends on DAMON_PADDR\nmm/damon/Kconfig-111-\thelp\n--\nmm/damon/Kconfig=116=config DAMON_STAT_ENABLED_DEFAULT\nmm/damon/Kconfig-117-\tbool \"Enable DAMON_STAT by default\"\nmm/damon/Kconfig:118:\tdepends on DAMON_STAT\nmm/damon/Kconfig-119-\tdefault DAMON_STAT\n"
}

7/2 2026/07/26 18:54 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14261
							output: 28
							thoughts: 77
						

Thoughts:
Okay, let's break this down.

**Understanding the DAMON Dependency Structure**

Right, so I'm seeing that the `DAMON_SYSFS` feature hinges on both `DAMON` and `SYSFS` being present. That's a fundamental building block. And, the inclusion of `DAMON_PADDR` is flagged as being essential because we've got a modification in `mm/damon/paddr.c`. This strongly suggests that `DAMON_PADDR` directly impacts how physical addresses are handled within DAMON. Now, I want to confirm that this is true and that `paddr.c` is only compiled if `DAMON_PADDR` is set. To do that, the logical next step is to examine the `mm/damon/Makefile`. That should reveal the conditional compilation rules, and confirm my hypothesis.



8/2 2026/07/26 18:54 tool grepper
0m Args:
{
  "Expression": "paddr",
  "PathPrefix": "mm/damon/Makefile"
}

Results:
{
  "Output": "mm/damon/Makefile=4=obj-$(CONFIG_DAMON_VADDR)\t+= ops-common.o vaddr.o\nmm/damon/Makefile:5:obj-$(CONFIG_DAMON_PADDR)\t+= ops-common.o paddr.o\nmm/damon/Makefile-6-obj-$(CONFIG_DAMON_SYSFS)\t+= sysfs-common.o sysfs-schemes.o sysfs.o\n"
}

9/2 2026/07/26 18:54 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14665
							output: 34
							thoughts: 303
						

Thoughts:
**Analyzing DAMON Patch Function Visibility**

Okay, so I need to confirm that `DAMON_PADDR` is indeed a necessary part of this. Right, confirmed. Now, to get to the heart of this, let's look at the functions involved. I need to focus on these: `damon_pa_prep_probes_region`, `damon_pa_prep_probes`, `damon_sysfs_preps_add_dirs`, `nr_preps_store`, `prep_action_store`, `damon_sysfs_set_preps`, and `damon_commit_preps`. I need to figure out how these play a role in the changes.

Hmm, a quick check reveals they are all static. Yes, they are. That's a red flag. If they are all static, they're probably not the best candidates for direct FocusSymbol analysis within the patch. I need to dig deeper. They might be indirectly important, but I need to find the publicly visible functions.

Alright, let's shift focus to identify non-static functions in this patch. Ah, here we go: `damon_new_prep` and `damon_add_prep`. These are exported, meaning they are non-static. Those are the ones I should be looking at when it comes to the symbol analysis.

I should probably cross reference with `mm/damon/core.c` to see if there are any others there.



10/2 2026/07/26 18:54 tool grepper
0m Args:
{
  "Expression": "damon_new_prep",
  "PathPrefix": "mm/damon/core.c"
}

Results:
{
  "Output": "mm/damon/core.c=98=int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id)\n--\nmm/damon/core.c-113-\nmm/damon/core.c:114:struct damon_prep *damon_new_prep(enum damon_prep_action action)\nmm/damon/core.c-115-{\n--\nmm/damon/core.c=1735=static int damon_commit_preps(struct damon_probe *dst, struct damon_probe *src)\n--\nmm/damon/core.c-1751-\nmm/damon/core.c:1752:\t\tnew_prep = damon_new_prep(src_prep-\u003eaction);\nmm/damon/core.c-1753-\t\tif (!new_prep)\n"
}

11/2 2026/07/26 18:54 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15549
							output: 34
							thoughts: 9
						

Thoughts:
Okay, here's my summary, framed as my internal thought process:

**Non-Static Function Considerations**

Hmm, I'm analyzing the codebase, and my initial question is focused on function design. Are there *any* other functions that aren't static? I'm already pretty familiar with the static ones, but I need to make sure I haven't missed any non-static functions as I consider design patterns and potential optimizations. This is important because their scope, memory management, and overall behavior could be different, impacting performance and how other parts of the system interact with them. I need to be thorough. I need to map out the non-static functions to consider their effect on the greater whole.



12/2 2026/07/26 18:54 tool grepper
0m Args:
{
  "Expression": "damon_add_prep",
  "PathPrefix": "mm/damon/core.c"
}

Results:
{
  "Output": "mm/damon/core.c=114=struct damon_prep *damon_new_prep(enum damon_prep_action action)\n--\nmm/damon/core.c-125-\nmm/damon/core.c:126:void damon_add_prep(struct damon_probe *p, struct damon_prep *prep)\nmm/damon/core.c-127-{\n--\nmm/damon/core.c=1735=static int damon_commit_preps(struct damon_probe *dst, struct damon_probe *src)\n--\nmm/damon/core.c-1754-\t\t\treturn -ENOMEM;\nmm/damon/core.c:1755:\t\tdamon_add_prep(dst, new_prep);\nmm/damon/core.c-1756-\t}\n"
}

13/2 2026/07/26 18:54 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15969
							output: 70
							thoughts: 124
						

Thoughts:
**Examining the DAMON Code's Symbol Visibility**

Okay, so I'm digging into this DAMON code again, and I'm hitting a bit of a wall in my understanding. I keep seeing these function names, like `damon_sysfs_set_probe` and `damon_commit_probes`, but they're *static*. That's a problem. If all the interesting, modified functions are static, how do I build a good `FocusSymbols` list? I need something to focus on.

Alright, I can definitely include `damon_new_prep` and `damon_add_prep`; those look promising. And, there's `kdamond_fn`, but that's a thread function, so I'll need to consider how that fits into the bigger picture.

I need to expand my search. Time to check `mm/damon/sysfs.c`, and see if there are any non-static functions in there that I've missed, functions that might be modified and, therefore, more useful to me. I need to make sure I am getting the complete picture.



14/2 2026/07/26 18:54 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "^[a-zA-Z_][a-zA-Z0-9_]*\\s+\\**[a-zA-Z_][a-zA-Z0-9_]*\\(",
  "PathPrefix": "mm/damon/sysfs.c"
}

Results:
{
  "error": "no matches"
}

15/2 2026/07/26 18:54 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 16419
							output: 42
							thoughts: 32
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Examining `mm/damon/sysfs.c` for Data Structures**

Alright, I need to quickly get a lay of the land in `mm/damon/sysfs.c`. I need to figure out the key data structures being used. My initial approach is the classic, quick and dirty method: let's use `grep`. I'm going to leverage regular expressions to zero in on the relevant declarations. Specifically, I'll search for lines that *begin* with `int `, `void `, or `struct `. This will give me a first pass, a reasonable starting point to identify integer variables, void return types (which often hint at function declarations with side effects), and `struct` definitions, which are absolutely crucial for understanding the core data organization in the module. It's a pragmatic, preliminary scan before I dive deeper with ctags or even start pulling up the definitions in an IDE. I'm essentially using `grep` as a very targeted code indexer for a quick, initial overview.



16/2 2026/07/26 18:54 tool grepper
0m Args:
{
  "Expression": "^(int|void|struct|ssize_t) ",
  "PathPrefix": "mm/damon/sysfs.c"
}

Results:
{
  "Output": "mm/damon/sysfs.c-15-\nmm/damon/sysfs.c:16:struct damon_sysfs_region {\nmm/damon/sysfs.c-17-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=82=static const struct kobj_type damon_sysfs_region_ktype = {\n--\nmm/damon/sysfs.c-91-\nmm/damon/sysfs.c:92:struct damon_sysfs_regions {\nmm/damon/sysfs.c-93-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=201=static const struct kobj_type damon_sysfs_regions_ktype = {\n--\nmm/damon/sysfs.c-210-\nmm/damon/sysfs.c:211:struct damon_sysfs_target {\nmm/damon/sysfs.c-212-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=308=static const struct kobj_type damon_sysfs_target_ktype = {\n--\nmm/damon/sysfs.c-317-\nmm/damon/sysfs.c:318:struct damon_sysfs_targets {\nmm/damon/sysfs.c-319-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=436=static const struct kobj_type damon_sysfs_targets_ktype = {\n--\nmm/damon/sysfs.c-445-\nmm/damon/sysfs.c:446:struct damon_sysfs_intervals_goal {\nmm/damon/sysfs.c-447-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=593=static const struct kobj_type damon_sysfs_intervals_goal_ktype = {\n--\nmm/damon/sysfs.c-602-\nmm/damon/sysfs.c:603:struct damon_sysfs_intervals {\nmm/damon/sysfs.c-604-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=747=static const struct kobj_type damon_sysfs_intervals_ktype = {\n--\nmm/damon/sysfs.c-756-\nmm/damon/sysfs.c:757:struct damon_sysfs_prep {\nmm/damon/sysfs.c-758-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=762=static struct damon_sysfs_prep *damon_sysfs_prep_alloc(void)\n--\nmm/damon/sysfs.c-772-\nmm/damon/sysfs.c:773:struct damon_sysfs_prep_action_name {\nmm/damon/sysfs.c-774-\tenum damon_prep_action action;\n--\nmm/damon/sysfs.c=841=static const struct kobj_type damon_sysfs_prep_ktype = {\n--\nmm/damon/sysfs.c-850-\nmm/damon/sysfs.c:851:struct damon_sysfs_preps {\nmm/damon/sysfs.c-852-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=960=static const struct kobj_type damon_sysfs_preps_ktype = {\n--\nmm/damon/sysfs.c-969-\nmm/damon/sysfs.c:970:struct damon_sysfs_filter {\nmm/damon/sysfs.c-971-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=978=static struct damon_sysfs_filter *damon_sysfs_filter_alloc(void)\n--\nmm/damon/sysfs.c-982-\nmm/damon/sysfs.c:983:struct damon_sysfs_filter_type_name {\nmm/damon/sysfs.c-984-\tenum damon_filter_type type;\n--\nmm/damon/sysfs.c=1154=static const struct kobj_type damon_sysfs_filter_ktype = {\n--\nmm/damon/sysfs.c-1163-\nmm/damon/sysfs.c:1164:struct damon_sysfs_filters {\nmm/damon/sysfs.c-1165-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=1273=static const struct kobj_type damon_sysfs_filters_ktype = {\n--\nmm/damon/sysfs.c-1282-\nmm/damon/sysfs.c:1283:struct damon_sysfs_probe {\nmm/damon/sysfs.c-1284-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=1380=static const struct kobj_type damon_sysfs_probe_ktype = {\n--\nmm/damon/sysfs.c-1389-\nmm/damon/sysfs.c:1390:struct damon_sysfs_probes {\nmm/damon/sysfs.c-1391-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=1509=static const struct kobj_type damon_sysfs_probes_ktype = {\n--\nmm/damon/sysfs.c-1518-\nmm/damon/sysfs.c:1519:struct damon_sysfs_attrs {\nmm/damon/sysfs.c-1520-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=1615=static const struct kobj_type damon_sysfs_attrs_ktype = {\n--\nmm/damon/sysfs.c-1624-\nmm/damon/sysfs.c:1625:struct damon_sysfs_ops_name {\nmm/damon/sysfs.c-1626-\tenum damon_ops_id ops_id;\n--\nmm/damon/sysfs.c=1630=static const struct damon_sysfs_ops_name damon_sysfs_ops_names[] = {\n--\nmm/damon/sysfs.c-1644-\nmm/damon/sysfs.c:1645:struct damon_sysfs_context {\nmm/damon/sysfs.c-1646-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=1891=static const struct kobj_type damon_sysfs_context_ktype = {\n--\nmm/damon/sysfs.c-1900-\nmm/damon/sysfs.c:1901:struct damon_sysfs_contexts {\nmm/damon/sysfs.c-1902-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=2020=static const struct kobj_type damon_sysfs_contexts_ktype = {\n--\nmm/damon/sysfs.c-2029-\nmm/damon/sysfs.c:2030:struct damon_sysfs_kdamond {\nmm/damon/sysfs.c-2031-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=2569=static int damon_sysfs_damon_call(int (*fn)(void *data),\n--\nmm/damon/sysfs.c-2582-\nmm/damon/sysfs.c:2583:struct damon_sysfs_schemes_walk_data {\nmm/damon/sysfs.c-2584-\tstruct damon_sysfs_kdamond *sysfs_kdamond;\n--\nmm/damon/sysfs.c=2767=static const struct kobj_type damon_sysfs_kdamond_ktype = {\n--\nmm/damon/sysfs.c-2776-\nmm/damon/sysfs.c:2777:struct damon_sysfs_kdamonds {\nmm/damon/sysfs.c-2778-\tstruct kobject kobj;\n--\nmm/damon/sysfs.c=2912=static const struct kobj_type damon_sysfs_kdamonds_ktype = {\n--\nmm/damon/sysfs.c-2921-\nmm/damon/sysfs.c:2922:struct damon_sysfs_ui_dir {\nmm/damon/sysfs.c-2923-\tstruct kobject kobj;\n"
}

17/2 2026/07/26 18:54 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 18982
							output: 38
							thoughts: 64
						

Thoughts:
**Analyzing DAMON's Sysfs Interface**

Okay, so I'm diving into this DAMON code, and the first thing I'm noticing is that every single sysfs function is declared as static. Interesting. That's a deliberate design choice, and it immediately makes me think about scope and potential external interactions. But then I see a couple of functions in `mm/damon/core.c` – specifically `damon_new_prep` and `damon_add_prep` – that aren't static. My initial thought is to figure out if either of them are exported. Are they intended for use outside of the core DAMON component? That's the crucial question. Time to check the export status, and determine their intended purpose.



18/2 2026/07/26 18:54 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "EXPORT_SYMBOL.*damon_new_prep",
  "PathPrefix": "mm/damon/core.c"
}

Results:
{
  "error": "no matches"
}

19/2 2026/07/26 18:54 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 19258
							output: 38
							thoughts: 26
						

Thoughts:
Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person:

**Navigating the Scope and Visibility**

Right, so I'm looking at this particular function or variable, and the first thing that jumps out is that it's *not* part of the public API, at least not directly through standard exports. That's fine, but the fact that it's *not* declared as `static` raises a flag. It implies a degree of accessibility beyond a purely internal scope. This means it *could* be accessed or linked to from other parts of the codebase, or perhaps even dynamically loaded, depending on the build and linking strategy.

Then, the key question arises: is this `damon_add_prep` function – *this* specific entity – actually exported by any other means? Is it exposed in a way that, while not explicitly declared in a typical header or export list, is still accessible through some other mechanism? Perhaps a dynamically generated symbol table? Knowing this answer is crucial for understanding its intended use and potential impact on the overall architecture. It's about figuring out the actual effective boundary of the function.



20/2 2026/07/26 18:54 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "EXPORT_SYMBOL.*damon_add_prep",
  "PathPrefix": "mm/damon/core.c"
}

Results:
{
  "error": "no matches"
}

21/2 2026/07/26 18:54 llm patch-evaluator
1m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 19581
							output: 137
							thoughts: 633
						

Thoughts:
**My Analysis of the DAMON Patch for Fuzzing**

Okay, so I've been looking at this DAMON patch, and my initial thought is, "This looks interesting from a fuzzing perspective." While the core functions within the patch aren't directly static, they are part of the broader DAMON framework, and specifically, they are related to FocusSymbols. I need to make sure I identify the correct points to target with fuzzing.

My first check was whether `damon_sysfs_set_preps` and `damon_pa_prep_probes` were static. Yes, they are. But I realized that since this is a sysfs interface, the real entry points are the sysfs store and show functions. So, after a little thought, I'm going to list `damon_new_prep` and `damon_add_prep` as my FocusSymbols. I also considered `kdamond_fn`, the thread function, but decided against it, as it's a hot-path function, the main loop, and not a direct entry point.

Next, I needed to check the relevant configurations. I see that `DAMON_SYSFS` and `DAMON_PADDR` are required to enable this. Additionally, `DAMON`, `SYSFS`, `MMU`, and `PAGE_IDLE_FLAG` are implied. So, my EnableConfigs list will be `DAMON_SYSFS` and `DAMON_PADDR`. I confirmed that `mm/damon/sysfs.c` compiles when `CONFIG_DAMON_SYSFS` is set, and `mm/damon/paddr.c` compiles when `CONFIG_DAMON_PADDR` is set.

Reviewing the patch again, I see that it adds a `preps` directory under `probes/<P>/` within the sysfs interface. This allows setting `prep_action` to `set_pgidle` and adds a new filter type called `pgidle_unset`. This is a functional change, as it allows users to set page idle flags prior to probing and then filter results. This significantly modifies DAMON's core behavior, and it's reachable from user space via sysfs. This is definitely worth a fuzzing campaign.

So, to summarize for fuzzing purposes:

*   **FocusSymbols:** `damon_new_prep`, `damon_add_prep`
*   **EnableConfigs:** `DAMON_SYSFS`, `DAMON_PADDR`

Finally, let me re-verify that `damon_new_prep` and `damon_add_prep` are the right entry points, the only non-static functions added by the patch. Yep, that's what I want. They are the best symbols for fuzzing this. Now, let's call `set-results`.



22/2 2026/07/26 18:55 tool set-results
0m Args:
{
  "EnableConfigs": [
    "DAMON_SYSFS",
    "DAMON_PADDR"
  ],
  "FocusSymbols": [
    "damon_new_prep",
    "damon_add_prep"
  ],
  "Reasoning": "The patch introduces a new feature to the DAMON subsystem, allowing users to configure probing preparation actions (e.g., `set_pgidle`) and a new filter type (`pgidle_unset`) via sysfs. This modifies the core DAMON logic and physical address monitoring operations, making it a functional change that is reachable from user space and worth fuzzing.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "DAMON_SYSFS",
    "DAMON_PADDR"
  ],
  "FocusSymbols": [
    "damon_new_prep",
    "damon_add_prep"
  ],
  "Reasoning": "The patch introduces a new feature to the DAMON subsystem, allowing users to configure probing preparation actions (e.g., `set_pgidle`) and a new filter type (`pgidle_unset`) via sysfs. This modifies the core DAMON logic and physical address monitoring operations, making it a functional change that is reachable from user space and worth fuzzing.",
  "WorthFuzzing": true
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)