Skip to content

Commit 1b32234

Browse files
sjp38torvalds
authored andcommitted
mm/damon/sysfs: support DAMOS watermarks
This commit makes DAMON sysfs interface supports the DAMOS watermarks feature. Specifically, this commit adds 'watermarks' 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,sz,reset_interval_ms │ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil │ │ │ │ │ │ │ watermarks/ <- NEW DIRECTORY │ │ │ │ │ │ │ │ metric,interval_us,high,mid,lo │ │ │ │ │ │ ... │ │ │ │ ... │ │ ... [[email protected]: fix out-of-bound array access for wmark_metric_strs[]] Link: https://lkml.kernel.org/r/[email protected] 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]> Cc: Colin Ian King <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 1c78b2b commit 1b32234

File tree

1 file changed

+215
-5
lines changed

1 file changed

+215
-5
lines changed

mm/damon/sysfs.c

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

116+
/*
117+
* watermarks directory
118+
*/
119+
120+
struct damon_sysfs_watermarks {
121+
struct kobject kobj;
122+
enum damos_wmark_metric metric;
123+
unsigned long interval_us;
124+
unsigned long high;
125+
unsigned long mid;
126+
unsigned long low;
127+
};
128+
129+
static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
130+
enum damos_wmark_metric metric, unsigned long interval_us,
131+
unsigned long high, unsigned long mid, unsigned long low)
132+
{
133+
struct damon_sysfs_watermarks *watermarks = kmalloc(
134+
sizeof(*watermarks), GFP_KERNEL);
135+
136+
if (!watermarks)
137+
return NULL;
138+
watermarks->kobj = (struct kobject){};
139+
watermarks->metric = metric;
140+
watermarks->interval_us = interval_us;
141+
watermarks->high = high;
142+
watermarks->mid = mid;
143+
watermarks->low = low;
144+
return watermarks;
145+
}
146+
147+
/* Should match with enum damos_wmark_metric */
148+
static const char * const damon_sysfs_wmark_metric_strs[] = {
149+
"none",
150+
"free_mem_rate",
151+
};
152+
153+
static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
154+
char *buf)
155+
{
156+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
157+
struct damon_sysfs_watermarks, kobj);
158+
159+
return sysfs_emit(buf, "%s\n",
160+
damon_sysfs_wmark_metric_strs[watermarks->metric]);
161+
}
162+
163+
static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
164+
const char *buf, size_t count)
165+
{
166+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
167+
struct damon_sysfs_watermarks, kobj);
168+
enum damos_wmark_metric metric;
169+
170+
for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
171+
if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
172+
watermarks->metric = metric;
173+
return count;
174+
}
175+
}
176+
return -EINVAL;
177+
}
178+
179+
static ssize_t interval_us_show(struct kobject *kobj,
180+
struct kobj_attribute *attr, char *buf)
181+
{
182+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
183+
struct damon_sysfs_watermarks, kobj);
184+
185+
return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
186+
}
187+
188+
static ssize_t interval_us_store(struct kobject *kobj,
189+
struct kobj_attribute *attr, const char *buf, size_t count)
190+
{
191+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
192+
struct damon_sysfs_watermarks, kobj);
193+
int err = kstrtoul(buf, 0, &watermarks->interval_us);
194+
195+
if (err)
196+
return -EINVAL;
197+
return count;
198+
}
199+
200+
static ssize_t high_show(struct kobject *kobj,
201+
struct kobj_attribute *attr, char *buf)
202+
{
203+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
204+
struct damon_sysfs_watermarks, kobj);
205+
206+
return sysfs_emit(buf, "%lu\n", watermarks->high);
207+
}
208+
209+
static ssize_t high_store(struct kobject *kobj,
210+
struct kobj_attribute *attr, const char *buf, size_t count)
211+
{
212+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
213+
struct damon_sysfs_watermarks, kobj);
214+
int err = kstrtoul(buf, 0, &watermarks->high);
215+
216+
if (err)
217+
return -EINVAL;
218+
return count;
219+
}
220+
221+
static ssize_t mid_show(struct kobject *kobj,
222+
struct kobj_attribute *attr, char *buf)
223+
{
224+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
225+
struct damon_sysfs_watermarks, kobj);
226+
227+
return sysfs_emit(buf, "%lu\n", watermarks->mid);
228+
}
229+
230+
static ssize_t mid_store(struct kobject *kobj,
231+
struct kobj_attribute *attr, const char *buf, size_t count)
232+
{
233+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
234+
struct damon_sysfs_watermarks, kobj);
235+
int err = kstrtoul(buf, 0, &watermarks->mid);
236+
237+
if (err)
238+
return -EINVAL;
239+
return count;
240+
}
241+
242+
static ssize_t low_show(struct kobject *kobj,
243+
struct kobj_attribute *attr, char *buf)
244+
{
245+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
246+
struct damon_sysfs_watermarks, kobj);
247+
248+
return sysfs_emit(buf, "%lu\n", watermarks->low);
249+
}
250+
251+
static ssize_t low_store(struct kobject *kobj,
252+
struct kobj_attribute *attr, const char *buf, size_t count)
253+
{
254+
struct damon_sysfs_watermarks *watermarks = container_of(kobj,
255+
struct damon_sysfs_watermarks, kobj);
256+
int err = kstrtoul(buf, 0, &watermarks->low);
257+
258+
if (err)
259+
return -EINVAL;
260+
return count;
261+
}
262+
263+
static void damon_sysfs_watermarks_release(struct kobject *kobj)
264+
{
265+
kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
266+
}
267+
268+
static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
269+
__ATTR_RW_MODE(metric, 0600);
270+
271+
static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
272+
__ATTR_RW_MODE(interval_us, 0600);
273+
274+
static struct kobj_attribute damon_sysfs_watermarks_high_attr =
275+
__ATTR_RW_MODE(high, 0600);
276+
277+
static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
278+
__ATTR_RW_MODE(mid, 0600);
279+
280+
static struct kobj_attribute damon_sysfs_watermarks_low_attr =
281+
__ATTR_RW_MODE(low, 0600);
282+
283+
static struct attribute *damon_sysfs_watermarks_attrs[] = {
284+
&damon_sysfs_watermarks_metric_attr.attr,
285+
&damon_sysfs_watermarks_interval_us_attr.attr,
286+
&damon_sysfs_watermarks_high_attr.attr,
287+
&damon_sysfs_watermarks_mid_attr.attr,
288+
&damon_sysfs_watermarks_low_attr.attr,
289+
NULL,
290+
};
291+
ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
292+
293+
static struct kobj_type damon_sysfs_watermarks_ktype = {
294+
.release = damon_sysfs_watermarks_release,
295+
.sysfs_ops = &kobj_sysfs_ops,
296+
.default_groups = damon_sysfs_watermarks_groups,
297+
};
298+
116299
/*
117300
* scheme/weights directory
118301
*/
@@ -469,6 +652,7 @@ struct damon_sysfs_scheme {
469652
enum damos_action action;
470653
struct damon_sysfs_access_pattern *access_pattern;
471654
struct damon_sysfs_quotas *quotas;
655+
struct damon_sysfs_watermarks *watermarks;
472656
};
473657

474658
/* This should match with enum damos_action */
@@ -541,6 +725,24 @@ static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
541725
return err;
542726
}
543727

728+
static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
729+
{
730+
struct damon_sysfs_watermarks *watermarks =
731+
damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
732+
int err;
733+
734+
if (!watermarks)
735+
return -ENOMEM;
736+
err = kobject_init_and_add(&watermarks->kobj,
737+
&damon_sysfs_watermarks_ktype, &scheme->kobj,
738+
"watermarks");
739+
if (err)
740+
kobject_put(&watermarks->kobj);
741+
else
742+
scheme->watermarks = watermarks;
743+
return err;
744+
}
745+
544746
static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
545747
{
546748
int err;
@@ -551,8 +753,14 @@ static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
551753
err = damon_sysfs_scheme_set_quotas(scheme);
552754
if (err)
553755
goto put_access_pattern_out;
756+
err = damon_sysfs_scheme_set_watermarks(scheme);
757+
if (err)
758+
goto put_quotas_access_pattern_out;
554759
return 0;
555760

761+
put_quotas_access_pattern_out:
762+
kobject_put(&scheme->quotas->kobj);
763+
scheme->quotas = NULL;
556764
put_access_pattern_out:
557765
kobject_put(&scheme->access_pattern->kobj);
558766
scheme->access_pattern = NULL;
@@ -565,6 +773,7 @@ static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
565773
kobject_put(&scheme->access_pattern->kobj);
566774
damon_sysfs_quotas_rm_dirs(scheme->quotas);
567775
kobject_put(&scheme->quotas->kobj);
776+
kobject_put(&scheme->watermarks->kobj);
568777
}
569778

570779
static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -1805,6 +2014,7 @@ static struct damos *damon_sysfs_mk_scheme(
18052014
sysfs_scheme->access_pattern;
18062015
struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
18072016
struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
2017+
struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
18082018
struct damos_quota quota = {
18092019
.ms = sysfs_quotas->ms,
18102020
.sz = sysfs_quotas->sz,
@@ -1814,11 +2024,11 @@ static struct damos *damon_sysfs_mk_scheme(
18142024
.weight_age = sysfs_weights->age,
18152025
};
18162026
struct damos_watermarks wmarks = {
1817-
.metric = DAMOS_WMARK_NONE,
1818-
.interval = 0,
1819-
.high = 0,
1820-
.mid = 0,
1821-
.low = 0,
2027+
.metric = sysfs_wmarks->metric,
2028+
.interval = sysfs_wmarks->interval_us,
2029+
.high = sysfs_wmarks->high,
2030+
.mid = sysfs_wmarks->mid,
2031+
.low = sysfs_wmarks->low,
18222032
};
18232033

18242034
return damon_new_scheme(pattern->sz->min, pattern->sz->max,

0 commit comments

Comments
 (0)