Skip to content

Commit 9bbb820

Browse files
sjp38torvalds
authored andcommitted
mm/damon/sysfs: support DAMOS quotas
This commit makes DAMON sysfs interface supports the DAMOS quotas feature. Specifically, this commit adds 'quotas' directory under each scheme directory and makes kdamond 'state' file writing respects the contents in the directory. As a result, the files hierarchy becomes as below: /sys/kernel/mm/damon/admin │ kdamonds/nr_kdamonds │ │ 0/state,pid │ │ │ contexts/nr_contexts │ │ │ │ 0/operations │ │ │ │ │ monitoring_attrs/intervals/sample_us,aggr_us,update_us │ │ │ │ │ │ nr_regions/min,max │ │ │ │ │ targets/nr_targets │ │ │ │ │ │ 0/pid_target │ │ │ │ │ │ │ regions/nr_regions │ │ │ │ │ │ │ │ 0/start,end │ │ │ │ │ │ │ │ ... │ │ │ │ │ │ ... │ │ │ │ │ schemes/nr_schemes │ │ │ │ │ │ 0/action │ │ │ │ │ │ │ access_pattern/ │ │ │ │ │ │ │ │ sz/min,max │ │ │ │ │ │ │ │ nr_accesses/min,max │ │ │ │ │ │ │ │ age/min,max │ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms <- NEW DIRECTORY │ │ │ │ │ │ ... │ │ │ │ ... │ │ ... Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: SeongJae Park <[email protected]> Cc: David Rientjes <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Xin Hao <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 7e84b1f commit 9bbb820

File tree

1 file changed

+145
-1
lines changed

1 file changed

+145
-1
lines changed

mm/damon/sysfs.c

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,113 @@ static struct kobj_type damon_sysfs_ul_range_ktype = {
113113
.default_groups = damon_sysfs_ul_range_groups,
114114
};
115115

116+
/*
117+
* quotas directory
118+
*/
119+
120+
struct damon_sysfs_quotas {
121+
struct kobject kobj;
122+
unsigned long ms;
123+
unsigned long sz;
124+
unsigned long reset_interval_ms;
125+
};
126+
127+
static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
128+
{
129+
return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
130+
}
131+
132+
static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
133+
char *buf)
134+
{
135+
struct damon_sysfs_quotas *quotas = container_of(kobj,
136+
struct damon_sysfs_quotas, kobj);
137+
138+
return sysfs_emit(buf, "%lu\n", quotas->ms);
139+
}
140+
141+
static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
142+
const char *buf, size_t count)
143+
{
144+
struct damon_sysfs_quotas *quotas = container_of(kobj,
145+
struct damon_sysfs_quotas, kobj);
146+
int err = kstrtoul(buf, 0, &quotas->ms);
147+
148+
if (err)
149+
return -EINVAL;
150+
return count;
151+
}
152+
153+
static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
154+
char *buf)
155+
{
156+
struct damon_sysfs_quotas *quotas = container_of(kobj,
157+
struct damon_sysfs_quotas, kobj);
158+
159+
return sysfs_emit(buf, "%lu\n", quotas->sz);
160+
}
161+
162+
static ssize_t bytes_store(struct kobject *kobj,
163+
struct kobj_attribute *attr, const char *buf, size_t count)
164+
{
165+
struct damon_sysfs_quotas *quotas = container_of(kobj,
166+
struct damon_sysfs_quotas, kobj);
167+
int err = kstrtoul(buf, 0, &quotas->sz);
168+
169+
if (err)
170+
return -EINVAL;
171+
return count;
172+
}
173+
174+
static ssize_t reset_interval_ms_show(struct kobject *kobj,
175+
struct kobj_attribute *attr, char *buf)
176+
{
177+
struct damon_sysfs_quotas *quotas = container_of(kobj,
178+
struct damon_sysfs_quotas, kobj);
179+
180+
return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
181+
}
182+
183+
static ssize_t reset_interval_ms_store(struct kobject *kobj,
184+
struct kobj_attribute *attr, const char *buf, size_t count)
185+
{
186+
struct damon_sysfs_quotas *quotas = container_of(kobj,
187+
struct damon_sysfs_quotas, kobj);
188+
int err = kstrtoul(buf, 0, &quotas->reset_interval_ms);
189+
190+
if (err)
191+
return -EINVAL;
192+
return count;
193+
}
194+
195+
static void damon_sysfs_quotas_release(struct kobject *kobj)
196+
{
197+
kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
198+
}
199+
200+
static struct kobj_attribute damon_sysfs_quotas_ms_attr =
201+
__ATTR_RW_MODE(ms, 0600);
202+
203+
static struct kobj_attribute damon_sysfs_quotas_sz_attr =
204+
__ATTR_RW_MODE(bytes, 0600);
205+
206+
static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
207+
__ATTR_RW_MODE(reset_interval_ms, 0600);
208+
209+
static struct attribute *damon_sysfs_quotas_attrs[] = {
210+
&damon_sysfs_quotas_ms_attr.attr,
211+
&damon_sysfs_quotas_sz_attr.attr,
212+
&damon_sysfs_quotas_reset_interval_ms_attr.attr,
213+
NULL,
214+
};
215+
ATTRIBUTE_GROUPS(damon_sysfs_quotas);
216+
217+
static struct kobj_type damon_sysfs_quotas_ktype = {
218+
.release = damon_sysfs_quotas_release,
219+
.sysfs_ops = &kobj_sysfs_ops,
220+
.default_groups = damon_sysfs_quotas_groups,
221+
};
222+
116223
/*
117224
* access_pattern directory
118225
*/
@@ -220,6 +327,7 @@ struct damon_sysfs_scheme {
220327
struct kobject kobj;
221328
enum damos_action action;
222329
struct damon_sysfs_access_pattern *access_pattern;
330+
struct damon_sysfs_quotas *quotas;
223331
};
224332

225333
/* This should match with enum damos_action */
@@ -270,20 +378,48 @@ static int damon_sysfs_scheme_set_access_pattern(
270378
return err;
271379
}
272380

381+
static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
382+
{
383+
struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
384+
int err;
385+
386+
if (!quotas)
387+
return -ENOMEM;
388+
err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
389+
&scheme->kobj, "quotas");
390+
if (err)
391+
goto out;
392+
scheme->quotas = quotas;
393+
return 0;
394+
395+
out:
396+
kobject_put(&quotas->kobj);
397+
return err;
398+
}
399+
273400
static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
274401
{
275402
int err;
276403

277404
err = damon_sysfs_scheme_set_access_pattern(scheme);
278405
if (err)
279406
return err;
407+
err = damon_sysfs_scheme_set_quotas(scheme);
408+
if (err)
409+
goto put_access_pattern_out;
280410
return 0;
411+
412+
put_access_pattern_out:
413+
kobject_put(&scheme->access_pattern->kobj);
414+
scheme->access_pattern = NULL;
415+
return err;
281416
}
282417

283418
static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
284419
{
285420
damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
286421
kobject_put(&scheme->access_pattern->kobj);
422+
kobject_put(&scheme->quotas->kobj);
287423
}
288424

289425
static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -1522,7 +1658,15 @@ static struct damos *damon_sysfs_mk_scheme(
15221658
{
15231659
struct damon_sysfs_access_pattern *pattern =
15241660
sysfs_scheme->access_pattern;
1525-
struct damos_quota quota = (struct damos_quota){};
1661+
struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1662+
struct damos_quota quota = {
1663+
.ms = sysfs_quotas->ms,
1664+
.sz = sysfs_quotas->sz,
1665+
.reset_interval = sysfs_quotas->reset_interval_ms,
1666+
.weight_sz = 1000,
1667+
.weight_nr_accesses = 1000,
1668+
.weight_age = 1000,
1669+
};
15261670
struct damos_watermarks wmarks = {
15271671
.metric = DAMOS_WMARK_NONE,
15281672
.interval = 0,

0 commit comments

Comments
 (0)