cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sysfs.c (71401B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * DAMON sysfs Interface
      4 *
      5 * Copyright (c) 2022 SeongJae Park <sj@kernel.org>
      6 */
      7
      8#include <linux/damon.h>
      9#include <linux/kobject.h>
     10#include <linux/pid.h>
     11#include <linux/sched.h>
     12#include <linux/slab.h>
     13
     14static DEFINE_MUTEX(damon_sysfs_lock);
     15
     16/*
     17 * unsigned long range directory
     18 */
     19
     20struct damon_sysfs_ul_range {
     21	struct kobject kobj;
     22	unsigned long min;
     23	unsigned long max;
     24};
     25
     26static struct damon_sysfs_ul_range *damon_sysfs_ul_range_alloc(
     27		unsigned long min,
     28		unsigned long max)
     29{
     30	struct damon_sysfs_ul_range *range = kmalloc(sizeof(*range),
     31			GFP_KERNEL);
     32
     33	if (!range)
     34		return NULL;
     35	range->kobj = (struct kobject){};
     36	range->min = min;
     37	range->max = max;
     38
     39	return range;
     40}
     41
     42static ssize_t min_show(struct kobject *kobj, struct kobj_attribute *attr,
     43		char *buf)
     44{
     45	struct damon_sysfs_ul_range *range = container_of(kobj,
     46			struct damon_sysfs_ul_range, kobj);
     47
     48	return sysfs_emit(buf, "%lu\n", range->min);
     49}
     50
     51static ssize_t min_store(struct kobject *kobj, struct kobj_attribute *attr,
     52		const char *buf, size_t count)
     53{
     54	struct damon_sysfs_ul_range *range = container_of(kobj,
     55			struct damon_sysfs_ul_range, kobj);
     56	unsigned long min;
     57	int err;
     58
     59	err = kstrtoul(buf, 0, &min);
     60	if (err)
     61		return -EINVAL;
     62
     63	range->min = min;
     64	return count;
     65}
     66
     67static ssize_t max_show(struct kobject *kobj, struct kobj_attribute *attr,
     68		char *buf)
     69{
     70	struct damon_sysfs_ul_range *range = container_of(kobj,
     71			struct damon_sysfs_ul_range, kobj);
     72
     73	return sysfs_emit(buf, "%lu\n", range->max);
     74}
     75
     76static ssize_t max_store(struct kobject *kobj, struct kobj_attribute *attr,
     77		const char *buf, size_t count)
     78{
     79	struct damon_sysfs_ul_range *range = container_of(kobj,
     80			struct damon_sysfs_ul_range, kobj);
     81	unsigned long max;
     82	int err;
     83
     84	err = kstrtoul(buf, 0, &max);
     85	if (err)
     86		return -EINVAL;
     87
     88	range->max = max;
     89	return count;
     90}
     91
     92static void damon_sysfs_ul_range_release(struct kobject *kobj)
     93{
     94	kfree(container_of(kobj, struct damon_sysfs_ul_range, kobj));
     95}
     96
     97static struct kobj_attribute damon_sysfs_ul_range_min_attr =
     98		__ATTR_RW_MODE(min, 0600);
     99
    100static struct kobj_attribute damon_sysfs_ul_range_max_attr =
    101		__ATTR_RW_MODE(max, 0600);
    102
    103static struct attribute *damon_sysfs_ul_range_attrs[] = {
    104	&damon_sysfs_ul_range_min_attr.attr,
    105	&damon_sysfs_ul_range_max_attr.attr,
    106	NULL,
    107};
    108ATTRIBUTE_GROUPS(damon_sysfs_ul_range);
    109
    110static struct kobj_type damon_sysfs_ul_range_ktype = {
    111	.release = damon_sysfs_ul_range_release,
    112	.sysfs_ops = &kobj_sysfs_ops,
    113	.default_groups = damon_sysfs_ul_range_groups,
    114};
    115
    116/*
    117 * schemes/stats directory
    118 */
    119
    120struct damon_sysfs_stats {
    121	struct kobject kobj;
    122	unsigned long nr_tried;
    123	unsigned long sz_tried;
    124	unsigned long nr_applied;
    125	unsigned long sz_applied;
    126	unsigned long qt_exceeds;
    127};
    128
    129static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
    130{
    131	return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
    132}
    133
    134static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
    135		char *buf)
    136{
    137	struct damon_sysfs_stats *stats = container_of(kobj,
    138			struct damon_sysfs_stats, kobj);
    139
    140	return sysfs_emit(buf, "%lu\n", stats->nr_tried);
    141}
    142
    143static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
    144		char *buf)
    145{
    146	struct damon_sysfs_stats *stats = container_of(kobj,
    147			struct damon_sysfs_stats, kobj);
    148
    149	return sysfs_emit(buf, "%lu\n", stats->sz_tried);
    150}
    151
    152static ssize_t nr_applied_show(struct kobject *kobj,
    153		struct kobj_attribute *attr, char *buf)
    154{
    155	struct damon_sysfs_stats *stats = container_of(kobj,
    156			struct damon_sysfs_stats, kobj);
    157
    158	return sysfs_emit(buf, "%lu\n", stats->nr_applied);
    159}
    160
    161static ssize_t sz_applied_show(struct kobject *kobj,
    162		struct kobj_attribute *attr, char *buf)
    163{
    164	struct damon_sysfs_stats *stats = container_of(kobj,
    165			struct damon_sysfs_stats, kobj);
    166
    167	return sysfs_emit(buf, "%lu\n", stats->sz_applied);
    168}
    169
    170static ssize_t qt_exceeds_show(struct kobject *kobj,
    171		struct kobj_attribute *attr, char *buf)
    172{
    173	struct damon_sysfs_stats *stats = container_of(kobj,
    174			struct damon_sysfs_stats, kobj);
    175
    176	return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
    177}
    178
    179static void damon_sysfs_stats_release(struct kobject *kobj)
    180{
    181	kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
    182}
    183
    184static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
    185		__ATTR_RO_MODE(nr_tried, 0400);
    186
    187static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
    188		__ATTR_RO_MODE(sz_tried, 0400);
    189
    190static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
    191		__ATTR_RO_MODE(nr_applied, 0400);
    192
    193static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
    194		__ATTR_RO_MODE(sz_applied, 0400);
    195
    196static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
    197		__ATTR_RO_MODE(qt_exceeds, 0400);
    198
    199static struct attribute *damon_sysfs_stats_attrs[] = {
    200	&damon_sysfs_stats_nr_tried_attr.attr,
    201	&damon_sysfs_stats_sz_tried_attr.attr,
    202	&damon_sysfs_stats_nr_applied_attr.attr,
    203	&damon_sysfs_stats_sz_applied_attr.attr,
    204	&damon_sysfs_stats_qt_exceeds_attr.attr,
    205	NULL,
    206};
    207ATTRIBUTE_GROUPS(damon_sysfs_stats);
    208
    209static struct kobj_type damon_sysfs_stats_ktype = {
    210	.release = damon_sysfs_stats_release,
    211	.sysfs_ops = &kobj_sysfs_ops,
    212	.default_groups = damon_sysfs_stats_groups,
    213};
    214
    215/*
    216 * watermarks directory
    217 */
    218
    219struct damon_sysfs_watermarks {
    220	struct kobject kobj;
    221	enum damos_wmark_metric metric;
    222	unsigned long interval_us;
    223	unsigned long high;
    224	unsigned long mid;
    225	unsigned long low;
    226};
    227
    228static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
    229		enum damos_wmark_metric metric, unsigned long interval_us,
    230		unsigned long high, unsigned long mid, unsigned long low)
    231{
    232	struct damon_sysfs_watermarks *watermarks = kmalloc(
    233			sizeof(*watermarks), GFP_KERNEL);
    234
    235	if (!watermarks)
    236		return NULL;
    237	watermarks->kobj = (struct kobject){};
    238	watermarks->metric = metric;
    239	watermarks->interval_us = interval_us;
    240	watermarks->high = high;
    241	watermarks->mid = mid;
    242	watermarks->low = low;
    243	return watermarks;
    244}
    245
    246/* Should match with enum damos_wmark_metric */
    247static const char * const damon_sysfs_wmark_metric_strs[] = {
    248	"none",
    249	"free_mem_rate",
    250};
    251
    252static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
    253		char *buf)
    254{
    255	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    256			struct damon_sysfs_watermarks, kobj);
    257
    258	return sysfs_emit(buf, "%s\n",
    259			damon_sysfs_wmark_metric_strs[watermarks->metric]);
    260}
    261
    262static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
    263		const char *buf, size_t count)
    264{
    265	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    266			struct damon_sysfs_watermarks, kobj);
    267	enum damos_wmark_metric metric;
    268
    269	for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
    270		if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
    271			watermarks->metric = metric;
    272			return count;
    273		}
    274	}
    275	return -EINVAL;
    276}
    277
    278static ssize_t interval_us_show(struct kobject *kobj,
    279		struct kobj_attribute *attr, char *buf)
    280{
    281	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    282			struct damon_sysfs_watermarks, kobj);
    283
    284	return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
    285}
    286
    287static ssize_t interval_us_store(struct kobject *kobj,
    288		struct kobj_attribute *attr, const char *buf, size_t count)
    289{
    290	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    291			struct damon_sysfs_watermarks, kobj);
    292	int err = kstrtoul(buf, 0, &watermarks->interval_us);
    293
    294	if (err)
    295		return -EINVAL;
    296	return count;
    297}
    298
    299static ssize_t high_show(struct kobject *kobj,
    300		struct kobj_attribute *attr, char *buf)
    301{
    302	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    303			struct damon_sysfs_watermarks, kobj);
    304
    305	return sysfs_emit(buf, "%lu\n", watermarks->high);
    306}
    307
    308static ssize_t high_store(struct kobject *kobj,
    309		struct kobj_attribute *attr, const char *buf, size_t count)
    310{
    311	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    312			struct damon_sysfs_watermarks, kobj);
    313	int err = kstrtoul(buf, 0, &watermarks->high);
    314
    315	if (err)
    316		return -EINVAL;
    317	return count;
    318}
    319
    320static ssize_t mid_show(struct kobject *kobj,
    321		struct kobj_attribute *attr, char *buf)
    322{
    323	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    324			struct damon_sysfs_watermarks, kobj);
    325
    326	return sysfs_emit(buf, "%lu\n", watermarks->mid);
    327}
    328
    329static ssize_t mid_store(struct kobject *kobj,
    330		struct kobj_attribute *attr, const char *buf, size_t count)
    331{
    332	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    333			struct damon_sysfs_watermarks, kobj);
    334	int err = kstrtoul(buf, 0, &watermarks->mid);
    335
    336	if (err)
    337		return -EINVAL;
    338	return count;
    339}
    340
    341static ssize_t low_show(struct kobject *kobj,
    342		struct kobj_attribute *attr, char *buf)
    343{
    344	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    345			struct damon_sysfs_watermarks, kobj);
    346
    347	return sysfs_emit(buf, "%lu\n", watermarks->low);
    348}
    349
    350static ssize_t low_store(struct kobject *kobj,
    351		struct kobj_attribute *attr, const char *buf, size_t count)
    352{
    353	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
    354			struct damon_sysfs_watermarks, kobj);
    355	int err = kstrtoul(buf, 0, &watermarks->low);
    356
    357	if (err)
    358		return -EINVAL;
    359	return count;
    360}
    361
    362static void damon_sysfs_watermarks_release(struct kobject *kobj)
    363{
    364	kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
    365}
    366
    367static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
    368		__ATTR_RW_MODE(metric, 0600);
    369
    370static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
    371		__ATTR_RW_MODE(interval_us, 0600);
    372
    373static struct kobj_attribute damon_sysfs_watermarks_high_attr =
    374		__ATTR_RW_MODE(high, 0600);
    375
    376static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
    377		__ATTR_RW_MODE(mid, 0600);
    378
    379static struct kobj_attribute damon_sysfs_watermarks_low_attr =
    380		__ATTR_RW_MODE(low, 0600);
    381
    382static struct attribute *damon_sysfs_watermarks_attrs[] = {
    383	&damon_sysfs_watermarks_metric_attr.attr,
    384	&damon_sysfs_watermarks_interval_us_attr.attr,
    385	&damon_sysfs_watermarks_high_attr.attr,
    386	&damon_sysfs_watermarks_mid_attr.attr,
    387	&damon_sysfs_watermarks_low_attr.attr,
    388	NULL,
    389};
    390ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
    391
    392static struct kobj_type damon_sysfs_watermarks_ktype = {
    393	.release = damon_sysfs_watermarks_release,
    394	.sysfs_ops = &kobj_sysfs_ops,
    395	.default_groups = damon_sysfs_watermarks_groups,
    396};
    397
    398/*
    399 * scheme/weights directory
    400 */
    401
    402struct damon_sysfs_weights {
    403	struct kobject kobj;
    404	unsigned int sz;
    405	unsigned int nr_accesses;
    406	unsigned int age;
    407};
    408
    409static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
    410		unsigned int nr_accesses, unsigned int age)
    411{
    412	struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
    413			GFP_KERNEL);
    414
    415	if (!weights)
    416		return NULL;
    417	weights->kobj = (struct kobject){};
    418	weights->sz = sz;
    419	weights->nr_accesses = nr_accesses;
    420	weights->age = age;
    421	return weights;
    422}
    423
    424static ssize_t sz_permil_show(struct kobject *kobj,
    425		struct kobj_attribute *attr, char *buf)
    426{
    427	struct damon_sysfs_weights *weights = container_of(kobj,
    428			struct damon_sysfs_weights, kobj);
    429
    430	return sysfs_emit(buf, "%u\n", weights->sz);
    431}
    432
    433static ssize_t sz_permil_store(struct kobject *kobj,
    434		struct kobj_attribute *attr, const char *buf, size_t count)
    435{
    436	struct damon_sysfs_weights *weights = container_of(kobj,
    437			struct damon_sysfs_weights, kobj);
    438	int err = kstrtouint(buf, 0, &weights->sz);
    439
    440	if (err)
    441		return -EINVAL;
    442	return count;
    443}
    444
    445static ssize_t nr_accesses_permil_show(struct kobject *kobj,
    446		struct kobj_attribute *attr, char *buf)
    447{
    448	struct damon_sysfs_weights *weights = container_of(kobj,
    449			struct damon_sysfs_weights, kobj);
    450
    451	return sysfs_emit(buf, "%u\n", weights->nr_accesses);
    452}
    453
    454static ssize_t nr_accesses_permil_store(struct kobject *kobj,
    455		struct kobj_attribute *attr, const char *buf, size_t count)
    456{
    457	struct damon_sysfs_weights *weights = container_of(kobj,
    458			struct damon_sysfs_weights, kobj);
    459	int err = kstrtouint(buf, 0, &weights->nr_accesses);
    460
    461	if (err)
    462		return -EINVAL;
    463	return count;
    464}
    465
    466static ssize_t age_permil_show(struct kobject *kobj,
    467		struct kobj_attribute *attr, char *buf)
    468{
    469	struct damon_sysfs_weights *weights = container_of(kobj,
    470			struct damon_sysfs_weights, kobj);
    471
    472	return sysfs_emit(buf, "%u\n", weights->age);
    473}
    474
    475static ssize_t age_permil_store(struct kobject *kobj,
    476		struct kobj_attribute *attr, const char *buf, size_t count)
    477{
    478	struct damon_sysfs_weights *weights = container_of(kobj,
    479			struct damon_sysfs_weights, kobj);
    480	int err = kstrtouint(buf, 0, &weights->age);
    481
    482	if (err)
    483		return -EINVAL;
    484	return count;
    485}
    486
    487static void damon_sysfs_weights_release(struct kobject *kobj)
    488{
    489	kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
    490}
    491
    492static struct kobj_attribute damon_sysfs_weights_sz_attr =
    493		__ATTR_RW_MODE(sz_permil, 0600);
    494
    495static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
    496		__ATTR_RW_MODE(nr_accesses_permil, 0600);
    497
    498static struct kobj_attribute damon_sysfs_weights_age_attr =
    499		__ATTR_RW_MODE(age_permil, 0600);
    500
    501static struct attribute *damon_sysfs_weights_attrs[] = {
    502	&damon_sysfs_weights_sz_attr.attr,
    503	&damon_sysfs_weights_nr_accesses_attr.attr,
    504	&damon_sysfs_weights_age_attr.attr,
    505	NULL,
    506};
    507ATTRIBUTE_GROUPS(damon_sysfs_weights);
    508
    509static struct kobj_type damon_sysfs_weights_ktype = {
    510	.release = damon_sysfs_weights_release,
    511	.sysfs_ops = &kobj_sysfs_ops,
    512	.default_groups = damon_sysfs_weights_groups,
    513};
    514
    515/*
    516 * quotas directory
    517 */
    518
    519struct damon_sysfs_quotas {
    520	struct kobject kobj;
    521	struct damon_sysfs_weights *weights;
    522	unsigned long ms;
    523	unsigned long sz;
    524	unsigned long reset_interval_ms;
    525};
    526
    527static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
    528{
    529	return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
    530}
    531
    532static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
    533{
    534	struct damon_sysfs_weights *weights;
    535	int err;
    536
    537	weights = damon_sysfs_weights_alloc(0, 0, 0);
    538	if (!weights)
    539		return -ENOMEM;
    540
    541	err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
    542			&quotas->kobj, "weights");
    543	if (err)
    544		kobject_put(&weights->kobj);
    545	else
    546		quotas->weights = weights;
    547	return err;
    548}
    549
    550static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
    551{
    552	kobject_put(&quotas->weights->kobj);
    553}
    554
    555static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
    556		char *buf)
    557{
    558	struct damon_sysfs_quotas *quotas = container_of(kobj,
    559			struct damon_sysfs_quotas, kobj);
    560
    561	return sysfs_emit(buf, "%lu\n", quotas->ms);
    562}
    563
    564static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
    565		const char *buf, size_t count)
    566{
    567	struct damon_sysfs_quotas *quotas = container_of(kobj,
    568			struct damon_sysfs_quotas, kobj);
    569	int err = kstrtoul(buf, 0, &quotas->ms);
    570
    571	if (err)
    572		return -EINVAL;
    573	return count;
    574}
    575
    576static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
    577		char *buf)
    578{
    579	struct damon_sysfs_quotas *quotas = container_of(kobj,
    580			struct damon_sysfs_quotas, kobj);
    581
    582	return sysfs_emit(buf, "%lu\n", quotas->sz);
    583}
    584
    585static ssize_t bytes_store(struct kobject *kobj,
    586		struct kobj_attribute *attr, const char *buf, size_t count)
    587{
    588	struct damon_sysfs_quotas *quotas = container_of(kobj,
    589			struct damon_sysfs_quotas, kobj);
    590	int err = kstrtoul(buf, 0, &quotas->sz);
    591
    592	if (err)
    593		return -EINVAL;
    594	return count;
    595}
    596
    597static ssize_t reset_interval_ms_show(struct kobject *kobj,
    598		struct kobj_attribute *attr, char *buf)
    599{
    600	struct damon_sysfs_quotas *quotas = container_of(kobj,
    601			struct damon_sysfs_quotas, kobj);
    602
    603	return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
    604}
    605
    606static ssize_t reset_interval_ms_store(struct kobject *kobj,
    607		struct kobj_attribute *attr, const char *buf, size_t count)
    608{
    609	struct damon_sysfs_quotas *quotas = container_of(kobj,
    610			struct damon_sysfs_quotas, kobj);
    611	int err = kstrtoul(buf, 0, &quotas->reset_interval_ms);
    612
    613	if (err)
    614		return -EINVAL;
    615	return count;
    616}
    617
    618static void damon_sysfs_quotas_release(struct kobject *kobj)
    619{
    620	kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
    621}
    622
    623static struct kobj_attribute damon_sysfs_quotas_ms_attr =
    624		__ATTR_RW_MODE(ms, 0600);
    625
    626static struct kobj_attribute damon_sysfs_quotas_sz_attr =
    627		__ATTR_RW_MODE(bytes, 0600);
    628
    629static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
    630		__ATTR_RW_MODE(reset_interval_ms, 0600);
    631
    632static struct attribute *damon_sysfs_quotas_attrs[] = {
    633	&damon_sysfs_quotas_ms_attr.attr,
    634	&damon_sysfs_quotas_sz_attr.attr,
    635	&damon_sysfs_quotas_reset_interval_ms_attr.attr,
    636	NULL,
    637};
    638ATTRIBUTE_GROUPS(damon_sysfs_quotas);
    639
    640static struct kobj_type damon_sysfs_quotas_ktype = {
    641	.release = damon_sysfs_quotas_release,
    642	.sysfs_ops = &kobj_sysfs_ops,
    643	.default_groups = damon_sysfs_quotas_groups,
    644};
    645
    646/*
    647 * access_pattern directory
    648 */
    649
    650struct damon_sysfs_access_pattern {
    651	struct kobject kobj;
    652	struct damon_sysfs_ul_range *sz;
    653	struct damon_sysfs_ul_range *nr_accesses;
    654	struct damon_sysfs_ul_range *age;
    655};
    656
    657static
    658struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
    659{
    660	struct damon_sysfs_access_pattern *access_pattern =
    661		kmalloc(sizeof(*access_pattern), GFP_KERNEL);
    662
    663	if (!access_pattern)
    664		return NULL;
    665	access_pattern->kobj = (struct kobject){};
    666	return access_pattern;
    667}
    668
    669static int damon_sysfs_access_pattern_add_range_dir(
    670		struct damon_sysfs_access_pattern *access_pattern,
    671		struct damon_sysfs_ul_range **range_dir_ptr,
    672		char *name)
    673{
    674	struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
    675	int err;
    676
    677	if (!range)
    678		return -ENOMEM;
    679	err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
    680			&access_pattern->kobj, name);
    681	if (err)
    682		kobject_put(&range->kobj);
    683	else
    684		*range_dir_ptr = range;
    685	return err;
    686}
    687
    688static int damon_sysfs_access_pattern_add_dirs(
    689		struct damon_sysfs_access_pattern *access_pattern)
    690{
    691	int err;
    692
    693	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
    694			&access_pattern->sz, "sz");
    695	if (err)
    696		goto put_sz_out;
    697
    698	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
    699			&access_pattern->nr_accesses, "nr_accesses");
    700	if (err)
    701		goto put_nr_accesses_sz_out;
    702
    703	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
    704			&access_pattern->age, "age");
    705	if (err)
    706		goto put_age_nr_accesses_sz_out;
    707	return 0;
    708
    709put_age_nr_accesses_sz_out:
    710	kobject_put(&access_pattern->age->kobj);
    711	access_pattern->age = NULL;
    712put_nr_accesses_sz_out:
    713	kobject_put(&access_pattern->nr_accesses->kobj);
    714	access_pattern->nr_accesses = NULL;
    715put_sz_out:
    716	kobject_put(&access_pattern->sz->kobj);
    717	access_pattern->sz = NULL;
    718	return err;
    719}
    720
    721static void damon_sysfs_access_pattern_rm_dirs(
    722		struct damon_sysfs_access_pattern *access_pattern)
    723{
    724	kobject_put(&access_pattern->sz->kobj);
    725	kobject_put(&access_pattern->nr_accesses->kobj);
    726	kobject_put(&access_pattern->age->kobj);
    727}
    728
    729static void damon_sysfs_access_pattern_release(struct kobject *kobj)
    730{
    731	kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
    732}
    733
    734static struct attribute *damon_sysfs_access_pattern_attrs[] = {
    735	NULL,
    736};
    737ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
    738
    739static struct kobj_type damon_sysfs_access_pattern_ktype = {
    740	.release = damon_sysfs_access_pattern_release,
    741	.sysfs_ops = &kobj_sysfs_ops,
    742	.default_groups = damon_sysfs_access_pattern_groups,
    743};
    744
    745/*
    746 * scheme directory
    747 */
    748
    749struct damon_sysfs_scheme {
    750	struct kobject kobj;
    751	enum damos_action action;
    752	struct damon_sysfs_access_pattern *access_pattern;
    753	struct damon_sysfs_quotas *quotas;
    754	struct damon_sysfs_watermarks *watermarks;
    755	struct damon_sysfs_stats *stats;
    756};
    757
    758/* This should match with enum damos_action */
    759static const char * const damon_sysfs_damos_action_strs[] = {
    760	"willneed",
    761	"cold",
    762	"pageout",
    763	"hugepage",
    764	"nohugepage",
    765	"stat",
    766};
    767
    768static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
    769		enum damos_action action)
    770{
    771	struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
    772				GFP_KERNEL);
    773
    774	if (!scheme)
    775		return NULL;
    776	scheme->kobj = (struct kobject){};
    777	scheme->action = action;
    778	return scheme;
    779}
    780
    781static int damon_sysfs_scheme_set_access_pattern(
    782		struct damon_sysfs_scheme *scheme)
    783{
    784	struct damon_sysfs_access_pattern *access_pattern;
    785	int err;
    786
    787	access_pattern = damon_sysfs_access_pattern_alloc();
    788	if (!access_pattern)
    789		return -ENOMEM;
    790	err = kobject_init_and_add(&access_pattern->kobj,
    791			&damon_sysfs_access_pattern_ktype, &scheme->kobj,
    792			"access_pattern");
    793	if (err)
    794		goto out;
    795	err = damon_sysfs_access_pattern_add_dirs(access_pattern);
    796	if (err)
    797		goto out;
    798	scheme->access_pattern = access_pattern;
    799	return 0;
    800
    801out:
    802	kobject_put(&access_pattern->kobj);
    803	return err;
    804}
    805
    806static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
    807{
    808	struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
    809	int err;
    810
    811	if (!quotas)
    812		return -ENOMEM;
    813	err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
    814			&scheme->kobj, "quotas");
    815	if (err)
    816		goto out;
    817	err = damon_sysfs_quotas_add_dirs(quotas);
    818	if (err)
    819		goto out;
    820	scheme->quotas = quotas;
    821	return 0;
    822
    823out:
    824	kobject_put(&quotas->kobj);
    825	return err;
    826}
    827
    828static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
    829{
    830	struct damon_sysfs_watermarks *watermarks =
    831		damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
    832	int err;
    833
    834	if (!watermarks)
    835		return -ENOMEM;
    836	err = kobject_init_and_add(&watermarks->kobj,
    837			&damon_sysfs_watermarks_ktype, &scheme->kobj,
    838			"watermarks");
    839	if (err)
    840		kobject_put(&watermarks->kobj);
    841	else
    842		scheme->watermarks = watermarks;
    843	return err;
    844}
    845
    846static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
    847{
    848	struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
    849	int err;
    850
    851	if (!stats)
    852		return -ENOMEM;
    853	err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
    854			&scheme->kobj, "stats");
    855	if (err)
    856		kobject_put(&stats->kobj);
    857	else
    858		scheme->stats = stats;
    859	return err;
    860}
    861
    862static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
    863{
    864	int err;
    865
    866	err = damon_sysfs_scheme_set_access_pattern(scheme);
    867	if (err)
    868		return err;
    869	err = damon_sysfs_scheme_set_quotas(scheme);
    870	if (err)
    871		goto put_access_pattern_out;
    872	err = damon_sysfs_scheme_set_watermarks(scheme);
    873	if (err)
    874		goto put_quotas_access_pattern_out;
    875	err = damon_sysfs_scheme_set_stats(scheme);
    876	if (err)
    877		goto put_watermarks_quotas_access_pattern_out;
    878	return 0;
    879
    880put_watermarks_quotas_access_pattern_out:
    881	kobject_put(&scheme->watermarks->kobj);
    882	scheme->watermarks = NULL;
    883put_quotas_access_pattern_out:
    884	kobject_put(&scheme->quotas->kobj);
    885	scheme->quotas = NULL;
    886put_access_pattern_out:
    887	kobject_put(&scheme->access_pattern->kobj);
    888	scheme->access_pattern = NULL;
    889	return err;
    890}
    891
    892static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
    893{
    894	damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
    895	kobject_put(&scheme->access_pattern->kobj);
    896	damon_sysfs_quotas_rm_dirs(scheme->quotas);
    897	kobject_put(&scheme->quotas->kobj);
    898	kobject_put(&scheme->watermarks->kobj);
    899	kobject_put(&scheme->stats->kobj);
    900}
    901
    902static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
    903		char *buf)
    904{
    905	struct damon_sysfs_scheme *scheme = container_of(kobj,
    906			struct damon_sysfs_scheme, kobj);
    907
    908	return sysfs_emit(buf, "%s\n",
    909			damon_sysfs_damos_action_strs[scheme->action]);
    910}
    911
    912static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
    913		const char *buf, size_t count)
    914{
    915	struct damon_sysfs_scheme *scheme = container_of(kobj,
    916			struct damon_sysfs_scheme, kobj);
    917	enum damos_action action;
    918
    919	for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
    920		if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
    921			scheme->action = action;
    922			return count;
    923		}
    924	}
    925	return -EINVAL;
    926}
    927
    928static void damon_sysfs_scheme_release(struct kobject *kobj)
    929{
    930	kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
    931}
    932
    933static struct kobj_attribute damon_sysfs_scheme_action_attr =
    934		__ATTR_RW_MODE(action, 0600);
    935
    936static struct attribute *damon_sysfs_scheme_attrs[] = {
    937	&damon_sysfs_scheme_action_attr.attr,
    938	NULL,
    939};
    940ATTRIBUTE_GROUPS(damon_sysfs_scheme);
    941
    942static struct kobj_type damon_sysfs_scheme_ktype = {
    943	.release = damon_sysfs_scheme_release,
    944	.sysfs_ops = &kobj_sysfs_ops,
    945	.default_groups = damon_sysfs_scheme_groups,
    946};
    947
    948/*
    949 * schemes directory
    950 */
    951
    952struct damon_sysfs_schemes {
    953	struct kobject kobj;
    954	struct damon_sysfs_scheme **schemes_arr;
    955	int nr;
    956};
    957
    958static struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
    959{
    960	return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
    961}
    962
    963static void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
    964{
    965	struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
    966	int i;
    967
    968	for (i = 0; i < schemes->nr; i++) {
    969		damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
    970		kobject_put(&schemes_arr[i]->kobj);
    971	}
    972	schemes->nr = 0;
    973	kfree(schemes_arr);
    974	schemes->schemes_arr = NULL;
    975}
    976
    977static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
    978		int nr_schemes)
    979{
    980	struct damon_sysfs_scheme **schemes_arr, *scheme;
    981	int err, i;
    982
    983	damon_sysfs_schemes_rm_dirs(schemes);
    984	if (!nr_schemes)
    985		return 0;
    986
    987	schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
    988			GFP_KERNEL | __GFP_NOWARN);
    989	if (!schemes_arr)
    990		return -ENOMEM;
    991	schemes->schemes_arr = schemes_arr;
    992
    993	for (i = 0; i < nr_schemes; i++) {
    994		scheme = damon_sysfs_scheme_alloc(DAMOS_STAT);
    995		if (!scheme) {
    996			damon_sysfs_schemes_rm_dirs(schemes);
    997			return -ENOMEM;
    998		}
    999
   1000		err = kobject_init_and_add(&scheme->kobj,
   1001				&damon_sysfs_scheme_ktype, &schemes->kobj,
   1002				"%d", i);
   1003		if (err)
   1004			goto out;
   1005		err = damon_sysfs_scheme_add_dirs(scheme);
   1006		if (err)
   1007			goto out;
   1008
   1009		schemes_arr[i] = scheme;
   1010		schemes->nr++;
   1011	}
   1012	return 0;
   1013
   1014out:
   1015	damon_sysfs_schemes_rm_dirs(schemes);
   1016	kobject_put(&scheme->kobj);
   1017	return err;
   1018}
   1019
   1020static ssize_t nr_schemes_show(struct kobject *kobj,
   1021		struct kobj_attribute *attr, char *buf)
   1022{
   1023	struct damon_sysfs_schemes *schemes = container_of(kobj,
   1024			struct damon_sysfs_schemes, kobj);
   1025
   1026	return sysfs_emit(buf, "%d\n", schemes->nr);
   1027}
   1028
   1029static ssize_t nr_schemes_store(struct kobject *kobj,
   1030		struct kobj_attribute *attr, const char *buf, size_t count)
   1031{
   1032	struct damon_sysfs_schemes *schemes = container_of(kobj,
   1033			struct damon_sysfs_schemes, kobj);
   1034	int nr, err = kstrtoint(buf, 0, &nr);
   1035
   1036	if (err)
   1037		return err;
   1038	if (nr < 0)
   1039		return -EINVAL;
   1040
   1041	if (!mutex_trylock(&damon_sysfs_lock))
   1042		return -EBUSY;
   1043	err = damon_sysfs_schemes_add_dirs(schemes, nr);
   1044	mutex_unlock(&damon_sysfs_lock);
   1045	if (err)
   1046		return err;
   1047	return count;
   1048}
   1049
   1050static void damon_sysfs_schemes_release(struct kobject *kobj)
   1051{
   1052	kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
   1053}
   1054
   1055static struct kobj_attribute damon_sysfs_schemes_nr_attr =
   1056		__ATTR_RW_MODE(nr_schemes, 0600);
   1057
   1058static struct attribute *damon_sysfs_schemes_attrs[] = {
   1059	&damon_sysfs_schemes_nr_attr.attr,
   1060	NULL,
   1061};
   1062ATTRIBUTE_GROUPS(damon_sysfs_schemes);
   1063
   1064static struct kobj_type damon_sysfs_schemes_ktype = {
   1065	.release = damon_sysfs_schemes_release,
   1066	.sysfs_ops = &kobj_sysfs_ops,
   1067	.default_groups = damon_sysfs_schemes_groups,
   1068};
   1069
   1070/*
   1071 * init region directory
   1072 */
   1073
   1074struct damon_sysfs_region {
   1075	struct kobject kobj;
   1076	unsigned long start;
   1077	unsigned long end;
   1078};
   1079
   1080static struct damon_sysfs_region *damon_sysfs_region_alloc(
   1081		unsigned long start,
   1082		unsigned long end)
   1083{
   1084	struct damon_sysfs_region *region = kmalloc(sizeof(*region),
   1085			GFP_KERNEL);
   1086
   1087	if (!region)
   1088		return NULL;
   1089	region->kobj = (struct kobject){};
   1090	region->start = start;
   1091	region->end = end;
   1092	return region;
   1093}
   1094
   1095static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr,
   1096		char *buf)
   1097{
   1098	struct damon_sysfs_region *region = container_of(kobj,
   1099			struct damon_sysfs_region, kobj);
   1100
   1101	return sysfs_emit(buf, "%lu\n", region->start);
   1102}
   1103
   1104static ssize_t start_store(struct kobject *kobj, struct kobj_attribute *attr,
   1105		const char *buf, size_t count)
   1106{
   1107	struct damon_sysfs_region *region = container_of(kobj,
   1108			struct damon_sysfs_region, kobj);
   1109	int err = kstrtoul(buf, 0, &region->start);
   1110
   1111	if (err)
   1112		return -EINVAL;
   1113	return count;
   1114}
   1115
   1116static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr,
   1117		char *buf)
   1118{
   1119	struct damon_sysfs_region *region = container_of(kobj,
   1120			struct damon_sysfs_region, kobj);
   1121
   1122	return sysfs_emit(buf, "%lu\n", region->end);
   1123}
   1124
   1125static ssize_t end_store(struct kobject *kobj, struct kobj_attribute *attr,
   1126		const char *buf, size_t count)
   1127{
   1128	struct damon_sysfs_region *region = container_of(kobj,
   1129			struct damon_sysfs_region, kobj);
   1130	int err = kstrtoul(buf, 0, &region->end);
   1131
   1132	if (err)
   1133		return -EINVAL;
   1134	return count;
   1135}
   1136
   1137static void damon_sysfs_region_release(struct kobject *kobj)
   1138{
   1139	kfree(container_of(kobj, struct damon_sysfs_region, kobj));
   1140}
   1141
   1142static struct kobj_attribute damon_sysfs_region_start_attr =
   1143		__ATTR_RW_MODE(start, 0600);
   1144
   1145static struct kobj_attribute damon_sysfs_region_end_attr =
   1146		__ATTR_RW_MODE(end, 0600);
   1147
   1148static struct attribute *damon_sysfs_region_attrs[] = {
   1149	&damon_sysfs_region_start_attr.attr,
   1150	&damon_sysfs_region_end_attr.attr,
   1151	NULL,
   1152};
   1153ATTRIBUTE_GROUPS(damon_sysfs_region);
   1154
   1155static struct kobj_type damon_sysfs_region_ktype = {
   1156	.release = damon_sysfs_region_release,
   1157	.sysfs_ops = &kobj_sysfs_ops,
   1158	.default_groups = damon_sysfs_region_groups,
   1159};
   1160
   1161/*
   1162 * init_regions directory
   1163 */
   1164
   1165struct damon_sysfs_regions {
   1166	struct kobject kobj;
   1167	struct damon_sysfs_region **regions_arr;
   1168	int nr;
   1169};
   1170
   1171static struct damon_sysfs_regions *damon_sysfs_regions_alloc(void)
   1172{
   1173	return kzalloc(sizeof(struct damon_sysfs_regions), GFP_KERNEL);
   1174}
   1175
   1176static void damon_sysfs_regions_rm_dirs(struct damon_sysfs_regions *regions)
   1177{
   1178	struct damon_sysfs_region **regions_arr = regions->regions_arr;
   1179	int i;
   1180
   1181	for (i = 0; i < regions->nr; i++)
   1182		kobject_put(&regions_arr[i]->kobj);
   1183	regions->nr = 0;
   1184	kfree(regions_arr);
   1185	regions->regions_arr = NULL;
   1186}
   1187
   1188static int damon_sysfs_regions_add_dirs(struct damon_sysfs_regions *regions,
   1189		int nr_regions)
   1190{
   1191	struct damon_sysfs_region **regions_arr, *region;
   1192	int err, i;
   1193
   1194	damon_sysfs_regions_rm_dirs(regions);
   1195	if (!nr_regions)
   1196		return 0;
   1197
   1198	regions_arr = kmalloc_array(nr_regions, sizeof(*regions_arr),
   1199			GFP_KERNEL | __GFP_NOWARN);
   1200	if (!regions_arr)
   1201		return -ENOMEM;
   1202	regions->regions_arr = regions_arr;
   1203
   1204	for (i = 0; i < nr_regions; i++) {
   1205		region = damon_sysfs_region_alloc(0, 0);
   1206		if (!region) {
   1207			damon_sysfs_regions_rm_dirs(regions);
   1208			return -ENOMEM;
   1209		}
   1210
   1211		err = kobject_init_and_add(&region->kobj,
   1212				&damon_sysfs_region_ktype, &regions->kobj,
   1213				"%d", i);
   1214		if (err) {
   1215			kobject_put(&region->kobj);
   1216			damon_sysfs_regions_rm_dirs(regions);
   1217			return err;
   1218		}
   1219
   1220		regions_arr[i] = region;
   1221		regions->nr++;
   1222	}
   1223	return 0;
   1224}
   1225
   1226static ssize_t nr_regions_show(struct kobject *kobj,
   1227		struct kobj_attribute *attr, char *buf)
   1228{
   1229	struct damon_sysfs_regions *regions = container_of(kobj,
   1230			struct damon_sysfs_regions, kobj);
   1231
   1232	return sysfs_emit(buf, "%d\n", regions->nr);
   1233}
   1234
   1235static ssize_t nr_regions_store(struct kobject *kobj,
   1236		struct kobj_attribute *attr, const char *buf, size_t count)
   1237{
   1238	struct damon_sysfs_regions *regions = container_of(kobj,
   1239			struct damon_sysfs_regions, kobj);
   1240	int nr, err = kstrtoint(buf, 0, &nr);
   1241
   1242	if (err)
   1243		return err;
   1244	if (nr < 0)
   1245		return -EINVAL;
   1246
   1247	if (!mutex_trylock(&damon_sysfs_lock))
   1248		return -EBUSY;
   1249	err = damon_sysfs_regions_add_dirs(regions, nr);
   1250	mutex_unlock(&damon_sysfs_lock);
   1251	if (err)
   1252		return err;
   1253
   1254	return count;
   1255}
   1256
   1257static void damon_sysfs_regions_release(struct kobject *kobj)
   1258{
   1259	kfree(container_of(kobj, struct damon_sysfs_regions, kobj));
   1260}
   1261
   1262static struct kobj_attribute damon_sysfs_regions_nr_attr =
   1263		__ATTR_RW_MODE(nr_regions, 0600);
   1264
   1265static struct attribute *damon_sysfs_regions_attrs[] = {
   1266	&damon_sysfs_regions_nr_attr.attr,
   1267	NULL,
   1268};
   1269ATTRIBUTE_GROUPS(damon_sysfs_regions);
   1270
   1271static struct kobj_type damon_sysfs_regions_ktype = {
   1272	.release = damon_sysfs_regions_release,
   1273	.sysfs_ops = &kobj_sysfs_ops,
   1274	.default_groups = damon_sysfs_regions_groups,
   1275};
   1276
   1277/*
   1278 * target directory
   1279 */
   1280
   1281struct damon_sysfs_target {
   1282	struct kobject kobj;
   1283	struct damon_sysfs_regions *regions;
   1284	int pid;
   1285};
   1286
   1287static struct damon_sysfs_target *damon_sysfs_target_alloc(void)
   1288{
   1289	return kzalloc(sizeof(struct damon_sysfs_target), GFP_KERNEL);
   1290}
   1291
   1292static int damon_sysfs_target_add_dirs(struct damon_sysfs_target *target)
   1293{
   1294	struct damon_sysfs_regions *regions = damon_sysfs_regions_alloc();
   1295	int err;
   1296
   1297	if (!regions)
   1298		return -ENOMEM;
   1299
   1300	err = kobject_init_and_add(&regions->kobj, &damon_sysfs_regions_ktype,
   1301			&target->kobj, "regions");
   1302	if (err)
   1303		kobject_put(&regions->kobj);
   1304	else
   1305		target->regions = regions;
   1306	return err;
   1307}
   1308
   1309static void damon_sysfs_target_rm_dirs(struct damon_sysfs_target *target)
   1310{
   1311	damon_sysfs_regions_rm_dirs(target->regions);
   1312	kobject_put(&target->regions->kobj);
   1313}
   1314
   1315static ssize_t pid_target_show(struct kobject *kobj,
   1316		struct kobj_attribute *attr, char *buf)
   1317{
   1318	struct damon_sysfs_target *target = container_of(kobj,
   1319			struct damon_sysfs_target, kobj);
   1320
   1321	return sysfs_emit(buf, "%d\n", target->pid);
   1322}
   1323
   1324static ssize_t pid_target_store(struct kobject *kobj,
   1325		struct kobj_attribute *attr, const char *buf, size_t count)
   1326{
   1327	struct damon_sysfs_target *target = container_of(kobj,
   1328			struct damon_sysfs_target, kobj);
   1329	int err = kstrtoint(buf, 0, &target->pid);
   1330
   1331	if (err)
   1332		return -EINVAL;
   1333	return count;
   1334}
   1335
   1336static void damon_sysfs_target_release(struct kobject *kobj)
   1337{
   1338	kfree(container_of(kobj, struct damon_sysfs_target, kobj));
   1339}
   1340
   1341static struct kobj_attribute damon_sysfs_target_pid_attr =
   1342		__ATTR_RW_MODE(pid_target, 0600);
   1343
   1344static struct attribute *damon_sysfs_target_attrs[] = {
   1345	&damon_sysfs_target_pid_attr.attr,
   1346	NULL,
   1347};
   1348ATTRIBUTE_GROUPS(damon_sysfs_target);
   1349
   1350static struct kobj_type damon_sysfs_target_ktype = {
   1351	.release = damon_sysfs_target_release,
   1352	.sysfs_ops = &kobj_sysfs_ops,
   1353	.default_groups = damon_sysfs_target_groups,
   1354};
   1355
   1356/*
   1357 * targets directory
   1358 */
   1359
   1360struct damon_sysfs_targets {
   1361	struct kobject kobj;
   1362	struct damon_sysfs_target **targets_arr;
   1363	int nr;
   1364};
   1365
   1366static struct damon_sysfs_targets *damon_sysfs_targets_alloc(void)
   1367{
   1368	return kzalloc(sizeof(struct damon_sysfs_targets), GFP_KERNEL);
   1369}
   1370
   1371static void damon_sysfs_targets_rm_dirs(struct damon_sysfs_targets *targets)
   1372{
   1373	struct damon_sysfs_target **targets_arr = targets->targets_arr;
   1374	int i;
   1375
   1376	for (i = 0; i < targets->nr; i++) {
   1377		damon_sysfs_target_rm_dirs(targets_arr[i]);
   1378		kobject_put(&targets_arr[i]->kobj);
   1379	}
   1380	targets->nr = 0;
   1381	kfree(targets_arr);
   1382	targets->targets_arr = NULL;
   1383}
   1384
   1385static int damon_sysfs_targets_add_dirs(struct damon_sysfs_targets *targets,
   1386		int nr_targets)
   1387{
   1388	struct damon_sysfs_target **targets_arr, *target;
   1389	int err, i;
   1390
   1391	damon_sysfs_targets_rm_dirs(targets);
   1392	if (!nr_targets)
   1393		return 0;
   1394
   1395	targets_arr = kmalloc_array(nr_targets, sizeof(*targets_arr),
   1396			GFP_KERNEL | __GFP_NOWARN);
   1397	if (!targets_arr)
   1398		return -ENOMEM;
   1399	targets->targets_arr = targets_arr;
   1400
   1401	for (i = 0; i < nr_targets; i++) {
   1402		target = damon_sysfs_target_alloc();
   1403		if (!target) {
   1404			damon_sysfs_targets_rm_dirs(targets);
   1405			return -ENOMEM;
   1406		}
   1407
   1408		err = kobject_init_and_add(&target->kobj,
   1409				&damon_sysfs_target_ktype, &targets->kobj,
   1410				"%d", i);
   1411		if (err)
   1412			goto out;
   1413
   1414		err = damon_sysfs_target_add_dirs(target);
   1415		if (err)
   1416			goto out;
   1417
   1418		targets_arr[i] = target;
   1419		targets->nr++;
   1420	}
   1421	return 0;
   1422
   1423out:
   1424	damon_sysfs_targets_rm_dirs(targets);
   1425	kobject_put(&target->kobj);
   1426	return err;
   1427}
   1428
   1429static ssize_t nr_targets_show(struct kobject *kobj,
   1430		struct kobj_attribute *attr, char *buf)
   1431{
   1432	struct damon_sysfs_targets *targets = container_of(kobj,
   1433			struct damon_sysfs_targets, kobj);
   1434
   1435	return sysfs_emit(buf, "%d\n", targets->nr);
   1436}
   1437
   1438static ssize_t nr_targets_store(struct kobject *kobj,
   1439		struct kobj_attribute *attr, const char *buf, size_t count)
   1440{
   1441	struct damon_sysfs_targets *targets = container_of(kobj,
   1442			struct damon_sysfs_targets, kobj);
   1443	int nr, err = kstrtoint(buf, 0, &nr);
   1444
   1445	if (err)
   1446		return err;
   1447	if (nr < 0)
   1448		return -EINVAL;
   1449
   1450	if (!mutex_trylock(&damon_sysfs_lock))
   1451		return -EBUSY;
   1452	err = damon_sysfs_targets_add_dirs(targets, nr);
   1453	mutex_unlock(&damon_sysfs_lock);
   1454	if (err)
   1455		return err;
   1456
   1457	return count;
   1458}
   1459
   1460static void damon_sysfs_targets_release(struct kobject *kobj)
   1461{
   1462	kfree(container_of(kobj, struct damon_sysfs_targets, kobj));
   1463}
   1464
   1465static struct kobj_attribute damon_sysfs_targets_nr_attr =
   1466		__ATTR_RW_MODE(nr_targets, 0600);
   1467
   1468static struct attribute *damon_sysfs_targets_attrs[] = {
   1469	&damon_sysfs_targets_nr_attr.attr,
   1470	NULL,
   1471};
   1472ATTRIBUTE_GROUPS(damon_sysfs_targets);
   1473
   1474static struct kobj_type damon_sysfs_targets_ktype = {
   1475	.release = damon_sysfs_targets_release,
   1476	.sysfs_ops = &kobj_sysfs_ops,
   1477	.default_groups = damon_sysfs_targets_groups,
   1478};
   1479
   1480/*
   1481 * intervals directory
   1482 */
   1483
   1484struct damon_sysfs_intervals {
   1485	struct kobject kobj;
   1486	unsigned long sample_us;
   1487	unsigned long aggr_us;
   1488	unsigned long update_us;
   1489};
   1490
   1491static struct damon_sysfs_intervals *damon_sysfs_intervals_alloc(
   1492		unsigned long sample_us, unsigned long aggr_us,
   1493		unsigned long update_us)
   1494{
   1495	struct damon_sysfs_intervals *intervals = kmalloc(sizeof(*intervals),
   1496			GFP_KERNEL);
   1497
   1498	if (!intervals)
   1499		return NULL;
   1500
   1501	intervals->kobj = (struct kobject){};
   1502	intervals->sample_us = sample_us;
   1503	intervals->aggr_us = aggr_us;
   1504	intervals->update_us = update_us;
   1505	return intervals;
   1506}
   1507
   1508static ssize_t sample_us_show(struct kobject *kobj,
   1509		struct kobj_attribute *attr, char *buf)
   1510{
   1511	struct damon_sysfs_intervals *intervals = container_of(kobj,
   1512			struct damon_sysfs_intervals, kobj);
   1513
   1514	return sysfs_emit(buf, "%lu\n", intervals->sample_us);
   1515}
   1516
   1517static ssize_t sample_us_store(struct kobject *kobj,
   1518		struct kobj_attribute *attr, const char *buf, size_t count)
   1519{
   1520	struct damon_sysfs_intervals *intervals = container_of(kobj,
   1521			struct damon_sysfs_intervals, kobj);
   1522	unsigned long us;
   1523	int err = kstrtoul(buf, 0, &us);
   1524
   1525	if (err)
   1526		return -EINVAL;
   1527
   1528	intervals->sample_us = us;
   1529	return count;
   1530}
   1531
   1532static ssize_t aggr_us_show(struct kobject *kobj, struct kobj_attribute *attr,
   1533		char *buf)
   1534{
   1535	struct damon_sysfs_intervals *intervals = container_of(kobj,
   1536			struct damon_sysfs_intervals, kobj);
   1537
   1538	return sysfs_emit(buf, "%lu\n", intervals->aggr_us);
   1539}
   1540
   1541static ssize_t aggr_us_store(struct kobject *kobj, struct kobj_attribute *attr,
   1542		const char *buf, size_t count)
   1543{
   1544	struct damon_sysfs_intervals *intervals = container_of(kobj,
   1545			struct damon_sysfs_intervals, kobj);
   1546	unsigned long us;
   1547	int err = kstrtoul(buf, 0, &us);
   1548
   1549	if (err)
   1550		return -EINVAL;
   1551
   1552	intervals->aggr_us = us;
   1553	return count;
   1554}
   1555
   1556static ssize_t update_us_show(struct kobject *kobj,
   1557		struct kobj_attribute *attr, char *buf)
   1558{
   1559	struct damon_sysfs_intervals *intervals = container_of(kobj,
   1560			struct damon_sysfs_intervals, kobj);
   1561
   1562	return sysfs_emit(buf, "%lu\n", intervals->update_us);
   1563}
   1564
   1565static ssize_t update_us_store(struct kobject *kobj,
   1566		struct kobj_attribute *attr, const char *buf, size_t count)
   1567{
   1568	struct damon_sysfs_intervals *intervals = container_of(kobj,
   1569			struct damon_sysfs_intervals, kobj);
   1570	unsigned long us;
   1571	int err = kstrtoul(buf, 0, &us);
   1572
   1573	if (err)
   1574		return -EINVAL;
   1575
   1576	intervals->update_us = us;
   1577	return count;
   1578}
   1579
   1580static void damon_sysfs_intervals_release(struct kobject *kobj)
   1581{
   1582	kfree(container_of(kobj, struct damon_sysfs_intervals, kobj));
   1583}
   1584
   1585static struct kobj_attribute damon_sysfs_intervals_sample_us_attr =
   1586		__ATTR_RW_MODE(sample_us, 0600);
   1587
   1588static struct kobj_attribute damon_sysfs_intervals_aggr_us_attr =
   1589		__ATTR_RW_MODE(aggr_us, 0600);
   1590
   1591static struct kobj_attribute damon_sysfs_intervals_update_us_attr =
   1592		__ATTR_RW_MODE(update_us, 0600);
   1593
   1594static struct attribute *damon_sysfs_intervals_attrs[] = {
   1595	&damon_sysfs_intervals_sample_us_attr.attr,
   1596	&damon_sysfs_intervals_aggr_us_attr.attr,
   1597	&damon_sysfs_intervals_update_us_attr.attr,
   1598	NULL,
   1599};
   1600ATTRIBUTE_GROUPS(damon_sysfs_intervals);
   1601
   1602static struct kobj_type damon_sysfs_intervals_ktype = {
   1603	.release = damon_sysfs_intervals_release,
   1604	.sysfs_ops = &kobj_sysfs_ops,
   1605	.default_groups = damon_sysfs_intervals_groups,
   1606};
   1607
   1608/*
   1609 * monitoring_attrs directory
   1610 */
   1611
   1612struct damon_sysfs_attrs {
   1613	struct kobject kobj;
   1614	struct damon_sysfs_intervals *intervals;
   1615	struct damon_sysfs_ul_range *nr_regions_range;
   1616};
   1617
   1618static struct damon_sysfs_attrs *damon_sysfs_attrs_alloc(void)
   1619{
   1620	struct damon_sysfs_attrs *attrs = kmalloc(sizeof(*attrs), GFP_KERNEL);
   1621
   1622	if (!attrs)
   1623		return NULL;
   1624	attrs->kobj = (struct kobject){};
   1625	return attrs;
   1626}
   1627
   1628static int damon_sysfs_attrs_add_dirs(struct damon_sysfs_attrs *attrs)
   1629{
   1630	struct damon_sysfs_intervals *intervals;
   1631	struct damon_sysfs_ul_range *nr_regions_range;
   1632	int err;
   1633
   1634	intervals = damon_sysfs_intervals_alloc(5000, 100000, 60000000);
   1635	if (!intervals)
   1636		return -ENOMEM;
   1637
   1638	err = kobject_init_and_add(&intervals->kobj,
   1639			&damon_sysfs_intervals_ktype, &attrs->kobj,
   1640			"intervals");
   1641	if (err)
   1642		goto put_intervals_out;
   1643	attrs->intervals = intervals;
   1644
   1645	nr_regions_range = damon_sysfs_ul_range_alloc(10, 1000);
   1646	if (!nr_regions_range) {
   1647		err = -ENOMEM;
   1648		goto put_intervals_out;
   1649	}
   1650
   1651	err = kobject_init_and_add(&nr_regions_range->kobj,
   1652			&damon_sysfs_ul_range_ktype, &attrs->kobj,
   1653			"nr_regions");
   1654	if (err)
   1655		goto put_nr_regions_intervals_out;
   1656	attrs->nr_regions_range = nr_regions_range;
   1657	return 0;
   1658
   1659put_nr_regions_intervals_out:
   1660	kobject_put(&nr_regions_range->kobj);
   1661	attrs->nr_regions_range = NULL;
   1662put_intervals_out:
   1663	kobject_put(&intervals->kobj);
   1664	attrs->intervals = NULL;
   1665	return err;
   1666}
   1667
   1668static void damon_sysfs_attrs_rm_dirs(struct damon_sysfs_attrs *attrs)
   1669{
   1670	kobject_put(&attrs->nr_regions_range->kobj);
   1671	kobject_put(&attrs->intervals->kobj);
   1672}
   1673
   1674static void damon_sysfs_attrs_release(struct kobject *kobj)
   1675{
   1676	kfree(container_of(kobj, struct damon_sysfs_attrs, kobj));
   1677}
   1678
   1679static struct attribute *damon_sysfs_attrs_attrs[] = {
   1680	NULL,
   1681};
   1682ATTRIBUTE_GROUPS(damon_sysfs_attrs);
   1683
   1684static struct kobj_type damon_sysfs_attrs_ktype = {
   1685	.release = damon_sysfs_attrs_release,
   1686	.sysfs_ops = &kobj_sysfs_ops,
   1687	.default_groups = damon_sysfs_attrs_groups,
   1688};
   1689
   1690/*
   1691 * context directory
   1692 */
   1693
   1694/* This should match with enum damon_ops_id */
   1695static const char * const damon_sysfs_ops_strs[] = {
   1696	"vaddr",
   1697	"fvaddr",
   1698	"paddr",
   1699};
   1700
   1701struct damon_sysfs_context {
   1702	struct kobject kobj;
   1703	enum damon_ops_id ops_id;
   1704	struct damon_sysfs_attrs *attrs;
   1705	struct damon_sysfs_targets *targets;
   1706	struct damon_sysfs_schemes *schemes;
   1707};
   1708
   1709static struct damon_sysfs_context *damon_sysfs_context_alloc(
   1710		enum damon_ops_id ops_id)
   1711{
   1712	struct damon_sysfs_context *context = kmalloc(sizeof(*context),
   1713				GFP_KERNEL);
   1714
   1715	if (!context)
   1716		return NULL;
   1717	context->kobj = (struct kobject){};
   1718	context->ops_id = ops_id;
   1719	return context;
   1720}
   1721
   1722static int damon_sysfs_context_set_attrs(struct damon_sysfs_context *context)
   1723{
   1724	struct damon_sysfs_attrs *attrs = damon_sysfs_attrs_alloc();
   1725	int err;
   1726
   1727	if (!attrs)
   1728		return -ENOMEM;
   1729	err = kobject_init_and_add(&attrs->kobj, &damon_sysfs_attrs_ktype,
   1730			&context->kobj, "monitoring_attrs");
   1731	if (err)
   1732		goto out;
   1733	err = damon_sysfs_attrs_add_dirs(attrs);
   1734	if (err)
   1735		goto out;
   1736	context->attrs = attrs;
   1737	return 0;
   1738
   1739out:
   1740	kobject_put(&attrs->kobj);
   1741	return err;
   1742}
   1743
   1744static int damon_sysfs_context_set_targets(struct damon_sysfs_context *context)
   1745{
   1746	struct damon_sysfs_targets *targets = damon_sysfs_targets_alloc();
   1747	int err;
   1748
   1749	if (!targets)
   1750		return -ENOMEM;
   1751	err = kobject_init_and_add(&targets->kobj, &damon_sysfs_targets_ktype,
   1752			&context->kobj, "targets");
   1753	if (err) {
   1754		kobject_put(&targets->kobj);
   1755		return err;
   1756	}
   1757	context->targets = targets;
   1758	return 0;
   1759}
   1760
   1761static int damon_sysfs_context_set_schemes(struct damon_sysfs_context *context)
   1762{
   1763	struct damon_sysfs_schemes *schemes = damon_sysfs_schemes_alloc();
   1764	int err;
   1765
   1766	if (!schemes)
   1767		return -ENOMEM;
   1768	err = kobject_init_and_add(&schemes->kobj, &damon_sysfs_schemes_ktype,
   1769			&context->kobj, "schemes");
   1770	if (err) {
   1771		kobject_put(&schemes->kobj);
   1772		return err;
   1773	}
   1774	context->schemes = schemes;
   1775	return 0;
   1776}
   1777
   1778static int damon_sysfs_context_add_dirs(struct damon_sysfs_context *context)
   1779{
   1780	int err;
   1781
   1782	err = damon_sysfs_context_set_attrs(context);
   1783	if (err)
   1784		return err;
   1785
   1786	err = damon_sysfs_context_set_targets(context);
   1787	if (err)
   1788		goto put_attrs_out;
   1789
   1790	err = damon_sysfs_context_set_schemes(context);
   1791	if (err)
   1792		goto put_targets_attrs_out;
   1793	return 0;
   1794
   1795put_targets_attrs_out:
   1796	kobject_put(&context->targets->kobj);
   1797	context->targets = NULL;
   1798put_attrs_out:
   1799	kobject_put(&context->attrs->kobj);
   1800	context->attrs = NULL;
   1801	return err;
   1802}
   1803
   1804static void damon_sysfs_context_rm_dirs(struct damon_sysfs_context *context)
   1805{
   1806	damon_sysfs_attrs_rm_dirs(context->attrs);
   1807	kobject_put(&context->attrs->kobj);
   1808	damon_sysfs_targets_rm_dirs(context->targets);
   1809	kobject_put(&context->targets->kobj);
   1810	damon_sysfs_schemes_rm_dirs(context->schemes);
   1811	kobject_put(&context->schemes->kobj);
   1812}
   1813
   1814static ssize_t avail_operations_show(struct kobject *kobj,
   1815		struct kobj_attribute *attr, char *buf)
   1816{
   1817	enum damon_ops_id id;
   1818	int len = 0;
   1819
   1820	for (id = 0; id < NR_DAMON_OPS; id++) {
   1821		if (!damon_is_registered_ops(id))
   1822			continue;
   1823		len += sysfs_emit_at(buf, len, "%s\n",
   1824				damon_sysfs_ops_strs[id]);
   1825	}
   1826	return len;
   1827}
   1828
   1829static ssize_t operations_show(struct kobject *kobj,
   1830		struct kobj_attribute *attr, char *buf)
   1831{
   1832	struct damon_sysfs_context *context = container_of(kobj,
   1833			struct damon_sysfs_context, kobj);
   1834
   1835	return sysfs_emit(buf, "%s\n", damon_sysfs_ops_strs[context->ops_id]);
   1836}
   1837
   1838static ssize_t operations_store(struct kobject *kobj,
   1839		struct kobj_attribute *attr, const char *buf, size_t count)
   1840{
   1841	struct damon_sysfs_context *context = container_of(kobj,
   1842			struct damon_sysfs_context, kobj);
   1843	enum damon_ops_id id;
   1844
   1845	for (id = 0; id < NR_DAMON_OPS; id++) {
   1846		if (sysfs_streq(buf, damon_sysfs_ops_strs[id])) {
   1847			context->ops_id = id;
   1848			return count;
   1849		}
   1850	}
   1851	return -EINVAL;
   1852}
   1853
   1854static void damon_sysfs_context_release(struct kobject *kobj)
   1855{
   1856	kfree(container_of(kobj, struct damon_sysfs_context, kobj));
   1857}
   1858
   1859static struct kobj_attribute damon_sysfs_context_avail_operations_attr =
   1860		__ATTR_RO_MODE(avail_operations, 0400);
   1861
   1862static struct kobj_attribute damon_sysfs_context_operations_attr =
   1863		__ATTR_RW_MODE(operations, 0600);
   1864
   1865static struct attribute *damon_sysfs_context_attrs[] = {
   1866	&damon_sysfs_context_avail_operations_attr.attr,
   1867	&damon_sysfs_context_operations_attr.attr,
   1868	NULL,
   1869};
   1870ATTRIBUTE_GROUPS(damon_sysfs_context);
   1871
   1872static struct kobj_type damon_sysfs_context_ktype = {
   1873	.release = damon_sysfs_context_release,
   1874	.sysfs_ops = &kobj_sysfs_ops,
   1875	.default_groups = damon_sysfs_context_groups,
   1876};
   1877
   1878/*
   1879 * contexts directory
   1880 */
   1881
   1882struct damon_sysfs_contexts {
   1883	struct kobject kobj;
   1884	struct damon_sysfs_context **contexts_arr;
   1885	int nr;
   1886};
   1887
   1888static struct damon_sysfs_contexts *damon_sysfs_contexts_alloc(void)
   1889{
   1890	return kzalloc(sizeof(struct damon_sysfs_contexts), GFP_KERNEL);
   1891}
   1892
   1893static void damon_sysfs_contexts_rm_dirs(struct damon_sysfs_contexts *contexts)
   1894{
   1895	struct damon_sysfs_context **contexts_arr = contexts->contexts_arr;
   1896	int i;
   1897
   1898	for (i = 0; i < contexts->nr; i++) {
   1899		damon_sysfs_context_rm_dirs(contexts_arr[i]);
   1900		kobject_put(&contexts_arr[i]->kobj);
   1901	}
   1902	contexts->nr = 0;
   1903	kfree(contexts_arr);
   1904	contexts->contexts_arr = NULL;
   1905}
   1906
   1907static int damon_sysfs_contexts_add_dirs(struct damon_sysfs_contexts *contexts,
   1908		int nr_contexts)
   1909{
   1910	struct damon_sysfs_context **contexts_arr, *context;
   1911	int err, i;
   1912
   1913	damon_sysfs_contexts_rm_dirs(contexts);
   1914	if (!nr_contexts)
   1915		return 0;
   1916
   1917	contexts_arr = kmalloc_array(nr_contexts, sizeof(*contexts_arr),
   1918			GFP_KERNEL | __GFP_NOWARN);
   1919	if (!contexts_arr)
   1920		return -ENOMEM;
   1921	contexts->contexts_arr = contexts_arr;
   1922
   1923	for (i = 0; i < nr_contexts; i++) {
   1924		context = damon_sysfs_context_alloc(DAMON_OPS_VADDR);
   1925		if (!context) {
   1926			damon_sysfs_contexts_rm_dirs(contexts);
   1927			return -ENOMEM;
   1928		}
   1929
   1930		err = kobject_init_and_add(&context->kobj,
   1931				&damon_sysfs_context_ktype, &contexts->kobj,
   1932				"%d", i);
   1933		if (err)
   1934			goto out;
   1935
   1936		err = damon_sysfs_context_add_dirs(context);
   1937		if (err)
   1938			goto out;
   1939
   1940		contexts_arr[i] = context;
   1941		contexts->nr++;
   1942	}
   1943	return 0;
   1944
   1945out:
   1946	damon_sysfs_contexts_rm_dirs(contexts);
   1947	kobject_put(&context->kobj);
   1948	return err;
   1949}
   1950
   1951static ssize_t nr_contexts_show(struct kobject *kobj,
   1952		struct kobj_attribute *attr, char *buf)
   1953{
   1954	struct damon_sysfs_contexts *contexts = container_of(kobj,
   1955			struct damon_sysfs_contexts, kobj);
   1956
   1957	return sysfs_emit(buf, "%d\n", contexts->nr);
   1958}
   1959
   1960static ssize_t nr_contexts_store(struct kobject *kobj,
   1961		struct kobj_attribute *attr, const char *buf, size_t count)
   1962{
   1963	struct damon_sysfs_contexts *contexts = container_of(kobj,
   1964			struct damon_sysfs_contexts, kobj);
   1965	int nr, err;
   1966
   1967	err = kstrtoint(buf, 0, &nr);
   1968	if (err)
   1969		return err;
   1970	/* TODO: support multiple contexts per kdamond */
   1971	if (nr < 0 || 1 < nr)
   1972		return -EINVAL;
   1973
   1974	if (!mutex_trylock(&damon_sysfs_lock))
   1975		return -EBUSY;
   1976	err = damon_sysfs_contexts_add_dirs(contexts, nr);
   1977	mutex_unlock(&damon_sysfs_lock);
   1978	if (err)
   1979		return err;
   1980
   1981	return count;
   1982}
   1983
   1984static void damon_sysfs_contexts_release(struct kobject *kobj)
   1985{
   1986	kfree(container_of(kobj, struct damon_sysfs_contexts, kobj));
   1987}
   1988
   1989static struct kobj_attribute damon_sysfs_contexts_nr_attr
   1990		= __ATTR_RW_MODE(nr_contexts, 0600);
   1991
   1992static struct attribute *damon_sysfs_contexts_attrs[] = {
   1993	&damon_sysfs_contexts_nr_attr.attr,
   1994	NULL,
   1995};
   1996ATTRIBUTE_GROUPS(damon_sysfs_contexts);
   1997
   1998static struct kobj_type damon_sysfs_contexts_ktype = {
   1999	.release = damon_sysfs_contexts_release,
   2000	.sysfs_ops = &kobj_sysfs_ops,
   2001	.default_groups = damon_sysfs_contexts_groups,
   2002};
   2003
   2004/*
   2005 * kdamond directory
   2006 */
   2007
   2008struct damon_sysfs_kdamond {
   2009	struct kobject kobj;
   2010	struct damon_sysfs_contexts *contexts;
   2011	struct damon_ctx *damon_ctx;
   2012};
   2013
   2014static struct damon_sysfs_kdamond *damon_sysfs_kdamond_alloc(void)
   2015{
   2016	return kzalloc(sizeof(struct damon_sysfs_kdamond), GFP_KERNEL);
   2017}
   2018
   2019static int damon_sysfs_kdamond_add_dirs(struct damon_sysfs_kdamond *kdamond)
   2020{
   2021	struct damon_sysfs_contexts *contexts;
   2022	int err;
   2023
   2024	contexts = damon_sysfs_contexts_alloc();
   2025	if (!contexts)
   2026		return -ENOMEM;
   2027
   2028	err = kobject_init_and_add(&contexts->kobj,
   2029			&damon_sysfs_contexts_ktype, &kdamond->kobj,
   2030			"contexts");
   2031	if (err) {
   2032		kobject_put(&contexts->kobj);
   2033		return err;
   2034	}
   2035	kdamond->contexts = contexts;
   2036
   2037	return err;
   2038}
   2039
   2040static void damon_sysfs_kdamond_rm_dirs(struct damon_sysfs_kdamond *kdamond)
   2041{
   2042	damon_sysfs_contexts_rm_dirs(kdamond->contexts);
   2043	kobject_put(&kdamond->contexts->kobj);
   2044}
   2045
   2046static bool damon_sysfs_ctx_running(struct damon_ctx *ctx)
   2047{
   2048	bool running;
   2049
   2050	mutex_lock(&ctx->kdamond_lock);
   2051	running = ctx->kdamond != NULL;
   2052	mutex_unlock(&ctx->kdamond_lock);
   2053	return running;
   2054}
   2055
   2056/*
   2057 * enum damon_sysfs_cmd - Commands for a specific kdamond.
   2058 */
   2059enum damon_sysfs_cmd {
   2060	/* @DAMON_SYSFS_CMD_ON: Turn the kdamond on. */
   2061	DAMON_SYSFS_CMD_ON,
   2062	/* @DAMON_SYSFS_CMD_OFF: Turn the kdamond off. */
   2063	DAMON_SYSFS_CMD_OFF,
   2064	/* @DAMON_SYSFS_CMD_COMMIT: Update kdamond inputs. */
   2065	DAMON_SYSFS_CMD_COMMIT,
   2066	/*
   2067	 * @DAMON_SYSFS_CMD_UPDATE_SCHEMES_STATS: Update scheme stats sysfs
   2068	 * files.
   2069	 */
   2070	DAMON_SYSFS_CMD_UPDATE_SCHEMES_STATS,
   2071	/*
   2072	 * @NR_DAMON_SYSFS_CMDS: Total number of DAMON sysfs commands.
   2073	 */
   2074	NR_DAMON_SYSFS_CMDS,
   2075};
   2076
   2077/* Should match with enum damon_sysfs_cmd */
   2078static const char * const damon_sysfs_cmd_strs[] = {
   2079	"on",
   2080	"off",
   2081	"commit",
   2082	"update_schemes_stats",
   2083};
   2084
   2085/*
   2086 * struct damon_sysfs_cmd_request - A request to the DAMON callback.
   2087 * @cmd:	The command that needs to be handled by the callback.
   2088 * @kdamond:	The kobject wrapper that associated to the kdamond thread.
   2089 *
   2090 * This structure represents a sysfs command request that need to access some
   2091 * DAMON context-internal data.  Because DAMON context-internal data can be
   2092 * safely accessed from DAMON callbacks without additional synchronization, the
   2093 * request will be handled by the DAMON callback.  None-``NULL`` @kdamond means
   2094 * the request is valid.
   2095 */
   2096struct damon_sysfs_cmd_request {
   2097	enum damon_sysfs_cmd cmd;
   2098	struct damon_sysfs_kdamond *kdamond;
   2099};
   2100
   2101/* Current DAMON callback request.  Protected by damon_sysfs_lock. */
   2102static struct damon_sysfs_cmd_request damon_sysfs_cmd_request;
   2103
   2104static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
   2105		char *buf)
   2106{
   2107	struct damon_sysfs_kdamond *kdamond = container_of(kobj,
   2108			struct damon_sysfs_kdamond, kobj);
   2109	struct damon_ctx *ctx = kdamond->damon_ctx;
   2110	bool running;
   2111
   2112	if (!ctx)
   2113		running = false;
   2114	else
   2115		running = damon_sysfs_ctx_running(ctx);
   2116
   2117	return sysfs_emit(buf, "%s\n", running ?
   2118			damon_sysfs_cmd_strs[DAMON_SYSFS_CMD_ON] :
   2119			damon_sysfs_cmd_strs[DAMON_SYSFS_CMD_OFF]);
   2120}
   2121
   2122static int damon_sysfs_set_attrs(struct damon_ctx *ctx,
   2123		struct damon_sysfs_attrs *sys_attrs)
   2124{
   2125	struct damon_sysfs_intervals *sys_intervals = sys_attrs->intervals;
   2126	struct damon_sysfs_ul_range *sys_nr_regions =
   2127		sys_attrs->nr_regions_range;
   2128
   2129	return damon_set_attrs(ctx, sys_intervals->sample_us,
   2130			sys_intervals->aggr_us, sys_intervals->update_us,
   2131			sys_nr_regions->min, sys_nr_regions->max);
   2132}
   2133
   2134static void damon_sysfs_destroy_targets(struct damon_ctx *ctx)
   2135{
   2136	struct damon_target *t, *next;
   2137
   2138	damon_for_each_target_safe(t, next, ctx) {
   2139		if (ctx->ops.id == DAMON_OPS_VADDR ||
   2140				ctx->ops.id == DAMON_OPS_FVADDR)
   2141			put_pid(t->pid);
   2142		damon_destroy_target(t);
   2143	}
   2144}
   2145
   2146static int damon_sysfs_set_regions(struct damon_target *t,
   2147		struct damon_sysfs_regions *sysfs_regions)
   2148{
   2149	struct damon_addr_range *ranges = kmalloc_array(sysfs_regions->nr,
   2150			sizeof(*ranges), GFP_KERNEL | __GFP_NOWARN);
   2151	int i, err = -EINVAL;
   2152
   2153	if (!ranges)
   2154		return -ENOMEM;
   2155	for (i = 0; i < sysfs_regions->nr; i++) {
   2156		struct damon_sysfs_region *sys_region =
   2157			sysfs_regions->regions_arr[i];
   2158
   2159		if (sys_region->start > sys_region->end)
   2160			goto out;
   2161
   2162		ranges[i].start = sys_region->start;
   2163		ranges[i].end = sys_region->end;
   2164		if (i == 0)
   2165			continue;
   2166		if (ranges[i - 1].end > ranges[i].start)
   2167			goto out;
   2168	}
   2169	err = damon_set_regions(t, ranges, sysfs_regions->nr);
   2170out:
   2171	kfree(ranges);
   2172	return err;
   2173
   2174}
   2175
   2176static int damon_sysfs_add_target(struct damon_sysfs_target *sys_target,
   2177		struct damon_ctx *ctx)
   2178{
   2179	struct damon_target *t = damon_new_target();
   2180	int err = -EINVAL;
   2181
   2182	if (!t)
   2183		return -ENOMEM;
   2184	if (ctx->ops.id == DAMON_OPS_VADDR ||
   2185			ctx->ops.id == DAMON_OPS_FVADDR) {
   2186		t->pid = find_get_pid(sys_target->pid);
   2187		if (!t->pid)
   2188			goto destroy_targets_out;
   2189	}
   2190	damon_add_target(ctx, t);
   2191	err = damon_sysfs_set_regions(t, sys_target->regions);
   2192	if (err)
   2193		goto destroy_targets_out;
   2194	return 0;
   2195
   2196destroy_targets_out:
   2197	damon_sysfs_destroy_targets(ctx);
   2198	return err;
   2199}
   2200
   2201/*
   2202 * Search a target in a context that corresponds to the sysfs target input.
   2203 *
   2204 * Return: pointer to the target if found, NULL if not found, or negative
   2205 * error code if the search failed.
   2206 */
   2207static struct damon_target *damon_sysfs_existing_target(
   2208		struct damon_sysfs_target *sys_target, struct damon_ctx *ctx)
   2209{
   2210	struct pid *pid;
   2211	struct damon_target *t;
   2212
   2213	if (ctx->ops.id == DAMON_OPS_PADDR) {
   2214		/* Up to only one target for paddr could exist */
   2215		damon_for_each_target(t, ctx)
   2216			return t;
   2217		return NULL;
   2218	}
   2219
   2220	/* ops.id should be DAMON_OPS_VADDR or DAMON_OPS_FVADDR */
   2221	pid = find_get_pid(sys_target->pid);
   2222	if (!pid)
   2223		return ERR_PTR(-EINVAL);
   2224	damon_for_each_target(t, ctx) {
   2225		if (t->pid == pid) {
   2226			put_pid(pid);
   2227			return t;
   2228		}
   2229	}
   2230	put_pid(pid);
   2231	return NULL;
   2232}
   2233
   2234static int damon_sysfs_set_targets(struct damon_ctx *ctx,
   2235		struct damon_sysfs_targets *sysfs_targets)
   2236{
   2237	int i, err;
   2238
   2239	/* Multiple physical address space monitoring targets makes no sense */
   2240	if (ctx->ops.id == DAMON_OPS_PADDR && sysfs_targets->nr > 1)
   2241		return -EINVAL;
   2242
   2243	for (i = 0; i < sysfs_targets->nr; i++) {
   2244		struct damon_sysfs_target *st = sysfs_targets->targets_arr[i];
   2245		struct damon_target *t = damon_sysfs_existing_target(st, ctx);
   2246
   2247		if (IS_ERR(t))
   2248			return PTR_ERR(t);
   2249		if (!t)
   2250			err = damon_sysfs_add_target(st, ctx);
   2251		else
   2252			err = damon_sysfs_set_regions(t, st->regions);
   2253		if (err)
   2254			return err;
   2255	}
   2256	return 0;
   2257}
   2258
   2259static struct damos *damon_sysfs_mk_scheme(
   2260		struct damon_sysfs_scheme *sysfs_scheme)
   2261{
   2262	struct damon_sysfs_access_pattern *pattern =
   2263		sysfs_scheme->access_pattern;
   2264	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
   2265	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
   2266	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
   2267	struct damos_quota quota = {
   2268		.ms = sysfs_quotas->ms,
   2269		.sz = sysfs_quotas->sz,
   2270		.reset_interval = sysfs_quotas->reset_interval_ms,
   2271		.weight_sz = sysfs_weights->sz,
   2272		.weight_nr_accesses = sysfs_weights->nr_accesses,
   2273		.weight_age = sysfs_weights->age,
   2274	};
   2275	struct damos_watermarks wmarks = {
   2276		.metric = sysfs_wmarks->metric,
   2277		.interval = sysfs_wmarks->interval_us,
   2278		.high = sysfs_wmarks->high,
   2279		.mid = sysfs_wmarks->mid,
   2280		.low = sysfs_wmarks->low,
   2281	};
   2282
   2283	return damon_new_scheme(pattern->sz->min, pattern->sz->max,
   2284			pattern->nr_accesses->min, pattern->nr_accesses->max,
   2285			pattern->age->min, pattern->age->max,
   2286			sysfs_scheme->action, &quota, &wmarks);
   2287}
   2288
   2289static int damon_sysfs_set_schemes(struct damon_ctx *ctx,
   2290		struct damon_sysfs_schemes *sysfs_schemes)
   2291{
   2292	int i;
   2293
   2294	for (i = 0; i < sysfs_schemes->nr; i++) {
   2295		struct damos *scheme, *next;
   2296
   2297		scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
   2298		if (!scheme) {
   2299			damon_for_each_scheme_safe(scheme, next, ctx)
   2300				damon_destroy_scheme(scheme);
   2301			return -ENOMEM;
   2302		}
   2303		damon_add_scheme(ctx, scheme);
   2304	}
   2305	return 0;
   2306}
   2307
   2308static void damon_sysfs_before_terminate(struct damon_ctx *ctx)
   2309{
   2310	struct damon_target *t, *next;
   2311
   2312	if (ctx->ops.id != DAMON_OPS_VADDR && ctx->ops.id != DAMON_OPS_FVADDR)
   2313		return;
   2314
   2315	mutex_lock(&ctx->kdamond_lock);
   2316	damon_for_each_target_safe(t, next, ctx) {
   2317		put_pid(t->pid);
   2318		damon_destroy_target(t);
   2319	}
   2320	mutex_unlock(&ctx->kdamond_lock);
   2321}
   2322
   2323/*
   2324 * damon_sysfs_upd_schemes_stats() - Update schemes stats sysfs files.
   2325 * @kdamond:	The kobject wrapper that associated to the kdamond thread.
   2326 *
   2327 * This function reads the schemes stats of specific kdamond and update the
   2328 * related values for sysfs files.  This function should be called from DAMON
   2329 * callbacks while holding ``damon_syfs_lock``, to safely access the DAMON
   2330 * contexts-internal data and DAMON sysfs variables.
   2331 */
   2332static int damon_sysfs_upd_schemes_stats(struct damon_sysfs_kdamond *kdamond)
   2333{
   2334	struct damon_ctx *ctx = kdamond->damon_ctx;
   2335	struct damon_sysfs_schemes *sysfs_schemes;
   2336	struct damos *scheme;
   2337	int schemes_idx = 0;
   2338
   2339	if (!ctx)
   2340		return -EINVAL;
   2341	sysfs_schemes = kdamond->contexts->contexts_arr[0]->schemes;
   2342	damon_for_each_scheme(scheme, ctx) {
   2343		struct damon_sysfs_stats *sysfs_stats;
   2344
   2345		sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
   2346		sysfs_stats->nr_tried = scheme->stat.nr_tried;
   2347		sysfs_stats->sz_tried = scheme->stat.sz_tried;
   2348		sysfs_stats->nr_applied = scheme->stat.nr_applied;
   2349		sysfs_stats->sz_applied = scheme->stat.sz_applied;
   2350		sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
   2351	}
   2352	return 0;
   2353}
   2354
   2355static inline bool damon_sysfs_kdamond_running(
   2356		struct damon_sysfs_kdamond *kdamond)
   2357{
   2358	return kdamond->damon_ctx &&
   2359		damon_sysfs_ctx_running(kdamond->damon_ctx);
   2360}
   2361
   2362/*
   2363 * damon_sysfs_commit_input() - Commit user inputs to a running kdamond.
   2364 * @kdamond:	The kobject wrapper for the associated kdamond.
   2365 *
   2366 * If the sysfs input is wrong, the kdamond will be terminated.
   2367 */
   2368static int damon_sysfs_commit_input(struct damon_sysfs_kdamond *kdamond)
   2369{
   2370	struct damon_ctx *ctx = kdamond->damon_ctx;
   2371	struct damon_sysfs_context *sys_ctx;
   2372	int err = 0;
   2373
   2374	if (!damon_sysfs_kdamond_running(kdamond))
   2375		return -EINVAL;
   2376	/* TODO: Support multiple contexts per kdamond */
   2377	if (kdamond->contexts->nr != 1)
   2378		return -EINVAL;
   2379
   2380	sys_ctx = kdamond->contexts->contexts_arr[0];
   2381
   2382	err = damon_select_ops(ctx, sys_ctx->ops_id);
   2383	if (err)
   2384		return err;
   2385	err = damon_sysfs_set_attrs(ctx, sys_ctx->attrs);
   2386	if (err)
   2387		return err;
   2388	err = damon_sysfs_set_targets(ctx, sys_ctx->targets);
   2389	if (err)
   2390		return err;
   2391	err = damon_sysfs_set_schemes(ctx, sys_ctx->schemes);
   2392	if (err)
   2393		return err;
   2394	return err;
   2395}
   2396
   2397/*
   2398 * damon_sysfs_cmd_request_callback() - DAMON callback for handling requests.
   2399 * @c:	The DAMON context of the callback.
   2400 *
   2401 * This function is periodically called back from the kdamond thread for @c.
   2402 * Then, it checks if there is a waiting DAMON sysfs request and handles it.
   2403 */
   2404static int damon_sysfs_cmd_request_callback(struct damon_ctx *c)
   2405{
   2406	struct damon_sysfs_kdamond *kdamond;
   2407	int err = 0;
   2408
   2409	/* avoid deadlock due to concurrent state_store('off') */
   2410	if (!mutex_trylock(&damon_sysfs_lock))
   2411		return 0;
   2412	kdamond = damon_sysfs_cmd_request.kdamond;
   2413	if (!kdamond || kdamond->damon_ctx != c)
   2414		goto out;
   2415	switch (damon_sysfs_cmd_request.cmd) {
   2416	case DAMON_SYSFS_CMD_UPDATE_SCHEMES_STATS:
   2417		err = damon_sysfs_upd_schemes_stats(kdamond);
   2418		break;
   2419	case DAMON_SYSFS_CMD_COMMIT:
   2420		err = damon_sysfs_commit_input(kdamond);
   2421		break;
   2422	default:
   2423		break;
   2424	}
   2425	/* Mark the request as invalid now. */
   2426	damon_sysfs_cmd_request.kdamond = NULL;
   2427out:
   2428	mutex_unlock(&damon_sysfs_lock);
   2429	return err;
   2430}
   2431
   2432static struct damon_ctx *damon_sysfs_build_ctx(
   2433		struct damon_sysfs_context *sys_ctx)
   2434{
   2435	struct damon_ctx *ctx = damon_new_ctx();
   2436	int err;
   2437
   2438	if (!ctx)
   2439		return ERR_PTR(-ENOMEM);
   2440
   2441	err = damon_select_ops(ctx, sys_ctx->ops_id);
   2442	if (err)
   2443		goto out;
   2444	err = damon_sysfs_set_attrs(ctx, sys_ctx->attrs);
   2445	if (err)
   2446		goto out;
   2447	err = damon_sysfs_set_targets(ctx, sys_ctx->targets);
   2448	if (err)
   2449		goto out;
   2450	err = damon_sysfs_set_schemes(ctx, sys_ctx->schemes);
   2451	if (err)
   2452		goto out;
   2453
   2454	ctx->callback.after_wmarks_check = damon_sysfs_cmd_request_callback;
   2455	ctx->callback.after_aggregation = damon_sysfs_cmd_request_callback;
   2456	ctx->callback.before_terminate = damon_sysfs_before_terminate;
   2457	return ctx;
   2458
   2459out:
   2460	damon_destroy_ctx(ctx);
   2461	return ERR_PTR(err);
   2462}
   2463
   2464static int damon_sysfs_turn_damon_on(struct damon_sysfs_kdamond *kdamond)
   2465{
   2466	struct damon_ctx *ctx;
   2467	int err;
   2468
   2469	if (kdamond->damon_ctx &&
   2470			damon_sysfs_ctx_running(kdamond->damon_ctx))
   2471		return -EBUSY;
   2472	if (damon_sysfs_cmd_request.kdamond == kdamond)
   2473		return -EBUSY;
   2474	/* TODO: support multiple contexts per kdamond */
   2475	if (kdamond->contexts->nr != 1)
   2476		return -EINVAL;
   2477
   2478	if (kdamond->damon_ctx)
   2479		damon_destroy_ctx(kdamond->damon_ctx);
   2480	kdamond->damon_ctx = NULL;
   2481
   2482	ctx = damon_sysfs_build_ctx(kdamond->contexts->contexts_arr[0]);
   2483	if (IS_ERR(ctx))
   2484		return PTR_ERR(ctx);
   2485	err = damon_start(&ctx, 1, false);
   2486	if (err) {
   2487		damon_destroy_ctx(ctx);
   2488		return err;
   2489	}
   2490	kdamond->damon_ctx = ctx;
   2491	return err;
   2492}
   2493
   2494static int damon_sysfs_turn_damon_off(struct damon_sysfs_kdamond *kdamond)
   2495{
   2496	if (!kdamond->damon_ctx)
   2497		return -EINVAL;
   2498	return damon_stop(&kdamond->damon_ctx, 1);
   2499	/*
   2500	 * To allow users show final monitoring results of already turned-off
   2501	 * DAMON, we free kdamond->damon_ctx in next
   2502	 * damon_sysfs_turn_damon_on(), or kdamonds_nr_store()
   2503	 */
   2504}
   2505
   2506/*
   2507 * damon_sysfs_handle_cmd() - Handle a command for a specific kdamond.
   2508 * @cmd:	The command to handle.
   2509 * @kdamond:	The kobject wrapper for the associated kdamond.
   2510 *
   2511 * This function handles a DAMON sysfs command for a kdamond.  For commands
   2512 * that need to access running DAMON context-internal data, it requests
   2513 * handling of the command to the DAMON callback
   2514 * (@damon_sysfs_cmd_request_callback()) and wait until it is properly handled,
   2515 * or the context is completed.
   2516 *
   2517 * Return: 0 on success, negative error code otherwise.
   2518 */
   2519static int damon_sysfs_handle_cmd(enum damon_sysfs_cmd cmd,
   2520		struct damon_sysfs_kdamond *kdamond)
   2521{
   2522	bool need_wait = true;
   2523
   2524	/* Handle commands that doesn't access DAMON context-internal data */
   2525	switch (cmd) {
   2526	case DAMON_SYSFS_CMD_ON:
   2527		return damon_sysfs_turn_damon_on(kdamond);
   2528	case DAMON_SYSFS_CMD_OFF:
   2529		return damon_sysfs_turn_damon_off(kdamond);
   2530	default:
   2531		break;
   2532	}
   2533
   2534	/* Pass the command to DAMON callback for safe DAMON context access */
   2535	if (damon_sysfs_cmd_request.kdamond)
   2536		return -EBUSY;
   2537	if (!damon_sysfs_kdamond_running(kdamond))
   2538		return -EINVAL;
   2539	damon_sysfs_cmd_request.cmd = cmd;
   2540	damon_sysfs_cmd_request.kdamond = kdamond;
   2541
   2542	/*
   2543	 * wait until damon_sysfs_cmd_request_callback() handles the request
   2544	 * from kdamond context
   2545	 */
   2546	mutex_unlock(&damon_sysfs_lock);
   2547	while (need_wait) {
   2548		schedule_timeout_idle(msecs_to_jiffies(100));
   2549		if (!mutex_trylock(&damon_sysfs_lock))
   2550			continue;
   2551		if (!damon_sysfs_cmd_request.kdamond) {
   2552			/* damon_sysfs_cmd_request_callback() handled */
   2553			need_wait = false;
   2554		} else if (!damon_sysfs_kdamond_running(kdamond)) {
   2555			/* kdamond has already finished */
   2556			need_wait = false;
   2557			damon_sysfs_cmd_request.kdamond = NULL;
   2558		}
   2559		mutex_unlock(&damon_sysfs_lock);
   2560	}
   2561	mutex_lock(&damon_sysfs_lock);
   2562	return 0;
   2563}
   2564
   2565static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
   2566		const char *buf, size_t count)
   2567{
   2568	struct damon_sysfs_kdamond *kdamond = container_of(kobj,
   2569			struct damon_sysfs_kdamond, kobj);
   2570	enum damon_sysfs_cmd cmd;
   2571	ssize_t ret = -EINVAL;
   2572
   2573	if (!mutex_trylock(&damon_sysfs_lock))
   2574		return -EBUSY;
   2575	for (cmd = 0; cmd < NR_DAMON_SYSFS_CMDS; cmd++) {
   2576		if (sysfs_streq(buf, damon_sysfs_cmd_strs[cmd])) {
   2577			ret = damon_sysfs_handle_cmd(cmd, kdamond);
   2578			break;
   2579		}
   2580	}
   2581	mutex_unlock(&damon_sysfs_lock);
   2582	if (!ret)
   2583		ret = count;
   2584	return ret;
   2585}
   2586
   2587static ssize_t pid_show(struct kobject *kobj,
   2588		struct kobj_attribute *attr, char *buf)
   2589{
   2590	struct damon_sysfs_kdamond *kdamond = container_of(kobj,
   2591			struct damon_sysfs_kdamond, kobj);
   2592	struct damon_ctx *ctx;
   2593	int pid;
   2594
   2595	if (!mutex_trylock(&damon_sysfs_lock))
   2596		return -EBUSY;
   2597	ctx = kdamond->damon_ctx;
   2598	if (!ctx) {
   2599		pid = -1;
   2600		goto out;
   2601	}
   2602	mutex_lock(&ctx->kdamond_lock);
   2603	if (!ctx->kdamond)
   2604		pid = -1;
   2605	else
   2606		pid = ctx->kdamond->pid;
   2607	mutex_unlock(&ctx->kdamond_lock);
   2608out:
   2609	mutex_unlock(&damon_sysfs_lock);
   2610	return sysfs_emit(buf, "%d\n", pid);
   2611}
   2612
   2613static void damon_sysfs_kdamond_release(struct kobject *kobj)
   2614{
   2615	struct damon_sysfs_kdamond *kdamond = container_of(kobj,
   2616			struct damon_sysfs_kdamond, kobj);
   2617
   2618	if (kdamond->damon_ctx)
   2619		damon_destroy_ctx(kdamond->damon_ctx);
   2620	kfree(kdamond);
   2621}
   2622
   2623static struct kobj_attribute damon_sysfs_kdamond_state_attr =
   2624		__ATTR_RW_MODE(state, 0600);
   2625
   2626static struct kobj_attribute damon_sysfs_kdamond_pid_attr =
   2627		__ATTR_RO_MODE(pid, 0400);
   2628
   2629static struct attribute *damon_sysfs_kdamond_attrs[] = {
   2630	&damon_sysfs_kdamond_state_attr.attr,
   2631	&damon_sysfs_kdamond_pid_attr.attr,
   2632	NULL,
   2633};
   2634ATTRIBUTE_GROUPS(damon_sysfs_kdamond);
   2635
   2636static struct kobj_type damon_sysfs_kdamond_ktype = {
   2637	.release = damon_sysfs_kdamond_release,
   2638	.sysfs_ops = &kobj_sysfs_ops,
   2639	.default_groups = damon_sysfs_kdamond_groups,
   2640};
   2641
   2642/*
   2643 * kdamonds directory
   2644 */
   2645
   2646struct damon_sysfs_kdamonds {
   2647	struct kobject kobj;
   2648	struct damon_sysfs_kdamond **kdamonds_arr;
   2649	int nr;
   2650};
   2651
   2652static struct damon_sysfs_kdamonds *damon_sysfs_kdamonds_alloc(void)
   2653{
   2654	return kzalloc(sizeof(struct damon_sysfs_kdamonds), GFP_KERNEL);
   2655}
   2656
   2657static void damon_sysfs_kdamonds_rm_dirs(struct damon_sysfs_kdamonds *kdamonds)
   2658{
   2659	struct damon_sysfs_kdamond **kdamonds_arr = kdamonds->kdamonds_arr;
   2660	int i;
   2661
   2662	for (i = 0; i < kdamonds->nr; i++) {
   2663		damon_sysfs_kdamond_rm_dirs(kdamonds_arr[i]);
   2664		kobject_put(&kdamonds_arr[i]->kobj);
   2665	}
   2666	kdamonds->nr = 0;
   2667	kfree(kdamonds_arr);
   2668	kdamonds->kdamonds_arr = NULL;
   2669}
   2670
   2671static int damon_sysfs_nr_running_ctxs(struct damon_sysfs_kdamond **kdamonds,
   2672		int nr_kdamonds)
   2673{
   2674	int nr_running_ctxs = 0;
   2675	int i;
   2676
   2677	for (i = 0; i < nr_kdamonds; i++) {
   2678		struct damon_ctx *ctx = kdamonds[i]->damon_ctx;
   2679
   2680		if (!ctx)
   2681			continue;
   2682		mutex_lock(&ctx->kdamond_lock);
   2683		if (ctx->kdamond)
   2684			nr_running_ctxs++;
   2685		mutex_unlock(&ctx->kdamond_lock);
   2686	}
   2687	return nr_running_ctxs;
   2688}
   2689
   2690static int damon_sysfs_kdamonds_add_dirs(struct damon_sysfs_kdamonds *kdamonds,
   2691		int nr_kdamonds)
   2692{
   2693	struct damon_sysfs_kdamond **kdamonds_arr, *kdamond;
   2694	int err, i;
   2695
   2696	if (damon_sysfs_nr_running_ctxs(kdamonds->kdamonds_arr, kdamonds->nr))
   2697		return -EBUSY;
   2698
   2699	for (i = 0; i < kdamonds->nr; i++) {
   2700		if (damon_sysfs_cmd_request.kdamond ==
   2701				kdamonds->kdamonds_arr[i])
   2702			return -EBUSY;
   2703	}
   2704
   2705	damon_sysfs_kdamonds_rm_dirs(kdamonds);
   2706	if (!nr_kdamonds)
   2707		return 0;
   2708
   2709	kdamonds_arr = kmalloc_array(nr_kdamonds, sizeof(*kdamonds_arr),
   2710			GFP_KERNEL | __GFP_NOWARN);
   2711	if (!kdamonds_arr)
   2712		return -ENOMEM;
   2713	kdamonds->kdamonds_arr = kdamonds_arr;
   2714
   2715	for (i = 0; i < nr_kdamonds; i++) {
   2716		kdamond = damon_sysfs_kdamond_alloc();
   2717		if (!kdamond) {
   2718			damon_sysfs_kdamonds_rm_dirs(kdamonds);
   2719			return -ENOMEM;
   2720		}
   2721
   2722		err = kobject_init_and_add(&kdamond->kobj,
   2723				&damon_sysfs_kdamond_ktype, &kdamonds->kobj,
   2724				"%d", i);
   2725		if (err)
   2726			goto out;
   2727
   2728		err = damon_sysfs_kdamond_add_dirs(kdamond);
   2729		if (err)
   2730			goto out;
   2731
   2732		kdamonds_arr[i] = kdamond;
   2733		kdamonds->nr++;
   2734	}
   2735	return 0;
   2736
   2737out:
   2738	damon_sysfs_kdamonds_rm_dirs(kdamonds);
   2739	kobject_put(&kdamond->kobj);
   2740	return err;
   2741}
   2742
   2743static ssize_t nr_kdamonds_show(struct kobject *kobj,
   2744		struct kobj_attribute *attr, char *buf)
   2745{
   2746	struct damon_sysfs_kdamonds *kdamonds = container_of(kobj,
   2747			struct damon_sysfs_kdamonds, kobj);
   2748
   2749	return sysfs_emit(buf, "%d\n", kdamonds->nr);
   2750}
   2751
   2752static ssize_t nr_kdamonds_store(struct kobject *kobj,
   2753		struct kobj_attribute *attr, const char *buf, size_t count)
   2754{
   2755	struct damon_sysfs_kdamonds *kdamonds = container_of(kobj,
   2756			struct damon_sysfs_kdamonds, kobj);
   2757	int nr, err;
   2758
   2759	err = kstrtoint(buf, 0, &nr);
   2760	if (err)
   2761		return err;
   2762	if (nr < 0)
   2763		return -EINVAL;
   2764
   2765	if (!mutex_trylock(&damon_sysfs_lock))
   2766		return -EBUSY;
   2767	err = damon_sysfs_kdamonds_add_dirs(kdamonds, nr);
   2768	mutex_unlock(&damon_sysfs_lock);
   2769	if (err)
   2770		return err;
   2771
   2772	return count;
   2773}
   2774
   2775static void damon_sysfs_kdamonds_release(struct kobject *kobj)
   2776{
   2777	kfree(container_of(kobj, struct damon_sysfs_kdamonds, kobj));
   2778}
   2779
   2780static struct kobj_attribute damon_sysfs_kdamonds_nr_attr =
   2781		__ATTR_RW_MODE(nr_kdamonds, 0600);
   2782
   2783static struct attribute *damon_sysfs_kdamonds_attrs[] = {
   2784	&damon_sysfs_kdamonds_nr_attr.attr,
   2785	NULL,
   2786};
   2787ATTRIBUTE_GROUPS(damon_sysfs_kdamonds);
   2788
   2789static struct kobj_type damon_sysfs_kdamonds_ktype = {
   2790	.release = damon_sysfs_kdamonds_release,
   2791	.sysfs_ops = &kobj_sysfs_ops,
   2792	.default_groups = damon_sysfs_kdamonds_groups,
   2793};
   2794
   2795/*
   2796 * damon user interface directory
   2797 */
   2798
   2799struct damon_sysfs_ui_dir {
   2800	struct kobject kobj;
   2801	struct damon_sysfs_kdamonds *kdamonds;
   2802};
   2803
   2804static struct damon_sysfs_ui_dir *damon_sysfs_ui_dir_alloc(void)
   2805{
   2806	return kzalloc(sizeof(struct damon_sysfs_ui_dir), GFP_KERNEL);
   2807}
   2808
   2809static int damon_sysfs_ui_dir_add_dirs(struct damon_sysfs_ui_dir *ui_dir)
   2810{
   2811	struct damon_sysfs_kdamonds *kdamonds;
   2812	int err;
   2813
   2814	kdamonds = damon_sysfs_kdamonds_alloc();
   2815	if (!kdamonds)
   2816		return -ENOMEM;
   2817
   2818	err = kobject_init_and_add(&kdamonds->kobj,
   2819			&damon_sysfs_kdamonds_ktype, &ui_dir->kobj,
   2820			"kdamonds");
   2821	if (err) {
   2822		kobject_put(&kdamonds->kobj);
   2823		return err;
   2824	}
   2825	ui_dir->kdamonds = kdamonds;
   2826	return err;
   2827}
   2828
   2829static void damon_sysfs_ui_dir_release(struct kobject *kobj)
   2830{
   2831	kfree(container_of(kobj, struct damon_sysfs_ui_dir, kobj));
   2832}
   2833
   2834static struct attribute *damon_sysfs_ui_dir_attrs[] = {
   2835	NULL,
   2836};
   2837ATTRIBUTE_GROUPS(damon_sysfs_ui_dir);
   2838
   2839static struct kobj_type damon_sysfs_ui_dir_ktype = {
   2840	.release = damon_sysfs_ui_dir_release,
   2841	.sysfs_ops = &kobj_sysfs_ops,
   2842	.default_groups = damon_sysfs_ui_dir_groups,
   2843};
   2844
   2845static int __init damon_sysfs_init(void)
   2846{
   2847	struct kobject *damon_sysfs_root;
   2848	struct damon_sysfs_ui_dir *admin;
   2849	int err;
   2850
   2851	damon_sysfs_root = kobject_create_and_add("damon", mm_kobj);
   2852	if (!damon_sysfs_root)
   2853		return -ENOMEM;
   2854
   2855	admin = damon_sysfs_ui_dir_alloc();
   2856	if (!admin) {
   2857		kobject_put(damon_sysfs_root);
   2858		return -ENOMEM;
   2859	}
   2860	err = kobject_init_and_add(&admin->kobj, &damon_sysfs_ui_dir_ktype,
   2861			damon_sysfs_root, "admin");
   2862	if (err)
   2863		goto out;
   2864	err = damon_sysfs_ui_dir_add_dirs(admin);
   2865	if (err)
   2866		goto out;
   2867	return 0;
   2868
   2869out:
   2870	kobject_put(&admin->kobj);
   2871	kobject_put(damon_sysfs_root);
   2872	return err;
   2873}
   2874subsys_initcall(damon_sysfs_init);