mm/damon/sysfs: update monitoring target regions for online input commit

commit 9732336006764e2ee61225387e3c70eae9139035 upstream.

When user input is committed online, DAMON sysfs interface is ignoring the
user input for the monitoring target regions.  Such request is valid and
useful for fixed monitoring target regions-based monitoring ops like
'paddr' or 'fvaddr'.

Update the region boundaries as user specified, too.  Note that the
monitoring results of the regions that overlap between the latest
monitoring target regions and the new target regions are preserved.

Treat empty monitoring target regions user request as a request to just
make no change to the monitoring target regions.  Otherwise, users should
set the monitoring target regions same to current one for every online
input commit, and it could be challenging for dynamic monitoring target
regions update DAMON ops like 'vaddr'.  If the user really need to remove
all monitoring target regions, they can simply remove the target and then
create the target again with empty target regions.

Link: https://lkml.kernel.org/r/20231031170131.46972-1-sj@kernel.org
Fixes: da87878010 ("mm/damon/sysfs: support online inputs update")
Signed-off-by: SeongJae Park <sj@kernel.org>
Cc: <stable@vger.kernel.org>	[5.19+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
SeongJae Park 2023-10-31 17:01:31 +00:00 committed by Greg Kroah-Hartman
parent 9275f65d77
commit f0f3328af9
1 changed files with 32 additions and 19 deletions

View File

@ -2188,32 +2188,45 @@ static int damon_sysfs_add_target(struct damon_sysfs_target *sys_target,
return err; return err;
} }
static int damon_sysfs_update_target_pid(struct damon_target *target, int pid)
{
struct pid *pid_new;
pid_new = find_get_pid(pid);
if (!pid_new)
return -EINVAL;
if (pid_new == target->pid) {
put_pid(pid_new);
return 0;
}
put_pid(target->pid);
target->pid = pid_new;
return 0;
}
static int damon_sysfs_update_target(struct damon_target *target, static int damon_sysfs_update_target(struct damon_target *target,
struct damon_ctx *ctx, struct damon_ctx *ctx,
struct damon_sysfs_target *sys_target) struct damon_sysfs_target *sys_target)
{ {
struct pid *pid; int err;
struct damon_region *r, *next;
if (!damon_target_has_pid(ctx)) if (damon_target_has_pid(ctx)) {
return 0; err = damon_sysfs_update_target_pid(target, sys_target->pid);
if (err)
pid = find_get_pid(sys_target->pid); return err;
if (!pid)
return -EINVAL;
/* no change to the target */
if (pid == target->pid) {
put_pid(pid);
return 0;
} }
/* remove old monitoring results and update the target's pid */ /*
damon_for_each_region_safe(r, next, target) * Do monitoring target region boundary update only if one or more
damon_destroy_region(r, target); * regions are set by the user. This is for keeping current monitoring
put_pid(target->pid); * target results and range easier, especially for dynamic monitoring
target->pid = pid; * target regions update ops like 'vaddr'.
return 0; */
if (sys_target->regions->nr)
err = damon_sysfs_set_regions(target, sys_target->regions);
return err;
} }
static int damon_sysfs_set_targets(struct damon_ctx *ctx, static int damon_sysfs_set_targets(struct damon_ctx *ctx,