Skip to content

Commit 1c78b2b

Browse files
sjp38torvalds
authored andcommitted
mm/damon/sysfs: support schemes prioritization
This commit makes DAMON sysfs interface supports the DAMOS' regions prioritization weights feature under quotas limitation. Specifically, this commit adds 'weights' directory under each scheme directory and makes kdamond 'state' file writing respects the contents in the directory. /sys/kernel/mm/damon/admin │ kdamonds/nr │ │ 0/state,pid │ │ │ contexts/nr │ │ │ │ 0/operations │ │ │ │ │ monitoring_attrs/intervals/sample_us,aggr_us,update_us │ │ │ │ │ │ nr_regions/min,max │ │ │ │ │ targets/nr │ │ │ │ │ │ 0/pid │ │ │ │ │ │ │ regions/nr │ │ │ │ │ │ │ │ 0/start,end │ │ │ │ │ │ │ │ ... │ │ │ │ │ │ ... │ │ │ │ │ schemes/nr │ │ │ │ │ │ 0/action │ │ │ │ │ │ │ access_pattern/ │ │ │ │ │ │ │ │ sz/min,max │ │ │ │ │ │ │ │ nr_accesses/min,max │ │ │ │ │ │ │ │ age/min,max │ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms │ │ │ │ │ │ │ │ weights/ <- NEW DIRECTORY │ │ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil │ │ │ │ │ │ ... │ │ │ │ ... │ │ ... 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 9bbb820 commit 1c78b2b

File tree

1 file changed

+149
-3
lines changed

1 file changed

+149
-3
lines changed

mm/damon/sysfs.c

Lines changed: 149 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,130 @@ static struct kobj_type damon_sysfs_ul_range_ktype = {
113113
.default_groups = damon_sysfs_ul_range_groups,
114114
};
115115

116+
/*
117+
* scheme/weights directory
118+
*/
119+
120+
struct damon_sysfs_weights {
121+
struct kobject kobj;
122+
unsigned int sz;
123+
unsigned int nr_accesses;
124+
unsigned int age;
125+
};
126+
127+
static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
128+
unsigned int nr_accesses, unsigned int age)
129+
{
130+
struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
131+
GFP_KERNEL);
132+
133+
if (!weights)
134+
return NULL;
135+
weights->kobj = (struct kobject){};
136+
weights->sz = sz;
137+
weights->nr_accesses = nr_accesses;
138+
weights->age = age;
139+
return weights;
140+
}
141+
142+
static ssize_t sz_permil_show(struct kobject *kobj,
143+
struct kobj_attribute *attr, char *buf)
144+
{
145+
struct damon_sysfs_weights *weights = container_of(kobj,
146+
struct damon_sysfs_weights, kobj);
147+
148+
return sysfs_emit(buf, "%u\n", weights->sz);
149+
}
150+
151+
static ssize_t sz_permil_store(struct kobject *kobj,
152+
struct kobj_attribute *attr, const char *buf, size_t count)
153+
{
154+
struct damon_sysfs_weights *weights = container_of(kobj,
155+
struct damon_sysfs_weights, kobj);
156+
int err = kstrtouint(buf, 0, &weights->sz);
157+
158+
if (err)
159+
return -EINVAL;
160+
return count;
161+
}
162+
163+
static ssize_t nr_accesses_permil_show(struct kobject *kobj,
164+
struct kobj_attribute *attr, char *buf)
165+
{
166+
struct damon_sysfs_weights *weights = container_of(kobj,
167+
struct damon_sysfs_weights, kobj);
168+
169+
return sysfs_emit(buf, "%u\n", weights->nr_accesses);
170+
}
171+
172+
static ssize_t nr_accesses_permil_store(struct kobject *kobj,
173+
struct kobj_attribute *attr, const char *buf, size_t count)
174+
{
175+
struct damon_sysfs_weights *weights = container_of(kobj,
176+
struct damon_sysfs_weights, kobj);
177+
int err = kstrtouint(buf, 0, &weights->nr_accesses);
178+
179+
if (err)
180+
return -EINVAL;
181+
return count;
182+
}
183+
184+
static ssize_t age_permil_show(struct kobject *kobj,
185+
struct kobj_attribute *attr, char *buf)
186+
{
187+
struct damon_sysfs_weights *weights = container_of(kobj,
188+
struct damon_sysfs_weights, kobj);
189+
190+
return sysfs_emit(buf, "%u\n", weights->age);
191+
}
192+
193+
static ssize_t age_permil_store(struct kobject *kobj,
194+
struct kobj_attribute *attr, const char *buf, size_t count)
195+
{
196+
struct damon_sysfs_weights *weights = container_of(kobj,
197+
struct damon_sysfs_weights, kobj);
198+
int err = kstrtouint(buf, 0, &weights->age);
199+
200+
if (err)
201+
return -EINVAL;
202+
return count;
203+
}
204+
205+
static void damon_sysfs_weights_release(struct kobject *kobj)
206+
{
207+
kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
208+
}
209+
210+
static struct kobj_attribute damon_sysfs_weights_sz_attr =
211+
__ATTR_RW_MODE(sz_permil, 0600);
212+
213+
static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
214+
__ATTR_RW_MODE(nr_accesses_permil, 0600);
215+
216+
static struct kobj_attribute damon_sysfs_weights_age_attr =
217+
__ATTR_RW_MODE(age_permil, 0600);
218+
219+
static struct attribute *damon_sysfs_weights_attrs[] = {
220+
&damon_sysfs_weights_sz_attr.attr,
221+
&damon_sysfs_weights_nr_accesses_attr.attr,
222+
&damon_sysfs_weights_age_attr.attr,
223+
NULL,
224+
};
225+
ATTRIBUTE_GROUPS(damon_sysfs_weights);
226+
227+
static struct kobj_type damon_sysfs_weights_ktype = {
228+
.release = damon_sysfs_weights_release,
229+
.sysfs_ops = &kobj_sysfs_ops,
230+
.default_groups = damon_sysfs_weights_groups,
231+
};
232+
116233
/*
117234
* quotas directory
118235
*/
119236

120237
struct damon_sysfs_quotas {
121238
struct kobject kobj;
239+
struct damon_sysfs_weights *weights;
122240
unsigned long ms;
123241
unsigned long sz;
124242
unsigned long reset_interval_ms;
@@ -129,6 +247,29 @@ static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
129247
return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
130248
}
131249

250+
static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
251+
{
252+
struct damon_sysfs_weights *weights;
253+
int err;
254+
255+
weights = damon_sysfs_weights_alloc(0, 0, 0);
256+
if (!weights)
257+
return -ENOMEM;
258+
259+
err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
260+
&quotas->kobj, "weights");
261+
if (err)
262+
kobject_put(&weights->kobj);
263+
else
264+
quotas->weights = weights;
265+
return err;
266+
}
267+
268+
static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
269+
{
270+
kobject_put(&quotas->weights->kobj);
271+
}
272+
132273
static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
133274
char *buf)
134275
{
@@ -387,6 +528,9 @@ static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
387528
return -ENOMEM;
388529
err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
389530
&scheme->kobj, "quotas");
531+
if (err)
532+
goto out;
533+
err = damon_sysfs_quotas_add_dirs(quotas);
390534
if (err)
391535
goto out;
392536
scheme->quotas = quotas;
@@ -419,6 +563,7 @@ static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
419563
{
420564
damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
421565
kobject_put(&scheme->access_pattern->kobj);
566+
damon_sysfs_quotas_rm_dirs(scheme->quotas);
422567
kobject_put(&scheme->quotas->kobj);
423568
}
424569

@@ -1659,13 +1804,14 @@ static struct damos *damon_sysfs_mk_scheme(
16591804
struct damon_sysfs_access_pattern *pattern =
16601805
sysfs_scheme->access_pattern;
16611806
struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1807+
struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
16621808
struct damos_quota quota = {
16631809
.ms = sysfs_quotas->ms,
16641810
.sz = sysfs_quotas->sz,
16651811
.reset_interval = sysfs_quotas->reset_interval_ms,
1666-
.weight_sz = 1000,
1667-
.weight_nr_accesses = 1000,
1668-
.weight_age = 1000,
1812+
.weight_sz = sysfs_weights->sz,
1813+
.weight_nr_accesses = sysfs_weights->nr_accesses,
1814+
.weight_age = sysfs_weights->age,
16691815
};
16701816
struct damos_watermarks wmarks = {
16711817
.metric = DAMOS_WMARK_NONE,

0 commit comments

Comments
 (0)