Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm/damon/sysfs: implement obsolete_target file

There is no good way to remove DAMON targets in the middle of the existing
targets list. It restricts efficient and flexible DAMON use cases.
Improve the usability by implementing a new DAMON sysfs interface file,
namely obsolete_target, under each target directory. It is connected to
the obsolete field of parameters commit-source targets, so allows removing
arbitrary targets in the middle of existing targets list.

Note that the sysfs files are not automatically updated. For example,
let's suppose there are three targets in the running context, and a user
removes the third target using this feature. If the user writes 'commit'
to the kdamond 'state' file again, DAMON sysfs interface will again try to
remove the third target. But because there is no matching target in the
running context, the commit will fail. It is the user's responsibility to
understand resulting DAMON internal targets list change, and construct
sysfs files (using nr_targets and other sysfs files) to correctly
represent it.

Also note that this is arguably an improvement rather than a fix of broken
things.

Link: https://lkml.kernel.org/r/20251023012535.69625-4-sj@kernel.org
Signed-off-by: SeongJae Park <sj@kernel.org>
Reported-by: Bijan Tabatabai <bijan311@gmail.com>
Closes: https://github.com/damonitor/damo/issues/36
Reviewed-by: Bijan Tabatabai <bijan311@gmail.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

SeongJae Park and committed by
Andrew Morton
e35afdf2 60bd24f2

+29
+29
mm/damon/sysfs.c
··· 212 212 struct kobject kobj; 213 213 struct damon_sysfs_regions *regions; 214 214 int pid; 215 + bool obsolete; 215 216 }; 216 217 217 218 static struct damon_sysfs_target *damon_sysfs_target_alloc(void) ··· 264 263 return count; 265 264 } 266 265 266 + static ssize_t obsolete_target_show(struct kobject *kobj, 267 + struct kobj_attribute *attr, char *buf) 268 + { 269 + struct damon_sysfs_target *target = container_of(kobj, 270 + struct damon_sysfs_target, kobj); 271 + 272 + return sysfs_emit(buf, "%c\n", target->obsolete ? 'Y' : 'N'); 273 + } 274 + 275 + static ssize_t obsolete_target_store(struct kobject *kobj, 276 + struct kobj_attribute *attr, const char *buf, size_t count) 277 + { 278 + struct damon_sysfs_target *target = container_of(kobj, 279 + struct damon_sysfs_target, kobj); 280 + bool obsolete; 281 + int err = kstrtobool(buf, &obsolete); 282 + 283 + if (err) 284 + return err; 285 + target->obsolete = obsolete; 286 + return count; 287 + } 288 + 267 289 static void damon_sysfs_target_release(struct kobject *kobj) 268 290 { 269 291 kfree(container_of(kobj, struct damon_sysfs_target, kobj)); ··· 295 271 static struct kobj_attribute damon_sysfs_target_pid_attr = 296 272 __ATTR_RW_MODE(pid_target, 0600); 297 273 274 + static struct kobj_attribute damon_sysfs_target_obsolete_attr = 275 + __ATTR_RW_MODE(obsolete_target, 0600); 276 + 298 277 static struct attribute *damon_sysfs_target_attrs[] = { 299 278 &damon_sysfs_target_pid_attr.attr, 279 + &damon_sysfs_target_obsolete_attr.attr, 300 280 NULL, 301 281 }; 302 282 ATTRIBUTE_GROUPS(damon_sysfs_target); ··· 1405 1377 /* caller will destroy targets */ 1406 1378 return -EINVAL; 1407 1379 } 1380 + t->obsolete = sys_target->obsolete; 1408 1381 return damon_sysfs_set_regions(t, sys_target->regions, ctx->min_sz_region); 1409 1382 } 1410 1383