Skip to content

Commit 19467a9

Browse files
sjp38akpm00
authored andcommitted
mm/damon/sysfs: remove requested targets when online-commit inputs
damon_sysfs_set_targets(), which updates the targets of the context for online commitment, do not remove targets that removed from the corresponding sysfs files. As a result, more than intended targets of the context can exist and hence consume memory and monitoring CPU resource more than expected. Fix it by removing all targets of the context and fill up again using the user input. This could cause unnecessary memory dealloc and realloc operations, but this is not a hot code path. Also, note that damon_target is stateless, and hence no data is lost. [sj@kernel.org: fix unnecessary monitoring results removal] Link: https://lkml.kernel.org/r/20231028213353.45397-1-sj@kernel.org Link: https://lkml.kernel.org/r/20231022210735.46409-2-sj@kernel.org Fixes: da87878 ("mm/damon/sysfs: support online inputs update") Signed-off-by: SeongJae Park <sj@kernel.org> Cc: Brendan Higgins <brendanhiggins@google.com> Cc: <stable@vger.kernel.org> [5.19.x] Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 6479b29 commit 19467a9

File tree

1 file changed

+36
-34
lines changed

1 file changed

+36
-34
lines changed

mm/damon/sysfs.c

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,58 +1150,60 @@ static int damon_sysfs_add_target(struct damon_sysfs_target *sys_target,
11501150
return err;
11511151
}
11521152

1153-
/*
1154-
* Search a target in a context that corresponds to the sysfs target input.
1155-
*
1156-
* Return: pointer to the target if found, NULL if not found, or negative
1157-
* error code if the search failed.
1158-
*/
1159-
static struct damon_target *damon_sysfs_existing_target(
1160-
struct damon_sysfs_target *sys_target, struct damon_ctx *ctx)
1153+
static int damon_sysfs_update_target(struct damon_target *target,
1154+
struct damon_ctx *ctx,
1155+
struct damon_sysfs_target *sys_target)
11611156
{
11621157
struct pid *pid;
1163-
struct damon_target *t;
1158+
struct damon_region *r, *next;
11641159

1165-
if (!damon_target_has_pid(ctx)) {
1166-
/* Up to only one target for paddr could exist */
1167-
damon_for_each_target(t, ctx)
1168-
return t;
1169-
return NULL;
1170-
}
1160+
if (!damon_target_has_pid(ctx))
1161+
return 0;
11711162

1172-
/* ops.id should be DAMON_OPS_VADDR or DAMON_OPS_FVADDR */
11731163
pid = find_get_pid(sys_target->pid);
11741164
if (!pid)
1175-
return ERR_PTR(-EINVAL);
1176-
damon_for_each_target(t, ctx) {
1177-
if (t->pid == pid) {
1178-
put_pid(pid);
1179-
return t;
1180-
}
1165+
return -EINVAL;
1166+
1167+
/* no change to the target */
1168+
if (pid == target->pid) {
1169+
put_pid(pid);
1170+
return 0;
11811171
}
1182-
put_pid(pid);
1183-
return NULL;
1172+
1173+
/* remove old monitoring results and update the target's pid */
1174+
damon_for_each_region_safe(r, next, target)
1175+
damon_destroy_region(r, target);
1176+
put_pid(target->pid);
1177+
target->pid = pid;
1178+
return 0;
11841179
}
11851180

11861181
static int damon_sysfs_set_targets(struct damon_ctx *ctx,
11871182
struct damon_sysfs_targets *sysfs_targets)
11881183
{
1189-
int i, err;
1184+
struct damon_target *t, *next;
1185+
int i = 0, err;
11901186

11911187
/* Multiple physical address space monitoring targets makes no sense */
11921188
if (ctx->ops.id == DAMON_OPS_PADDR && sysfs_targets->nr > 1)
11931189
return -EINVAL;
11941190

1195-
for (i = 0; i < sysfs_targets->nr; i++) {
1191+
damon_for_each_target_safe(t, next, ctx) {
1192+
if (i < sysfs_targets->nr) {
1193+
damon_sysfs_update_target(t, ctx,
1194+
sysfs_targets->targets_arr[i]);
1195+
} else {
1196+
if (damon_target_has_pid(ctx))
1197+
put_pid(t->pid);
1198+
damon_destroy_target(t);
1199+
}
1200+
i++;
1201+
}
1202+
1203+
for (; i < sysfs_targets->nr; i++) {
11961204
struct damon_sysfs_target *st = sysfs_targets->targets_arr[i];
1197-
struct damon_target *t = damon_sysfs_existing_target(st, ctx);
1198-
1199-
if (IS_ERR(t))
1200-
return PTR_ERR(t);
1201-
if (!t)
1202-
err = damon_sysfs_add_target(st, ctx);
1203-
else
1204-
err = damon_sysfs_set_regions(t, st->regions);
1205+
1206+
err = damon_sysfs_add_target(st, ctx);
12051207
if (err)
12061208
return err;
12071209
}

0 commit comments

Comments
 (0)