summaryrefslogtreecommitdiff
path: root/mm/damon/sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/damon/sysfs.c')
-rw-r--r--mm/damon/sysfs.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index b65651498e0d..e3858ffab4b2 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -1065,6 +1065,7 @@ static const struct kobj_type damon_sysfs_filters_ktype = {
struct damon_sysfs_probe {
struct kobject kobj;
+ unsigned int weight;
struct damon_sysfs_filters *filters;
};
@@ -1100,12 +1101,35 @@ static void damon_sysfs_probe_rm_dirs(struct damon_sysfs_probe *probe)
}
}
+static ssize_t weight_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ struct damon_sysfs_probe *probe = container_of(kobj,
+ struct damon_sysfs_probe, kobj);
+
+ return sysfs_emit(buf, "%u\n", probe->weight);
+}
+
+static ssize_t weight_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_probe *probe = container_of(kobj,
+ struct damon_sysfs_probe, kobj);
+ int err = kstrtouint(buf, 0, &probe->weight);
+
+ return err ? err : count;
+}
+
static void damon_sysfs_probe_release(struct kobject *kobj)
{
kfree(container_of(kobj, struct damon_sysfs_probe, kobj));
}
+static struct kobj_attribute damon_sysfs_probe_weight_attr =
+ __ATTR_RW_MODE(weight, 0600);
+
static struct attribute *damon_sysfs_probe_attrs[] = {
+ &damon_sysfs_probe_weight_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(damon_sysfs_probe);
@@ -1965,6 +1989,7 @@ static int damon_sysfs_set_probes(struct damon_ctx *ctx,
return -ENOMEM;
damon_add_probe(ctx, p);
sys_probe = sys_probes->probes_arr[i];
+ p->weight = sys_probe->weight;
err = damon_sysfs_set_probe(p, sys_probe);
if (err)
return err;
@@ -2026,7 +2051,7 @@ static int damon_sysfs_add_targets(struct damon_ctx *ctx,
int i, err;
/* Multiple physical address space monitoring targets makes no sense */
- if (ctx->ops.id == DAMON_OPS_PADDR && sysfs_targets->nr > 1)
+ if (!damon_target_has_pid(ctx) && sysfs_targets->nr > 1)
return -EINVAL;
for (i = 0; i < sysfs_targets->nr; i++) {
@@ -2069,16 +2094,18 @@ static inline bool damon_sysfs_kdamond_running(
static int damon_sysfs_apply_inputs(struct damon_ctx *ctx,
struct damon_sysfs_context *sys_ctx)
{
+ enum damon_ops_id ops_id;
int err;
- err = damon_select_ops(ctx, sys_ctx->ops_id);
+ ops_id = READ_ONCE(sys_ctx->ops_id);
+ err = damon_select_ops(ctx, ops_id);
if (err)
return err;
- ctx->addr_unit = sys_ctx->addr_unit;
+ ctx->addr_unit = READ_ONCE(sys_ctx->addr_unit);
/* addr_unit is respected by only DAMON_OPS_PADDR */
- if (sys_ctx->ops_id == DAMON_OPS_PADDR)
+ if (ops_id == DAMON_OPS_PADDR)
ctx->min_region_sz = max(
- DAMON_MIN_REGION_SZ / sys_ctx->addr_unit, 1);
+ DAMON_MIN_REGION_SZ / ctx->addr_unit, 1);
ctx->pause = sys_ctx->pause;
err = damon_sysfs_set_attrs(ctx, sys_ctx->attrs);
if (err)
@@ -2262,12 +2289,13 @@ static int damon_sysfs_turn_damon_off(struct damon_sysfs_kdamond *kdamond)
{
if (!kdamond->damon_ctx)
return -EINVAL;
- return damon_stop(&kdamond->damon_ctx, 1);
+ damon_stop(&kdamond->damon_ctx, 1);
/*
* To allow users show final monitoring results of already turned-off
* DAMON, we free kdamond->damon_ctx in next
* damon_sysfs_turn_damon_on(), or kdamonds_nr_store()
*/
+ return 0;
}
static int damon_sysfs_damon_call(int (*fn)(void *data),