Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
   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/slab.h>
   9
  10#include "sysfs-common.h"
  11
  12/*
  13 * scheme region directory
  14 */
  15
  16struct damon_sysfs_scheme_region {
  17	struct kobject kobj;
  18	struct damon_addr_range ar;
  19	unsigned int nr_accesses;
  20	unsigned int age;
  21	struct list_head list;
  22};
  23
  24static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc(
  25		struct damon_region *region)
  26{
  27	struct damon_sysfs_scheme_region *sysfs_region = kmalloc(
  28			sizeof(*sysfs_region), GFP_KERNEL);
  29
  30	if (!sysfs_region)
  31		return NULL;
  32	sysfs_region->kobj = (struct kobject){};
  33	sysfs_region->ar = region->ar;
  34	sysfs_region->nr_accesses = region->nr_accesses_bp / 10000;
  35	sysfs_region->age = region->age;
  36	INIT_LIST_HEAD(&sysfs_region->list);
  37	return sysfs_region;
  38}
  39
  40static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr,
  41		char *buf)
  42{
  43	struct damon_sysfs_scheme_region *region = container_of(kobj,
  44			struct damon_sysfs_scheme_region, kobj);
  45
  46	return sysfs_emit(buf, "%lu\n", region->ar.start);
  47}
  48
  49static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr,
  50		char *buf)
  51{
  52	struct damon_sysfs_scheme_region *region = container_of(kobj,
  53			struct damon_sysfs_scheme_region, kobj);
  54
  55	return sysfs_emit(buf, "%lu\n", region->ar.end);
  56}
  57
  58static ssize_t nr_accesses_show(struct kobject *kobj,
  59		struct kobj_attribute *attr, char *buf)
  60{
  61	struct damon_sysfs_scheme_region *region = container_of(kobj,
  62			struct damon_sysfs_scheme_region, kobj);
  63
  64	return sysfs_emit(buf, "%u\n", region->nr_accesses);
  65}
  66
  67static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr,
  68		char *buf)
  69{
  70	struct damon_sysfs_scheme_region *region = container_of(kobj,
  71			struct damon_sysfs_scheme_region, kobj);
  72
  73	return sysfs_emit(buf, "%u\n", region->age);
  74}
  75
  76static void damon_sysfs_scheme_region_release(struct kobject *kobj)
  77{
  78	struct damon_sysfs_scheme_region *region = container_of(kobj,
  79			struct damon_sysfs_scheme_region, kobj);
  80
  81	list_del(&region->list);
  82	kfree(region);
  83}
  84
  85static struct kobj_attribute damon_sysfs_scheme_region_start_attr =
  86		__ATTR_RO_MODE(start, 0400);
  87
  88static struct kobj_attribute damon_sysfs_scheme_region_end_attr =
  89		__ATTR_RO_MODE(end, 0400);
  90
  91static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr =
  92		__ATTR_RO_MODE(nr_accesses, 0400);
  93
  94static struct kobj_attribute damon_sysfs_scheme_region_age_attr =
  95		__ATTR_RO_MODE(age, 0400);
  96
  97static struct attribute *damon_sysfs_scheme_region_attrs[] = {
  98	&damon_sysfs_scheme_region_start_attr.attr,
  99	&damon_sysfs_scheme_region_end_attr.attr,
 100	&damon_sysfs_scheme_region_nr_accesses_attr.attr,
 101	&damon_sysfs_scheme_region_age_attr.attr,
 102	NULL,
 103};
 104ATTRIBUTE_GROUPS(damon_sysfs_scheme_region);
 105
 106static const struct kobj_type damon_sysfs_scheme_region_ktype = {
 107	.release = damon_sysfs_scheme_region_release,
 108	.sysfs_ops = &kobj_sysfs_ops,
 109	.default_groups = damon_sysfs_scheme_region_groups,
 110};
 111
 112/*
 113 * scheme regions directory
 114 */
 115
 116/*
 117 * enum damos_sysfs_regions_upd_status - Represent DAMOS tried regions update
 118 *					 status
 119 * @DAMOS_TRIED_REGIONS_UPD_IDLE:		Waiting for next request.
 120 * @DAMOS_TRIED_REGIONS_UPD_STARTED:		Update started.
 121 * @DAMOS_TRIED_REGIONS_UPD_FINISHED:	Update finished.
 122 *
 123 * Each DAMON-based operation scheme (&struct damos) has its own apply
 124 * interval, and we need to expose the scheme tried regions based on only
 125 * single snapshot.  For this, we keep the tried regions update status for each
 126 * scheme.  The status becomes 'idle' at the beginning.
 127 *
 128 * Once the tried regions update request is received, the request handling
 129 * start function (damon_sysfs_scheme_update_regions_start()) sets the status
 130 * of all schemes as 'idle' again, and register ->before_damos_apply()
 131 * callback.
 132 *
 133 * Then, the first followup ->before_damos_apply() callback
 134 * (damon_sysfs_before_damos_apply()) sets the status 'started'.  The first
 135 * ->after_sampling() or ->after_aggregation() callback
 136 *  (damon_sysfs_cmd_request_callback()) after the call is called only after
 137 *  the scheme is completely applied to the given snapshot.  Hence the callback
 138 *  knows the situation by showing 'started' status, and sets the status as
 139 *  'finished'.  Then, damon_sysfs_before_damos_apply() understands the
 140 *  situation by showing the 'finished' status and do nothing.
 141 *
 142 * If DAMOS is not applied to any region due to any reasons including the
 143 * access pattern, the watermarks, the quotas, and the filters,
 144 * ->before_damos_apply() will not be called back.  Until the situation is
 145 * changed, the update will not be finished.  To avoid this,
 146 * damon_sysfs_after_sampling() set the status as 'finished' if more than two
 147 * apply intervals of the scheme is passed while the state is 'idle'.
 148 *
 149 *  Finally, the tried regions request handling finisher function
 150 *  (damon_sysfs_schemes_update_regions_stop()) unregisters the callbacks.
 151 */
 152enum damos_sysfs_regions_upd_status {
 153	DAMOS_TRIED_REGIONS_UPD_IDLE,
 154	DAMOS_TRIED_REGIONS_UPD_STARTED,
 155	DAMOS_TRIED_REGIONS_UPD_FINISHED,
 156};
 157
 158struct damon_sysfs_scheme_regions {
 159	struct kobject kobj;
 160	struct list_head regions_list;
 161	int nr_regions;
 162	unsigned long total_bytes;
 163	enum damos_sysfs_regions_upd_status upd_status;
 164	unsigned long upd_timeout_jiffies;
 165};
 166
 167static struct damon_sysfs_scheme_regions *
 168damon_sysfs_scheme_regions_alloc(void)
 169{
 170	struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
 171			GFP_KERNEL);
 172
 173	if (!regions)
 174		return NULL;
 175
 176	regions->kobj = (struct kobject){};
 177	INIT_LIST_HEAD(&regions->regions_list);
 178	regions->nr_regions = 0;
 179	regions->total_bytes = 0;
 180	regions->upd_status = DAMOS_TRIED_REGIONS_UPD_IDLE;
 181	return regions;
 182}
 183
 184static ssize_t total_bytes_show(struct kobject *kobj,
 185		struct kobj_attribute *attr, char *buf)
 186{
 187	struct damon_sysfs_scheme_regions *regions = container_of(kobj,
 188			struct damon_sysfs_scheme_regions, kobj);
 189
 190	return sysfs_emit(buf, "%lu\n", regions->total_bytes);
 191}
 192
 193static void damon_sysfs_scheme_regions_rm_dirs(
 194		struct damon_sysfs_scheme_regions *regions)
 195{
 196	struct damon_sysfs_scheme_region *r, *next;
 197
 198	list_for_each_entry_safe(r, next, &regions->regions_list, list) {
 199		/* release function deletes it from the list */
 200		kobject_put(&r->kobj);
 201		regions->nr_regions--;
 202	}
 203}
 204
 205static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
 206{
 207	kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
 208}
 209
 210static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr =
 211		__ATTR_RO_MODE(total_bytes, 0400);
 212
 213static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
 214	&damon_sysfs_scheme_regions_total_bytes_attr.attr,
 215	NULL,
 216};
 217ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
 218
 219static const struct kobj_type damon_sysfs_scheme_regions_ktype = {
 220	.release = damon_sysfs_scheme_regions_release,
 221	.sysfs_ops = &kobj_sysfs_ops,
 222	.default_groups = damon_sysfs_scheme_regions_groups,
 223};
 224
 225/*
 226 * schemes/stats directory
 227 */
 228
 229struct damon_sysfs_stats {
 230	struct kobject kobj;
 231	unsigned long nr_tried;
 232	unsigned long sz_tried;
 233	unsigned long nr_applied;
 234	unsigned long sz_applied;
 235	unsigned long qt_exceeds;
 236};
 237
 238static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
 239{
 240	return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
 241}
 242
 243static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
 244		char *buf)
 245{
 246	struct damon_sysfs_stats *stats = container_of(kobj,
 247			struct damon_sysfs_stats, kobj);
 248
 249	return sysfs_emit(buf, "%lu\n", stats->nr_tried);
 250}
 251
 252static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
 253		char *buf)
 254{
 255	struct damon_sysfs_stats *stats = container_of(kobj,
 256			struct damon_sysfs_stats, kobj);
 257
 258	return sysfs_emit(buf, "%lu\n", stats->sz_tried);
 259}
 260
 261static ssize_t nr_applied_show(struct kobject *kobj,
 262		struct kobj_attribute *attr, char *buf)
 263{
 264	struct damon_sysfs_stats *stats = container_of(kobj,
 265			struct damon_sysfs_stats, kobj);
 266
 267	return sysfs_emit(buf, "%lu\n", stats->nr_applied);
 268}
 269
 270static ssize_t sz_applied_show(struct kobject *kobj,
 271		struct kobj_attribute *attr, char *buf)
 272{
 273	struct damon_sysfs_stats *stats = container_of(kobj,
 274			struct damon_sysfs_stats, kobj);
 275
 276	return sysfs_emit(buf, "%lu\n", stats->sz_applied);
 277}
 278
 279static ssize_t qt_exceeds_show(struct kobject *kobj,
 280		struct kobj_attribute *attr, char *buf)
 281{
 282	struct damon_sysfs_stats *stats = container_of(kobj,
 283			struct damon_sysfs_stats, kobj);
 284
 285	return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
 286}
 287
 288static void damon_sysfs_stats_release(struct kobject *kobj)
 289{
 290	kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
 291}
 292
 293static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
 294		__ATTR_RO_MODE(nr_tried, 0400);
 295
 296static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
 297		__ATTR_RO_MODE(sz_tried, 0400);
 298
 299static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
 300		__ATTR_RO_MODE(nr_applied, 0400);
 301
 302static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
 303		__ATTR_RO_MODE(sz_applied, 0400);
 304
 305static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
 306		__ATTR_RO_MODE(qt_exceeds, 0400);
 307
 308static struct attribute *damon_sysfs_stats_attrs[] = {
 309	&damon_sysfs_stats_nr_tried_attr.attr,
 310	&damon_sysfs_stats_sz_tried_attr.attr,
 311	&damon_sysfs_stats_nr_applied_attr.attr,
 312	&damon_sysfs_stats_sz_applied_attr.attr,
 313	&damon_sysfs_stats_qt_exceeds_attr.attr,
 314	NULL,
 315};
 316ATTRIBUTE_GROUPS(damon_sysfs_stats);
 317
 318static const struct kobj_type damon_sysfs_stats_ktype = {
 319	.release = damon_sysfs_stats_release,
 320	.sysfs_ops = &kobj_sysfs_ops,
 321	.default_groups = damon_sysfs_stats_groups,
 322};
 323
 324/*
 325 * filter directory
 326 */
 327
 328struct damon_sysfs_scheme_filter {
 329	struct kobject kobj;
 330	enum damos_filter_type type;
 331	bool matching;
 332	char *memcg_path;
 333	struct damon_addr_range addr_range;
 334	int target_idx;
 335};
 336
 337static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void)
 338{
 339	return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL);
 340}
 341
 342/* Should match with enum damos_filter_type */
 343static const char * const damon_sysfs_scheme_filter_type_strs[] = {
 344	"anon",
 345	"memcg",
 346	"addr",
 347	"target",
 348};
 349
 350static ssize_t type_show(struct kobject *kobj,
 351		struct kobj_attribute *attr, char *buf)
 352{
 353	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 354			struct damon_sysfs_scheme_filter, kobj);
 355
 356	return sysfs_emit(buf, "%s\n",
 357			damon_sysfs_scheme_filter_type_strs[filter->type]);
 358}
 359
 360static ssize_t type_store(struct kobject *kobj,
 361		struct kobj_attribute *attr, const char *buf, size_t count)
 362{
 363	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 364			struct damon_sysfs_scheme_filter, kobj);
 365	enum damos_filter_type type;
 366	ssize_t ret = -EINVAL;
 367
 368	for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) {
 369		if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[
 370					type])) {
 371			filter->type = type;
 372			ret = count;
 373			break;
 374		}
 375	}
 376	return ret;
 377}
 378
 379static ssize_t matching_show(struct kobject *kobj,
 380		struct kobj_attribute *attr, char *buf)
 381{
 382	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 383			struct damon_sysfs_scheme_filter, kobj);
 384
 385	return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
 386}
 387
 388static ssize_t matching_store(struct kobject *kobj,
 389		struct kobj_attribute *attr, const char *buf, size_t count)
 390{
 391	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 392			struct damon_sysfs_scheme_filter, kobj);
 393	bool matching;
 394	int err = kstrtobool(buf, &matching);
 395
 396	if (err)
 397		return err;
 398
 399	filter->matching = matching;
 400	return count;
 401}
 402
 403static ssize_t memcg_path_show(struct kobject *kobj,
 404		struct kobj_attribute *attr, char *buf)
 405{
 406	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 407			struct damon_sysfs_scheme_filter, kobj);
 408
 409	return sysfs_emit(buf, "%s\n",
 410			filter->memcg_path ? filter->memcg_path : "");
 411}
 412
 413static ssize_t memcg_path_store(struct kobject *kobj,
 414		struct kobj_attribute *attr, const char *buf, size_t count)
 415{
 416	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 417			struct damon_sysfs_scheme_filter, kobj);
 418	char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL);
 419
 420	if (!path)
 421		return -ENOMEM;
 422
 423	strscpy(path, buf, count + 1);
 424	filter->memcg_path = path;
 425	return count;
 426}
 427
 428static ssize_t addr_start_show(struct kobject *kobj,
 429		struct kobj_attribute *attr, char *buf)
 430{
 431	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 432			struct damon_sysfs_scheme_filter, kobj);
 433
 434	return sysfs_emit(buf, "%lu\n", filter->addr_range.start);
 435}
 436
 437static ssize_t addr_start_store(struct kobject *kobj,
 438		struct kobj_attribute *attr, const char *buf, size_t count)
 439{
 440	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 441			struct damon_sysfs_scheme_filter, kobj);
 442	int err = kstrtoul(buf, 0, &filter->addr_range.start);
 443
 444	return err ? err : count;
 445}
 446
 447static ssize_t addr_end_show(struct kobject *kobj,
 448		struct kobj_attribute *attr, char *buf)
 449{
 450	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 451			struct damon_sysfs_scheme_filter, kobj);
 452
 453	return sysfs_emit(buf, "%lu\n", filter->addr_range.end);
 454}
 455
 456static ssize_t addr_end_store(struct kobject *kobj,
 457		struct kobj_attribute *attr, const char *buf, size_t count)
 458{
 459	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 460			struct damon_sysfs_scheme_filter, kobj);
 461	int err = kstrtoul(buf, 0, &filter->addr_range.end);
 462
 463	return err ? err : count;
 464}
 465
 466static ssize_t damon_target_idx_show(struct kobject *kobj,
 467		struct kobj_attribute *attr, char *buf)
 468{
 469	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 470			struct damon_sysfs_scheme_filter, kobj);
 471
 472	return sysfs_emit(buf, "%d\n", filter->target_idx);
 473}
 474
 475static ssize_t damon_target_idx_store(struct kobject *kobj,
 476		struct kobj_attribute *attr, const char *buf, size_t count)
 477{
 478	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 479			struct damon_sysfs_scheme_filter, kobj);
 480	int err = kstrtoint(buf, 0, &filter->target_idx);
 481
 482	return err ? err : count;
 483}
 484
 485static void damon_sysfs_scheme_filter_release(struct kobject *kobj)
 486{
 487	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 488			struct damon_sysfs_scheme_filter, kobj);
 489
 490	kfree(filter->memcg_path);
 491	kfree(filter);
 492}
 493
 494static struct kobj_attribute damon_sysfs_scheme_filter_type_attr =
 495		__ATTR_RW_MODE(type, 0600);
 496
 497static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr =
 498		__ATTR_RW_MODE(matching, 0600);
 499
 500static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr =
 501		__ATTR_RW_MODE(memcg_path, 0600);
 502
 503static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr =
 504		__ATTR_RW_MODE(addr_start, 0600);
 505
 506static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr =
 507		__ATTR_RW_MODE(addr_end, 0600);
 508
 509static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr =
 510		__ATTR_RW_MODE(damon_target_idx, 0600);
 511
 512static struct attribute *damon_sysfs_scheme_filter_attrs[] = {
 513	&damon_sysfs_scheme_filter_type_attr.attr,
 514	&damon_sysfs_scheme_filter_matching_attr.attr,
 515	&damon_sysfs_scheme_filter_memcg_path_attr.attr,
 516	&damon_sysfs_scheme_filter_addr_start_attr.attr,
 517	&damon_sysfs_scheme_filter_addr_end_attr.attr,
 518	&damon_sysfs_scheme_filter_damon_target_idx_attr.attr,
 519	NULL,
 520};
 521ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter);
 522
 523static const struct kobj_type damon_sysfs_scheme_filter_ktype = {
 524	.release = damon_sysfs_scheme_filter_release,
 525	.sysfs_ops = &kobj_sysfs_ops,
 526	.default_groups = damon_sysfs_scheme_filter_groups,
 527};
 528
 529/*
 530 * filters directory
 531 */
 532
 533struct damon_sysfs_scheme_filters {
 534	struct kobject kobj;
 535	struct damon_sysfs_scheme_filter **filters_arr;
 536	int nr;
 537};
 538
 539static struct damon_sysfs_scheme_filters *
 540damon_sysfs_scheme_filters_alloc(void)
 541{
 542	return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL);
 543}
 544
 545static void damon_sysfs_scheme_filters_rm_dirs(
 546		struct damon_sysfs_scheme_filters *filters)
 547{
 548	struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr;
 549	int i;
 550
 551	for (i = 0; i < filters->nr; i++)
 552		kobject_put(&filters_arr[i]->kobj);
 553	filters->nr = 0;
 554	kfree(filters_arr);
 555	filters->filters_arr = NULL;
 556}
 557
 558static int damon_sysfs_scheme_filters_add_dirs(
 559		struct damon_sysfs_scheme_filters *filters, int nr_filters)
 560{
 561	struct damon_sysfs_scheme_filter **filters_arr, *filter;
 562	int err, i;
 563
 564	damon_sysfs_scheme_filters_rm_dirs(filters);
 565	if (!nr_filters)
 566		return 0;
 567
 568	filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
 569			GFP_KERNEL | __GFP_NOWARN);
 570	if (!filters_arr)
 571		return -ENOMEM;
 572	filters->filters_arr = filters_arr;
 573
 574	for (i = 0; i < nr_filters; i++) {
 575		filter = damon_sysfs_scheme_filter_alloc();
 576		if (!filter) {
 577			damon_sysfs_scheme_filters_rm_dirs(filters);
 578			return -ENOMEM;
 579		}
 580
 581		err = kobject_init_and_add(&filter->kobj,
 582				&damon_sysfs_scheme_filter_ktype,
 583				&filters->kobj, "%d", i);
 584		if (err) {
 585			kobject_put(&filter->kobj);
 586			damon_sysfs_scheme_filters_rm_dirs(filters);
 587			return err;
 588		}
 589
 590		filters_arr[i] = filter;
 591		filters->nr++;
 592	}
 593	return 0;
 594}
 595
 596static ssize_t nr_filters_show(struct kobject *kobj,
 597		struct kobj_attribute *attr, char *buf)
 598{
 599	struct damon_sysfs_scheme_filters *filters = container_of(kobj,
 600			struct damon_sysfs_scheme_filters, kobj);
 601
 602	return sysfs_emit(buf, "%d\n", filters->nr);
 603}
 604
 605static ssize_t nr_filters_store(struct kobject *kobj,
 606		struct kobj_attribute *attr, const char *buf, size_t count)
 607{
 608	struct damon_sysfs_scheme_filters *filters;
 609	int nr, err = kstrtoint(buf, 0, &nr);
 610
 611	if (err)
 612		return err;
 613	if (nr < 0)
 614		return -EINVAL;
 615
 616	filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj);
 617
 618	if (!mutex_trylock(&damon_sysfs_lock))
 619		return -EBUSY;
 620	err = damon_sysfs_scheme_filters_add_dirs(filters, nr);
 621	mutex_unlock(&damon_sysfs_lock);
 622	if (err)
 623		return err;
 624
 625	return count;
 626}
 627
 628static void damon_sysfs_scheme_filters_release(struct kobject *kobj)
 629{
 630	kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj));
 631}
 632
 633static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr =
 634		__ATTR_RW_MODE(nr_filters, 0600);
 635
 636static struct attribute *damon_sysfs_scheme_filters_attrs[] = {
 637	&damon_sysfs_scheme_filters_nr_attr.attr,
 638	NULL,
 639};
 640ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters);
 641
 642static const struct kobj_type damon_sysfs_scheme_filters_ktype = {
 643	.release = damon_sysfs_scheme_filters_release,
 644	.sysfs_ops = &kobj_sysfs_ops,
 645	.default_groups = damon_sysfs_scheme_filters_groups,
 646};
 647
 648/*
 649 * watermarks directory
 650 */
 651
 652struct damon_sysfs_watermarks {
 653	struct kobject kobj;
 654	enum damos_wmark_metric metric;
 655	unsigned long interval_us;
 656	unsigned long high;
 657	unsigned long mid;
 658	unsigned long low;
 659};
 660
 661static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
 662		enum damos_wmark_metric metric, unsigned long interval_us,
 663		unsigned long high, unsigned long mid, unsigned long low)
 664{
 665	struct damon_sysfs_watermarks *watermarks = kmalloc(
 666			sizeof(*watermarks), GFP_KERNEL);
 667
 668	if (!watermarks)
 669		return NULL;
 670	watermarks->kobj = (struct kobject){};
 671	watermarks->metric = metric;
 672	watermarks->interval_us = interval_us;
 673	watermarks->high = high;
 674	watermarks->mid = mid;
 675	watermarks->low = low;
 676	return watermarks;
 677}
 678
 679/* Should match with enum damos_wmark_metric */
 680static const char * const damon_sysfs_wmark_metric_strs[] = {
 681	"none",
 682	"free_mem_rate",
 683};
 684
 685static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
 686		char *buf)
 687{
 688	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 689			struct damon_sysfs_watermarks, kobj);
 690
 691	return sysfs_emit(buf, "%s\n",
 692			damon_sysfs_wmark_metric_strs[watermarks->metric]);
 693}
 694
 695static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
 696		const char *buf, size_t count)
 697{
 698	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 699			struct damon_sysfs_watermarks, kobj);
 700	enum damos_wmark_metric metric;
 701
 702	for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
 703		if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
 704			watermarks->metric = metric;
 705			return count;
 706		}
 707	}
 708	return -EINVAL;
 709}
 710
 711static ssize_t interval_us_show(struct kobject *kobj,
 712		struct kobj_attribute *attr, char *buf)
 713{
 714	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 715			struct damon_sysfs_watermarks, kobj);
 716
 717	return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
 718}
 719
 720static ssize_t interval_us_store(struct kobject *kobj,
 721		struct kobj_attribute *attr, const char *buf, size_t count)
 722{
 723	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 724			struct damon_sysfs_watermarks, kobj);
 725	int err = kstrtoul(buf, 0, &watermarks->interval_us);
 726
 727	return err ? err : count;
 728}
 729
 730static ssize_t high_show(struct kobject *kobj,
 731		struct kobj_attribute *attr, char *buf)
 732{
 733	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 734			struct damon_sysfs_watermarks, kobj);
 735
 736	return sysfs_emit(buf, "%lu\n", watermarks->high);
 737}
 738
 739static ssize_t high_store(struct kobject *kobj,
 740		struct kobj_attribute *attr, const char *buf, size_t count)
 741{
 742	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 743			struct damon_sysfs_watermarks, kobj);
 744	int err = kstrtoul(buf, 0, &watermarks->high);
 745
 746	return err ? err : count;
 747}
 748
 749static ssize_t mid_show(struct kobject *kobj,
 750		struct kobj_attribute *attr, char *buf)
 751{
 752	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 753			struct damon_sysfs_watermarks, kobj);
 754
 755	return sysfs_emit(buf, "%lu\n", watermarks->mid);
 756}
 757
 758static ssize_t mid_store(struct kobject *kobj,
 759		struct kobj_attribute *attr, const char *buf, size_t count)
 760{
 761	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 762			struct damon_sysfs_watermarks, kobj);
 763	int err = kstrtoul(buf, 0, &watermarks->mid);
 764
 765	return err ? err : count;
 766}
 767
 768static ssize_t low_show(struct kobject *kobj,
 769		struct kobj_attribute *attr, char *buf)
 770{
 771	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 772			struct damon_sysfs_watermarks, kobj);
 773
 774	return sysfs_emit(buf, "%lu\n", watermarks->low);
 775}
 776
 777static ssize_t low_store(struct kobject *kobj,
 778		struct kobj_attribute *attr, const char *buf, size_t count)
 779{
 780	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 781			struct damon_sysfs_watermarks, kobj);
 782	int err = kstrtoul(buf, 0, &watermarks->low);
 783
 784	return err ? err : count;
 785}
 786
 787static void damon_sysfs_watermarks_release(struct kobject *kobj)
 788{
 789	kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
 790}
 791
 792static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
 793		__ATTR_RW_MODE(metric, 0600);
 794
 795static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
 796		__ATTR_RW_MODE(interval_us, 0600);
 797
 798static struct kobj_attribute damon_sysfs_watermarks_high_attr =
 799		__ATTR_RW_MODE(high, 0600);
 800
 801static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
 802		__ATTR_RW_MODE(mid, 0600);
 803
 804static struct kobj_attribute damon_sysfs_watermarks_low_attr =
 805		__ATTR_RW_MODE(low, 0600);
 806
 807static struct attribute *damon_sysfs_watermarks_attrs[] = {
 808	&damon_sysfs_watermarks_metric_attr.attr,
 809	&damon_sysfs_watermarks_interval_us_attr.attr,
 810	&damon_sysfs_watermarks_high_attr.attr,
 811	&damon_sysfs_watermarks_mid_attr.attr,
 812	&damon_sysfs_watermarks_low_attr.attr,
 813	NULL,
 814};
 815ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
 816
 817static const struct kobj_type damon_sysfs_watermarks_ktype = {
 818	.release = damon_sysfs_watermarks_release,
 819	.sysfs_ops = &kobj_sysfs_ops,
 820	.default_groups = damon_sysfs_watermarks_groups,
 821};
 822
 823/*
 824 * quota goal directory
 825 */
 826
 827struct damos_sysfs_quota_goal {
 828	struct kobject kobj;
 829	enum damos_quota_goal_metric metric;
 830	unsigned long target_value;
 831	unsigned long current_value;
 832};
 833
 834/* This should match with enum damos_action */
 835static const char * const damos_sysfs_quota_goal_metric_strs[] = {
 836	"user_input",
 837	"some_mem_psi_us",
 838};
 839
 840static struct damos_sysfs_quota_goal *damos_sysfs_quota_goal_alloc(void)
 841{
 842	return kzalloc(sizeof(struct damos_sysfs_quota_goal), GFP_KERNEL);
 843}
 844
 845static ssize_t target_metric_show(struct kobject *kobj,
 846		struct kobj_attribute *attr, char *buf)
 847{
 848	struct damos_sysfs_quota_goal *goal = container_of(kobj,
 849			struct damos_sysfs_quota_goal, kobj);
 850
 851	return sysfs_emit(buf, "%s\n",
 852			damos_sysfs_quota_goal_metric_strs[goal->metric]);
 853}
 854
 855static ssize_t target_metric_store(struct kobject *kobj,
 856		struct kobj_attribute *attr, const char *buf, size_t count)
 857{
 858	struct damos_sysfs_quota_goal *goal = container_of(kobj,
 859			struct damos_sysfs_quota_goal, kobj);
 860	enum damos_quota_goal_metric m;
 861
 862	for (m = 0; m < NR_DAMOS_QUOTA_GOAL_METRICS; m++) {
 863		if (sysfs_streq(buf, damos_sysfs_quota_goal_metric_strs[m])) {
 864			goal->metric = m;
 865			return count;
 866		}
 867	}
 868	return -EINVAL;
 869}
 870
 871static ssize_t target_value_show(struct kobject *kobj,
 872		struct kobj_attribute *attr, char *buf)
 873{
 874	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
 875			damos_sysfs_quota_goal, kobj);
 876
 877	return sysfs_emit(buf, "%lu\n", goal->target_value);
 878}
 879
 880static ssize_t target_value_store(struct kobject *kobj,
 881		struct kobj_attribute *attr, const char *buf, size_t count)
 882{
 883	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
 884			damos_sysfs_quota_goal, kobj);
 885	int err = kstrtoul(buf, 0, &goal->target_value);
 886
 887	return err ? err : count;
 888}
 889
 890static ssize_t current_value_show(struct kobject *kobj,
 891		struct kobj_attribute *attr, char *buf)
 892{
 893	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
 894			damos_sysfs_quota_goal, kobj);
 895
 896	return sysfs_emit(buf, "%lu\n", goal->current_value);
 897}
 898
 899static ssize_t current_value_store(struct kobject *kobj,
 900		struct kobj_attribute *attr, const char *buf, size_t count)
 901{
 902	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
 903			damos_sysfs_quota_goal, kobj);
 904	int err = kstrtoul(buf, 0, &goal->current_value);
 905
 906	/* feed callback should check existence of this file and read value */
 907	return err ? err : count;
 908}
 909
 910static void damos_sysfs_quota_goal_release(struct kobject *kobj)
 911{
 912	/* or, notify this release to the feed callback */
 913	kfree(container_of(kobj, struct damos_sysfs_quota_goal, kobj));
 914}
 915
 916static struct kobj_attribute damos_sysfs_quota_goal_target_metric_attr =
 917		__ATTR_RW_MODE(target_metric, 0600);
 918
 919static struct kobj_attribute damos_sysfs_quota_goal_target_value_attr =
 920		__ATTR_RW_MODE(target_value, 0600);
 921
 922static struct kobj_attribute damos_sysfs_quota_goal_current_value_attr =
 923		__ATTR_RW_MODE(current_value, 0600);
 924
 925static struct attribute *damos_sysfs_quota_goal_attrs[] = {
 926	&damos_sysfs_quota_goal_target_metric_attr.attr,
 927	&damos_sysfs_quota_goal_target_value_attr.attr,
 928	&damos_sysfs_quota_goal_current_value_attr.attr,
 929	NULL,
 930};
 931ATTRIBUTE_GROUPS(damos_sysfs_quota_goal);
 932
 933static const struct kobj_type damos_sysfs_quota_goal_ktype = {
 934	.release = damos_sysfs_quota_goal_release,
 935	.sysfs_ops = &kobj_sysfs_ops,
 936	.default_groups = damos_sysfs_quota_goal_groups,
 937};
 938
 939/*
 940 * quota goals directory
 941 */
 942
 943struct damos_sysfs_quota_goals {
 944	struct kobject kobj;
 945	struct damos_sysfs_quota_goal **goals_arr;	/* counted by nr */
 946	int nr;
 947};
 948
 949static struct damos_sysfs_quota_goals *damos_sysfs_quota_goals_alloc(void)
 950{
 951	return kzalloc(sizeof(struct damos_sysfs_quota_goals), GFP_KERNEL);
 952}
 953
 954static void damos_sysfs_quota_goals_rm_dirs(
 955		struct damos_sysfs_quota_goals *goals)
 956{
 957	struct damos_sysfs_quota_goal **goals_arr = goals->goals_arr;
 958	int i;
 959
 960	for (i = 0; i < goals->nr; i++)
 961		kobject_put(&goals_arr[i]->kobj);
 962	goals->nr = 0;
 963	kfree(goals_arr);
 964	goals->goals_arr = NULL;
 965}
 966
 967static int damos_sysfs_quota_goals_add_dirs(
 968		struct damos_sysfs_quota_goals *goals, int nr_goals)
 969{
 970	struct damos_sysfs_quota_goal **goals_arr, *goal;
 971	int err, i;
 972
 973	damos_sysfs_quota_goals_rm_dirs(goals);
 974	if (!nr_goals)
 975		return 0;
 976
 977	goals_arr = kmalloc_array(nr_goals, sizeof(*goals_arr),
 978			GFP_KERNEL | __GFP_NOWARN);
 979	if (!goals_arr)
 980		return -ENOMEM;
 981	goals->goals_arr = goals_arr;
 982
 983	for (i = 0; i < nr_goals; i++) {
 984		goal = damos_sysfs_quota_goal_alloc();
 985		if (!goal) {
 986			damos_sysfs_quota_goals_rm_dirs(goals);
 987			return -ENOMEM;
 988		}
 989
 990		err = kobject_init_and_add(&goal->kobj,
 991				&damos_sysfs_quota_goal_ktype, &goals->kobj,
 992				"%d", i);
 993		if (err) {
 994			kobject_put(&goal->kobj);
 995			damos_sysfs_quota_goals_rm_dirs(goals);
 996			return err;
 997		}
 998
 999		goals_arr[i] = goal;
1000		goals->nr++;
1001	}
1002	return 0;
1003}
1004
1005static ssize_t nr_goals_show(struct kobject *kobj,
1006		struct kobj_attribute *attr, char *buf)
1007{
1008	struct damos_sysfs_quota_goals *goals = container_of(kobj,
1009			struct damos_sysfs_quota_goals, kobj);
1010
1011	return sysfs_emit(buf, "%d\n", goals->nr);
1012}
1013
1014static ssize_t nr_goals_store(struct kobject *kobj,
1015		struct kobj_attribute *attr, const char *buf, size_t count)
1016{
1017	struct damos_sysfs_quota_goals *goals;
1018	int nr, err = kstrtoint(buf, 0, &nr);
1019
1020	if (err)
1021		return err;
1022	if (nr < 0)
1023		return -EINVAL;
1024
1025	goals = container_of(kobj, struct damos_sysfs_quota_goals, kobj);
1026
1027	if (!mutex_trylock(&damon_sysfs_lock))
1028		return -EBUSY;
1029	err = damos_sysfs_quota_goals_add_dirs(goals, nr);
1030	mutex_unlock(&damon_sysfs_lock);
1031	if (err)
1032		return err;
1033
1034	return count;
1035}
1036
1037static void damos_sysfs_quota_goals_release(struct kobject *kobj)
1038{
1039	kfree(container_of(kobj, struct damos_sysfs_quota_goals, kobj));
1040}
1041
1042static struct kobj_attribute damos_sysfs_quota_goals_nr_attr =
1043		__ATTR_RW_MODE(nr_goals, 0600);
1044
1045static struct attribute *damos_sysfs_quota_goals_attrs[] = {
1046	&damos_sysfs_quota_goals_nr_attr.attr,
1047	NULL,
1048};
1049ATTRIBUTE_GROUPS(damos_sysfs_quota_goals);
1050
1051static const struct kobj_type damos_sysfs_quota_goals_ktype = {
1052	.release = damos_sysfs_quota_goals_release,
1053	.sysfs_ops = &kobj_sysfs_ops,
1054	.default_groups = damos_sysfs_quota_goals_groups,
1055};
1056
1057/*
1058 * scheme/weights directory
1059 */
1060
1061struct damon_sysfs_weights {
1062	struct kobject kobj;
1063	unsigned int sz;
1064	unsigned int nr_accesses;
1065	unsigned int age;
1066};
1067
1068static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
1069		unsigned int nr_accesses, unsigned int age)
1070{
1071	struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
1072			GFP_KERNEL);
1073
1074	if (!weights)
1075		return NULL;
1076	weights->kobj = (struct kobject){};
1077	weights->sz = sz;
1078	weights->nr_accesses = nr_accesses;
1079	weights->age = age;
1080	return weights;
1081}
1082
1083static ssize_t sz_permil_show(struct kobject *kobj,
1084		struct kobj_attribute *attr, char *buf)
1085{
1086	struct damon_sysfs_weights *weights = container_of(kobj,
1087			struct damon_sysfs_weights, kobj);
1088
1089	return sysfs_emit(buf, "%u\n", weights->sz);
1090}
1091
1092static ssize_t sz_permil_store(struct kobject *kobj,
1093		struct kobj_attribute *attr, const char *buf, size_t count)
1094{
1095	struct damon_sysfs_weights *weights = container_of(kobj,
1096			struct damon_sysfs_weights, kobj);
1097	int err = kstrtouint(buf, 0, &weights->sz);
1098
1099	return err ? err : count;
1100}
1101
1102static ssize_t nr_accesses_permil_show(struct kobject *kobj,
1103		struct kobj_attribute *attr, char *buf)
1104{
1105	struct damon_sysfs_weights *weights = container_of(kobj,
1106			struct damon_sysfs_weights, kobj);
1107
1108	return sysfs_emit(buf, "%u\n", weights->nr_accesses);
1109}
1110
1111static ssize_t nr_accesses_permil_store(struct kobject *kobj,
1112		struct kobj_attribute *attr, const char *buf, size_t count)
1113{
1114	struct damon_sysfs_weights *weights = container_of(kobj,
1115			struct damon_sysfs_weights, kobj);
1116	int err = kstrtouint(buf, 0, &weights->nr_accesses);
1117
1118	return err ? err : count;
1119}
1120
1121static ssize_t age_permil_show(struct kobject *kobj,
1122		struct kobj_attribute *attr, char *buf)
1123{
1124	struct damon_sysfs_weights *weights = container_of(kobj,
1125			struct damon_sysfs_weights, kobj);
1126
1127	return sysfs_emit(buf, "%u\n", weights->age);
1128}
1129
1130static ssize_t age_permil_store(struct kobject *kobj,
1131		struct kobj_attribute *attr, const char *buf, size_t count)
1132{
1133	struct damon_sysfs_weights *weights = container_of(kobj,
1134			struct damon_sysfs_weights, kobj);
1135	int err = kstrtouint(buf, 0, &weights->age);
1136
1137	return err ? err : count;
1138}
1139
1140static void damon_sysfs_weights_release(struct kobject *kobj)
1141{
1142	kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
1143}
1144
1145static struct kobj_attribute damon_sysfs_weights_sz_attr =
1146		__ATTR_RW_MODE(sz_permil, 0600);
1147
1148static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
1149		__ATTR_RW_MODE(nr_accesses_permil, 0600);
1150
1151static struct kobj_attribute damon_sysfs_weights_age_attr =
1152		__ATTR_RW_MODE(age_permil, 0600);
1153
1154static struct attribute *damon_sysfs_weights_attrs[] = {
1155	&damon_sysfs_weights_sz_attr.attr,
1156	&damon_sysfs_weights_nr_accesses_attr.attr,
1157	&damon_sysfs_weights_age_attr.attr,
1158	NULL,
1159};
1160ATTRIBUTE_GROUPS(damon_sysfs_weights);
1161
1162static const struct kobj_type damon_sysfs_weights_ktype = {
1163	.release = damon_sysfs_weights_release,
1164	.sysfs_ops = &kobj_sysfs_ops,
1165	.default_groups = damon_sysfs_weights_groups,
1166};
1167
1168/*
1169 * quotas directory
1170 */
1171
1172struct damon_sysfs_quotas {
1173	struct kobject kobj;
1174	struct damon_sysfs_weights *weights;
1175	struct damos_sysfs_quota_goals *goals;
1176	unsigned long ms;
1177	unsigned long sz;
1178	unsigned long reset_interval_ms;
1179	unsigned long effective_sz;	/* Effective size quota in bytes */
1180};
1181
1182static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
1183{
1184	return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
1185}
1186
1187static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
1188{
1189	struct damon_sysfs_weights *weights;
1190	struct damos_sysfs_quota_goals *goals;
1191	int err;
1192
1193	weights = damon_sysfs_weights_alloc(0, 0, 0);
1194	if (!weights)
1195		return -ENOMEM;
1196
1197	err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
1198			&quotas->kobj, "weights");
1199	if (err) {
1200		kobject_put(&weights->kobj);
1201		return err;
1202	}
1203	quotas->weights = weights;
1204
1205	goals = damos_sysfs_quota_goals_alloc();
1206	if (!goals) {
1207		kobject_put(&weights->kobj);
1208		return -ENOMEM;
1209	}
1210	err = kobject_init_and_add(&goals->kobj,
1211			&damos_sysfs_quota_goals_ktype, &quotas->kobj,
1212			"goals");
1213	if (err) {
1214		kobject_put(&weights->kobj);
1215		kobject_put(&goals->kobj);
1216	} else {
1217		quotas->goals = goals;
1218	}
1219
1220	return err;
1221}
1222
1223static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
1224{
1225	kobject_put(&quotas->weights->kobj);
1226	damos_sysfs_quota_goals_rm_dirs(quotas->goals);
1227	kobject_put(&quotas->goals->kobj);
1228}
1229
1230static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
1231		char *buf)
1232{
1233	struct damon_sysfs_quotas *quotas = container_of(kobj,
1234			struct damon_sysfs_quotas, kobj);
1235
1236	return sysfs_emit(buf, "%lu\n", quotas->ms);
1237}
1238
1239static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
1240		const char *buf, size_t count)
1241{
1242	struct damon_sysfs_quotas *quotas = container_of(kobj,
1243			struct damon_sysfs_quotas, kobj);
1244	int err = kstrtoul(buf, 0, &quotas->ms);
1245
1246	if (err)
1247		return -EINVAL;
1248	return count;
1249}
1250
1251static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
1252		char *buf)
1253{
1254	struct damon_sysfs_quotas *quotas = container_of(kobj,
1255			struct damon_sysfs_quotas, kobj);
1256
1257	return sysfs_emit(buf, "%lu\n", quotas->sz);
1258}
1259
1260static ssize_t bytes_store(struct kobject *kobj,
1261		struct kobj_attribute *attr, const char *buf, size_t count)
1262{
1263	struct damon_sysfs_quotas *quotas = container_of(kobj,
1264			struct damon_sysfs_quotas, kobj);
1265	int err = kstrtoul(buf, 0, &quotas->sz);
1266
1267	if (err)
1268		return -EINVAL;
1269	return count;
1270}
1271
1272static ssize_t reset_interval_ms_show(struct kobject *kobj,
1273		struct kobj_attribute *attr, char *buf)
1274{
1275	struct damon_sysfs_quotas *quotas = container_of(kobj,
1276			struct damon_sysfs_quotas, kobj);
1277
1278	return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
1279}
1280
1281static ssize_t reset_interval_ms_store(struct kobject *kobj,
1282		struct kobj_attribute *attr, const char *buf, size_t count)
1283{
1284	struct damon_sysfs_quotas *quotas = container_of(kobj,
1285			struct damon_sysfs_quotas, kobj);
1286	int err = kstrtoul(buf, 0, &quotas->reset_interval_ms);
1287
1288	if (err)
1289		return -EINVAL;
1290	return count;
1291}
1292
1293static ssize_t effective_bytes_show(struct kobject *kobj,
1294		struct kobj_attribute *attr, char *buf)
1295{
1296	struct damon_sysfs_quotas *quotas = container_of(kobj,
1297			struct damon_sysfs_quotas, kobj);
1298
1299	return sysfs_emit(buf, "%lu\n", quotas->effective_sz);
1300}
1301
1302static void damon_sysfs_quotas_release(struct kobject *kobj)
1303{
1304	kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
1305}
1306
1307static struct kobj_attribute damon_sysfs_quotas_ms_attr =
1308		__ATTR_RW_MODE(ms, 0600);
1309
1310static struct kobj_attribute damon_sysfs_quotas_sz_attr =
1311		__ATTR_RW_MODE(bytes, 0600);
1312
1313static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
1314		__ATTR_RW_MODE(reset_interval_ms, 0600);
1315
1316static struct kobj_attribute damon_sysfs_quotas_effective_bytes_attr =
1317		__ATTR_RO_MODE(effective_bytes, 0400);
1318
1319static struct attribute *damon_sysfs_quotas_attrs[] = {
1320	&damon_sysfs_quotas_ms_attr.attr,
1321	&damon_sysfs_quotas_sz_attr.attr,
1322	&damon_sysfs_quotas_reset_interval_ms_attr.attr,
1323	&damon_sysfs_quotas_effective_bytes_attr.attr,
1324	NULL,
1325};
1326ATTRIBUTE_GROUPS(damon_sysfs_quotas);
1327
1328static const struct kobj_type damon_sysfs_quotas_ktype = {
1329	.release = damon_sysfs_quotas_release,
1330	.sysfs_ops = &kobj_sysfs_ops,
1331	.default_groups = damon_sysfs_quotas_groups,
1332};
1333
1334/*
1335 * access_pattern directory
1336 */
1337
1338struct damon_sysfs_access_pattern {
1339	struct kobject kobj;
1340	struct damon_sysfs_ul_range *sz;
1341	struct damon_sysfs_ul_range *nr_accesses;
1342	struct damon_sysfs_ul_range *age;
1343};
1344
1345static
1346struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
1347{
1348	struct damon_sysfs_access_pattern *access_pattern =
1349		kmalloc(sizeof(*access_pattern), GFP_KERNEL);
1350
1351	if (!access_pattern)
1352		return NULL;
1353	access_pattern->kobj = (struct kobject){};
1354	return access_pattern;
1355}
1356
1357static int damon_sysfs_access_pattern_add_range_dir(
1358		struct damon_sysfs_access_pattern *access_pattern,
1359		struct damon_sysfs_ul_range **range_dir_ptr,
1360		char *name)
1361{
1362	struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
1363	int err;
1364
1365	if (!range)
1366		return -ENOMEM;
1367	err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
1368			&access_pattern->kobj, name);
1369	if (err)
1370		kobject_put(&range->kobj);
1371	else
1372		*range_dir_ptr = range;
1373	return err;
1374}
1375
1376static int damon_sysfs_access_pattern_add_dirs(
1377		struct damon_sysfs_access_pattern *access_pattern)
1378{
1379	int err;
1380
1381	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1382			&access_pattern->sz, "sz");
1383	if (err)
1384		goto put_sz_out;
1385
1386	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1387			&access_pattern->nr_accesses, "nr_accesses");
1388	if (err)
1389		goto put_nr_accesses_sz_out;
1390
1391	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1392			&access_pattern->age, "age");
1393	if (err)
1394		goto put_age_nr_accesses_sz_out;
1395	return 0;
1396
1397put_age_nr_accesses_sz_out:
1398	kobject_put(&access_pattern->age->kobj);
1399	access_pattern->age = NULL;
1400put_nr_accesses_sz_out:
1401	kobject_put(&access_pattern->nr_accesses->kobj);
1402	access_pattern->nr_accesses = NULL;
1403put_sz_out:
1404	kobject_put(&access_pattern->sz->kobj);
1405	access_pattern->sz = NULL;
1406	return err;
1407}
1408
1409static void damon_sysfs_access_pattern_rm_dirs(
1410		struct damon_sysfs_access_pattern *access_pattern)
1411{
1412	kobject_put(&access_pattern->sz->kobj);
1413	kobject_put(&access_pattern->nr_accesses->kobj);
1414	kobject_put(&access_pattern->age->kobj);
1415}
1416
1417static void damon_sysfs_access_pattern_release(struct kobject *kobj)
1418{
1419	kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
1420}
1421
1422static struct attribute *damon_sysfs_access_pattern_attrs[] = {
1423	NULL,
1424};
1425ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
1426
1427static const struct kobj_type damon_sysfs_access_pattern_ktype = {
1428	.release = damon_sysfs_access_pattern_release,
1429	.sysfs_ops = &kobj_sysfs_ops,
1430	.default_groups = damon_sysfs_access_pattern_groups,
1431};
1432
1433/*
1434 * scheme directory
1435 */
1436
1437struct damon_sysfs_scheme {
1438	struct kobject kobj;
1439	enum damos_action action;
1440	struct damon_sysfs_access_pattern *access_pattern;
1441	unsigned long apply_interval_us;
1442	struct damon_sysfs_quotas *quotas;
1443	struct damon_sysfs_watermarks *watermarks;
1444	struct damon_sysfs_scheme_filters *filters;
1445	struct damon_sysfs_stats *stats;
1446	struct damon_sysfs_scheme_regions *tried_regions;
1447};
1448
1449/* This should match with enum damos_action */
1450static const char * const damon_sysfs_damos_action_strs[] = {
1451	"willneed",
1452	"cold",
1453	"pageout",
1454	"hugepage",
1455	"nohugepage",
1456	"lru_prio",
1457	"lru_deprio",
1458	"stat",
1459};
1460
1461static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
1462		enum damos_action action, unsigned long apply_interval_us)
1463{
1464	struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
1465				GFP_KERNEL);
1466
1467	if (!scheme)
1468		return NULL;
1469	scheme->kobj = (struct kobject){};
1470	scheme->action = action;
1471	scheme->apply_interval_us = apply_interval_us;
1472	return scheme;
1473}
1474
1475static int damon_sysfs_scheme_set_access_pattern(
1476		struct damon_sysfs_scheme *scheme)
1477{
1478	struct damon_sysfs_access_pattern *access_pattern;
1479	int err;
1480
1481	access_pattern = damon_sysfs_access_pattern_alloc();
1482	if (!access_pattern)
1483		return -ENOMEM;
1484	err = kobject_init_and_add(&access_pattern->kobj,
1485			&damon_sysfs_access_pattern_ktype, &scheme->kobj,
1486			"access_pattern");
1487	if (err)
1488		goto out;
1489	err = damon_sysfs_access_pattern_add_dirs(access_pattern);
1490	if (err)
1491		goto out;
1492	scheme->access_pattern = access_pattern;
1493	return 0;
1494
1495out:
1496	kobject_put(&access_pattern->kobj);
1497	return err;
1498}
1499
1500static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
1501{
1502	struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
1503	int err;
1504
1505	if (!quotas)
1506		return -ENOMEM;
1507	err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
1508			&scheme->kobj, "quotas");
1509	if (err)
1510		goto out;
1511	err = damon_sysfs_quotas_add_dirs(quotas);
1512	if (err)
1513		goto out;
1514	scheme->quotas = quotas;
1515	return 0;
1516
1517out:
1518	kobject_put(&quotas->kobj);
1519	return err;
1520}
1521
1522static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
1523{
1524	struct damon_sysfs_watermarks *watermarks =
1525		damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
1526	int err;
1527
1528	if (!watermarks)
1529		return -ENOMEM;
1530	err = kobject_init_and_add(&watermarks->kobj,
1531			&damon_sysfs_watermarks_ktype, &scheme->kobj,
1532			"watermarks");
1533	if (err)
1534		kobject_put(&watermarks->kobj);
1535	else
1536		scheme->watermarks = watermarks;
1537	return err;
1538}
1539
1540static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme)
1541{
1542	struct damon_sysfs_scheme_filters *filters =
1543		damon_sysfs_scheme_filters_alloc();
1544	int err;
1545
1546	if (!filters)
1547		return -ENOMEM;
1548	err = kobject_init_and_add(&filters->kobj,
1549			&damon_sysfs_scheme_filters_ktype, &scheme->kobj,
1550			"filters");
1551	if (err)
1552		kobject_put(&filters->kobj);
1553	else
1554		scheme->filters = filters;
1555	return err;
1556}
1557
1558static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
1559{
1560	struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
1561	int err;
1562
1563	if (!stats)
1564		return -ENOMEM;
1565	err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
1566			&scheme->kobj, "stats");
1567	if (err)
1568		kobject_put(&stats->kobj);
1569	else
1570		scheme->stats = stats;
1571	return err;
1572}
1573
1574static int damon_sysfs_scheme_set_tried_regions(
1575		struct damon_sysfs_scheme *scheme)
1576{
1577	struct damon_sysfs_scheme_regions *tried_regions =
1578		damon_sysfs_scheme_regions_alloc();
1579	int err;
1580
1581	if (!tried_regions)
1582		return -ENOMEM;
1583	err = kobject_init_and_add(&tried_regions->kobj,
1584			&damon_sysfs_scheme_regions_ktype, &scheme->kobj,
1585			"tried_regions");
1586	if (err)
1587		kobject_put(&tried_regions->kobj);
1588	else
1589		scheme->tried_regions = tried_regions;
1590	return err;
1591}
1592
1593static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
1594{
1595	int err;
1596
1597	err = damon_sysfs_scheme_set_access_pattern(scheme);
1598	if (err)
1599		return err;
1600	err = damon_sysfs_scheme_set_quotas(scheme);
1601	if (err)
1602		goto put_access_pattern_out;
1603	err = damon_sysfs_scheme_set_watermarks(scheme);
1604	if (err)
1605		goto put_quotas_access_pattern_out;
1606	err = damon_sysfs_scheme_set_filters(scheme);
1607	if (err)
1608		goto put_watermarks_quotas_access_pattern_out;
1609	err = damon_sysfs_scheme_set_stats(scheme);
1610	if (err)
1611		goto put_filters_watermarks_quotas_access_pattern_out;
1612	err = damon_sysfs_scheme_set_tried_regions(scheme);
1613	if (err)
1614		goto put_tried_regions_out;
1615	return 0;
1616
1617put_tried_regions_out:
1618	kobject_put(&scheme->tried_regions->kobj);
1619	scheme->tried_regions = NULL;
1620put_filters_watermarks_quotas_access_pattern_out:
1621	kobject_put(&scheme->filters->kobj);
1622	scheme->filters = NULL;
1623put_watermarks_quotas_access_pattern_out:
1624	kobject_put(&scheme->watermarks->kobj);
1625	scheme->watermarks = NULL;
1626put_quotas_access_pattern_out:
1627	kobject_put(&scheme->quotas->kobj);
1628	scheme->quotas = NULL;
1629put_access_pattern_out:
1630	kobject_put(&scheme->access_pattern->kobj);
1631	scheme->access_pattern = NULL;
1632	return err;
1633}
1634
1635static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
1636{
1637	damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
1638	kobject_put(&scheme->access_pattern->kobj);
1639	damon_sysfs_quotas_rm_dirs(scheme->quotas);
1640	kobject_put(&scheme->quotas->kobj);
1641	kobject_put(&scheme->watermarks->kobj);
1642	damon_sysfs_scheme_filters_rm_dirs(scheme->filters);
1643	kobject_put(&scheme->filters->kobj);
1644	kobject_put(&scheme->stats->kobj);
1645	damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
1646	kobject_put(&scheme->tried_regions->kobj);
1647}
1648
1649static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
1650		char *buf)
1651{
1652	struct damon_sysfs_scheme *scheme = container_of(kobj,
1653			struct damon_sysfs_scheme, kobj);
1654
1655	return sysfs_emit(buf, "%s\n",
1656			damon_sysfs_damos_action_strs[scheme->action]);
1657}
1658
1659static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
1660		const char *buf, size_t count)
1661{
1662	struct damon_sysfs_scheme *scheme = container_of(kobj,
1663			struct damon_sysfs_scheme, kobj);
1664	enum damos_action action;
1665
1666	for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
1667		if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
1668			scheme->action = action;
1669			return count;
1670		}
1671	}
1672	return -EINVAL;
1673}
1674
1675static ssize_t apply_interval_us_show(struct kobject *kobj,
1676		struct kobj_attribute *attr, char *buf)
1677{
1678	struct damon_sysfs_scheme *scheme = container_of(kobj,
1679			struct damon_sysfs_scheme, kobj);
1680
1681	return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us);
1682}
1683
1684static ssize_t apply_interval_us_store(struct kobject *kobj,
1685		struct kobj_attribute *attr, const char *buf, size_t count)
1686{
1687	struct damon_sysfs_scheme *scheme = container_of(kobj,
1688			struct damon_sysfs_scheme, kobj);
1689	int err = kstrtoul(buf, 0, &scheme->apply_interval_us);
1690
1691	return err ? err : count;
1692}
1693
1694static void damon_sysfs_scheme_release(struct kobject *kobj)
1695{
1696	kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
1697}
1698
1699static struct kobj_attribute damon_sysfs_scheme_action_attr =
1700		__ATTR_RW_MODE(action, 0600);
1701
1702static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr =
1703		__ATTR_RW_MODE(apply_interval_us, 0600);
1704
1705static struct attribute *damon_sysfs_scheme_attrs[] = {
1706	&damon_sysfs_scheme_action_attr.attr,
1707	&damon_sysfs_scheme_apply_interval_us_attr.attr,
1708	NULL,
1709};
1710ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1711
1712static const struct kobj_type damon_sysfs_scheme_ktype = {
1713	.release = damon_sysfs_scheme_release,
1714	.sysfs_ops = &kobj_sysfs_ops,
1715	.default_groups = damon_sysfs_scheme_groups,
1716};
1717
1718/*
1719 * schemes directory
1720 */
1721
1722struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1723{
1724	return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1725}
1726
1727void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1728{
1729	struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1730	int i;
1731
1732	for (i = 0; i < schemes->nr; i++) {
1733		damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1734		kobject_put(&schemes_arr[i]->kobj);
1735	}
1736	schemes->nr = 0;
1737	kfree(schemes_arr);
1738	schemes->schemes_arr = NULL;
1739}
1740
1741static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1742		int nr_schemes)
1743{
1744	struct damon_sysfs_scheme **schemes_arr, *scheme;
1745	int err, i;
1746
1747	damon_sysfs_schemes_rm_dirs(schemes);
1748	if (!nr_schemes)
1749		return 0;
1750
1751	schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1752			GFP_KERNEL | __GFP_NOWARN);
1753	if (!schemes_arr)
1754		return -ENOMEM;
1755	schemes->schemes_arr = schemes_arr;
1756
1757	for (i = 0; i < nr_schemes; i++) {
1758		/*
1759		 * apply_interval_us as 0 means same to aggregation interval
1760		 * (same to before-apply_interval behavior)
1761		 */
1762		scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0);
1763		if (!scheme) {
1764			damon_sysfs_schemes_rm_dirs(schemes);
1765			return -ENOMEM;
1766		}
1767
1768		err = kobject_init_and_add(&scheme->kobj,
1769				&damon_sysfs_scheme_ktype, &schemes->kobj,
1770				"%d", i);
1771		if (err)
1772			goto out;
1773		err = damon_sysfs_scheme_add_dirs(scheme);
1774		if (err)
1775			goto out;
1776
1777		schemes_arr[i] = scheme;
1778		schemes->nr++;
1779	}
1780	return 0;
1781
1782out:
1783	damon_sysfs_schemes_rm_dirs(schemes);
1784	kobject_put(&scheme->kobj);
1785	return err;
1786}
1787
1788static ssize_t nr_schemes_show(struct kobject *kobj,
1789		struct kobj_attribute *attr, char *buf)
1790{
1791	struct damon_sysfs_schemes *schemes = container_of(kobj,
1792			struct damon_sysfs_schemes, kobj);
1793
1794	return sysfs_emit(buf, "%d\n", schemes->nr);
1795}
1796
1797static ssize_t nr_schemes_store(struct kobject *kobj,
1798		struct kobj_attribute *attr, const char *buf, size_t count)
1799{
1800	struct damon_sysfs_schemes *schemes;
1801	int nr, err = kstrtoint(buf, 0, &nr);
1802
1803	if (err)
1804		return err;
1805	if (nr < 0)
1806		return -EINVAL;
1807
1808	schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1809
1810	if (!mutex_trylock(&damon_sysfs_lock))
1811		return -EBUSY;
1812	err = damon_sysfs_schemes_add_dirs(schemes, nr);
1813	mutex_unlock(&damon_sysfs_lock);
1814	if (err)
1815		return err;
1816	return count;
1817}
1818
1819static void damon_sysfs_schemes_release(struct kobject *kobj)
1820{
1821	kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1822}
1823
1824static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1825		__ATTR_RW_MODE(nr_schemes, 0600);
1826
1827static struct attribute *damon_sysfs_schemes_attrs[] = {
1828	&damon_sysfs_schemes_nr_attr.attr,
1829	NULL,
1830};
1831ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1832
1833const struct kobj_type damon_sysfs_schemes_ktype = {
1834	.release = damon_sysfs_schemes_release,
1835	.sysfs_ops = &kobj_sysfs_ops,
1836	.default_groups = damon_sysfs_schemes_groups,
1837};
1838
1839static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg,
1840		char *memcg_path_buf, char *path)
1841{
1842#ifdef CONFIG_MEMCG
1843	cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX);
1844	if (sysfs_streq(memcg_path_buf, path))
1845		return true;
1846#endif /* CONFIG_MEMCG */
1847	return false;
1848}
1849
1850static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id)
1851{
1852	struct mem_cgroup *memcg;
1853	char *path;
1854	bool found = false;
1855
1856	if (!memcg_path)
1857		return -EINVAL;
1858
1859	path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL);
1860	if (!path)
1861		return -ENOMEM;
1862
1863	for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg;
1864			memcg = mem_cgroup_iter(NULL, memcg, NULL)) {
1865		/* skip removed memcg */
1866		if (!mem_cgroup_id(memcg))
1867			continue;
1868		if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
1869			*id = mem_cgroup_id(memcg);
1870			found = true;
1871			break;
1872		}
1873	}
1874
1875	kfree(path);
1876	return found ? 0 : -EINVAL;
1877}
1878
1879static int damon_sysfs_set_scheme_filters(struct damos *scheme,
1880		struct damon_sysfs_scheme_filters *sysfs_filters)
1881{
1882	int i;
1883	struct damos_filter *filter, *next;
1884
1885	damos_for_each_filter_safe(filter, next, scheme)
1886		damos_destroy_filter(filter);
1887
1888	for (i = 0; i < sysfs_filters->nr; i++) {
1889		struct damon_sysfs_scheme_filter *sysfs_filter =
1890			sysfs_filters->filters_arr[i];
1891		struct damos_filter *filter =
1892			damos_new_filter(sysfs_filter->type,
1893					sysfs_filter->matching);
1894		int err;
1895
1896		if (!filter)
1897			return -ENOMEM;
1898		if (filter->type == DAMOS_FILTER_TYPE_MEMCG) {
1899			err = damon_sysfs_memcg_path_to_id(
1900					sysfs_filter->memcg_path,
1901					&filter->memcg_id);
1902			if (err) {
1903				damos_destroy_filter(filter);
1904				return err;
1905			}
1906		} else if (filter->type == DAMOS_FILTER_TYPE_ADDR) {
1907			if (sysfs_filter->addr_range.end <
1908					sysfs_filter->addr_range.start) {
1909				damos_destroy_filter(filter);
1910				return -EINVAL;
1911			}
1912			filter->addr_range = sysfs_filter->addr_range;
1913		} else if (filter->type == DAMOS_FILTER_TYPE_TARGET) {
1914			filter->target_idx = sysfs_filter->target_idx;
1915		}
1916
1917		damos_add_filter(scheme, filter);
1918	}
1919	return 0;
1920}
1921
1922static int damos_sysfs_set_quota_score(
1923		struct damos_sysfs_quota_goals *sysfs_goals,
1924		struct damos_quota *quota)
1925{
1926	struct damos_quota_goal *goal, *next;
1927	int i;
1928
1929	damos_for_each_quota_goal_safe(goal, next, quota)
1930		damos_destroy_quota_goal(goal);
1931
1932	for (i = 0; i < sysfs_goals->nr; i++) {
1933		struct damos_sysfs_quota_goal *sysfs_goal =
1934			sysfs_goals->goals_arr[i];
1935
1936		if (!sysfs_goal->target_value)
1937			continue;
1938
1939		goal = damos_new_quota_goal(sysfs_goal->metric,
1940				sysfs_goal->target_value);
1941		if (!goal)
1942			return -ENOMEM;
1943		if (sysfs_goal->metric == DAMOS_QUOTA_USER_INPUT)
1944			goal->current_value = sysfs_goal->current_value;
1945		damos_add_quota_goal(quota, goal);
1946	}
1947	return 0;
1948}
1949
1950int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes,
1951		struct damon_ctx *ctx)
1952{
1953	struct damos *scheme;
1954	int i = 0;
1955
1956	damon_for_each_scheme(scheme, ctx) {
1957		struct damon_sysfs_scheme *sysfs_scheme;
1958		int err;
1959
1960		/* user could have removed the scheme sysfs dir */
1961		if (i >= sysfs_schemes->nr)
1962			break;
1963
1964		sysfs_scheme = sysfs_schemes->schemes_arr[i];
1965		err = damos_sysfs_set_quota_score(sysfs_scheme->quotas->goals,
1966				&scheme->quota);
1967		if (err)
1968			/* kdamond will clean up schemes and terminated */
1969			return err;
1970		i++;
1971	}
1972	return 0;
1973}
1974
1975void damos_sysfs_update_effective_quotas(
1976		struct damon_sysfs_schemes *sysfs_schemes,
1977		struct damon_ctx *ctx)
1978{
1979	struct damos *scheme;
1980	int schemes_idx = 0;
1981
1982	damon_for_each_scheme(scheme, ctx) {
1983		struct damon_sysfs_quotas *sysfs_quotas;
1984
1985		/* user could have removed the scheme sysfs dir */
1986		if (schemes_idx >= sysfs_schemes->nr)
1987			break;
1988
1989		sysfs_quotas =
1990			sysfs_schemes->schemes_arr[schemes_idx++]->quotas;
1991		sysfs_quotas->effective_sz = scheme->quota.esz;
1992	}
1993}
1994
1995static struct damos *damon_sysfs_mk_scheme(
1996		struct damon_sysfs_scheme *sysfs_scheme)
1997{
1998	struct damon_sysfs_access_pattern *access_pattern =
1999		sysfs_scheme->access_pattern;
2000	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
2001	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
2002	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
2003	struct damon_sysfs_scheme_filters *sysfs_filters =
2004		sysfs_scheme->filters;
2005	struct damos *scheme;
2006	int err;
2007
2008	struct damos_access_pattern pattern = {
2009		.min_sz_region = access_pattern->sz->min,
2010		.max_sz_region = access_pattern->sz->max,
2011		.min_nr_accesses = access_pattern->nr_accesses->min,
2012		.max_nr_accesses = access_pattern->nr_accesses->max,
2013		.min_age_region = access_pattern->age->min,
2014		.max_age_region = access_pattern->age->max,
2015	};
2016	struct damos_quota quota = {
2017		.ms = sysfs_quotas->ms,
2018		.sz = sysfs_quotas->sz,
2019		.reset_interval = sysfs_quotas->reset_interval_ms,
2020		.weight_sz = sysfs_weights->sz,
2021		.weight_nr_accesses = sysfs_weights->nr_accesses,
2022		.weight_age = sysfs_weights->age,
2023	};
2024	struct damos_watermarks wmarks = {
2025		.metric = sysfs_wmarks->metric,
2026		.interval = sysfs_wmarks->interval_us,
2027		.high = sysfs_wmarks->high,
2028		.mid = sysfs_wmarks->mid,
2029		.low = sysfs_wmarks->low,
2030	};
2031
2032	scheme = damon_new_scheme(&pattern, sysfs_scheme->action,
2033			sysfs_scheme->apply_interval_us, &quota, &wmarks);
2034	if (!scheme)
2035		return NULL;
2036
2037	err = damos_sysfs_set_quota_score(sysfs_quotas->goals, &scheme->quota);
2038	if (err) {
2039		damon_destroy_scheme(scheme);
2040		return NULL;
2041	}
2042
2043	err = damon_sysfs_set_scheme_filters(scheme, sysfs_filters);
2044	if (err) {
2045		damon_destroy_scheme(scheme);
2046		return NULL;
2047	}
2048	return scheme;
2049}
2050
2051static void damon_sysfs_update_scheme(struct damos *scheme,
2052		struct damon_sysfs_scheme *sysfs_scheme)
2053{
2054	struct damon_sysfs_access_pattern *access_pattern =
2055		sysfs_scheme->access_pattern;
2056	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
2057	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
2058	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
2059	int err;
2060
2061	scheme->pattern.min_sz_region = access_pattern->sz->min;
2062	scheme->pattern.max_sz_region = access_pattern->sz->max;
2063	scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min;
2064	scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max;
2065	scheme->pattern.min_age_region = access_pattern->age->min;
2066	scheme->pattern.max_age_region = access_pattern->age->max;
2067
2068	scheme->action = sysfs_scheme->action;
2069	scheme->apply_interval_us = sysfs_scheme->apply_interval_us;
2070
2071	scheme->quota.ms = sysfs_quotas->ms;
2072	scheme->quota.sz = sysfs_quotas->sz;
2073	scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms;
2074	scheme->quota.weight_sz = sysfs_weights->sz;
2075	scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses;
2076	scheme->quota.weight_age = sysfs_weights->age;
2077
2078	err = damos_sysfs_set_quota_score(sysfs_quotas->goals, &scheme->quota);
2079	if (err) {
2080		damon_destroy_scheme(scheme);
2081		return;
2082	}
2083
2084	scheme->wmarks.metric = sysfs_wmarks->metric;
2085	scheme->wmarks.interval = sysfs_wmarks->interval_us;
2086	scheme->wmarks.high = sysfs_wmarks->high;
2087	scheme->wmarks.mid = sysfs_wmarks->mid;
2088	scheme->wmarks.low = sysfs_wmarks->low;
2089
2090	err = damon_sysfs_set_scheme_filters(scheme, sysfs_scheme->filters);
2091	if (err)
2092		damon_destroy_scheme(scheme);
2093}
2094
2095int damon_sysfs_set_schemes(struct damon_ctx *ctx,
2096		struct damon_sysfs_schemes *sysfs_schemes)
2097{
2098	struct damos *scheme, *next;
2099	int i = 0;
2100
2101	damon_for_each_scheme_safe(scheme, next, ctx) {
2102		if (i < sysfs_schemes->nr)
2103			damon_sysfs_update_scheme(scheme,
2104					sysfs_schemes->schemes_arr[i]);
2105		else
2106			damon_destroy_scheme(scheme);
2107		i++;
2108	}
2109
2110	for (; i < sysfs_schemes->nr; i++) {
2111		struct damos *scheme, *next;
2112
2113		scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
2114		if (!scheme) {
2115			damon_for_each_scheme_safe(scheme, next, ctx)
2116				damon_destroy_scheme(scheme);
2117			return -ENOMEM;
2118		}
2119		damon_add_scheme(ctx, scheme);
2120	}
2121	return 0;
2122}
2123
2124void damon_sysfs_schemes_update_stats(
2125		struct damon_sysfs_schemes *sysfs_schemes,
2126		struct damon_ctx *ctx)
2127{
2128	struct damos *scheme;
2129	int schemes_idx = 0;
2130
2131	damon_for_each_scheme(scheme, ctx) {
2132		struct damon_sysfs_stats *sysfs_stats;
2133
2134		/* user could have removed the scheme sysfs dir */
2135		if (schemes_idx >= sysfs_schemes->nr)
2136			break;
2137
2138		sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
2139		sysfs_stats->nr_tried = scheme->stat.nr_tried;
2140		sysfs_stats->sz_tried = scheme->stat.sz_tried;
2141		sysfs_stats->nr_applied = scheme->stat.nr_applied;
2142		sysfs_stats->sz_applied = scheme->stat.sz_applied;
2143		sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
2144	}
2145}
2146
2147/*
2148 * damon_sysfs_schemes that need to update its schemes regions dir.  Protected
2149 * by damon_sysfs_lock
2150 */
2151static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback;
2152static int damon_sysfs_schemes_region_idx;
2153static bool damos_regions_upd_total_bytes_only;
2154
2155/*
2156 * DAMON callback that called before damos apply.  While this callback is
2157 * registered, damon_sysfs_lock should be held to ensure the regions
2158 * directories exist.
2159 */
2160static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx,
2161		struct damon_target *t, struct damon_region *r,
2162		struct damos *s)
2163{
2164	struct damos *scheme;
2165	struct damon_sysfs_scheme_regions *sysfs_regions;
2166	struct damon_sysfs_scheme_region *region;
2167	struct damon_sysfs_schemes *sysfs_schemes =
2168		damon_sysfs_schemes_for_damos_callback;
2169	int schemes_idx = 0;
2170
2171	damon_for_each_scheme(scheme, ctx) {
2172		if (scheme == s)
2173			break;
2174		schemes_idx++;
2175	}
2176
2177	/* user could have removed the scheme sysfs dir */
2178	if (schemes_idx >= sysfs_schemes->nr)
2179		return 0;
2180
2181	sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
2182	if (sysfs_regions->upd_status == DAMOS_TRIED_REGIONS_UPD_FINISHED)
2183		return 0;
2184	if (sysfs_regions->upd_status == DAMOS_TRIED_REGIONS_UPD_IDLE)
2185		sysfs_regions->upd_status = DAMOS_TRIED_REGIONS_UPD_STARTED;
2186	sysfs_regions->total_bytes += r->ar.end - r->ar.start;
2187	if (damos_regions_upd_total_bytes_only)
2188		return 0;
2189
2190	region = damon_sysfs_scheme_region_alloc(r);
2191	if (!region)
2192		return 0;
2193	list_add_tail(&region->list, &sysfs_regions->regions_list);
2194	sysfs_regions->nr_regions++;
2195	if (kobject_init_and_add(&region->kobj,
2196				&damon_sysfs_scheme_region_ktype,
2197				&sysfs_regions->kobj, "%d",
2198				damon_sysfs_schemes_region_idx++)) {
2199		kobject_put(&region->kobj);
2200	}
2201	return 0;
2202}
2203
2204/*
2205 * DAMON callback that called after each accesses sampling.  While this
2206 * callback is registered, damon_sysfs_lock should be held to ensure the
2207 * regions directories exist.
2208 */
2209void damos_sysfs_mark_finished_regions_updates(struct damon_ctx *ctx)
2210{
2211	struct damon_sysfs_schemes *sysfs_schemes =
2212		damon_sysfs_schemes_for_damos_callback;
2213	struct damon_sysfs_scheme_regions *sysfs_regions;
2214	int i;
2215
2216	for (i = 0; i < sysfs_schemes->nr; i++) {
2217		sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions;
2218		if (sysfs_regions->upd_status ==
2219				DAMOS_TRIED_REGIONS_UPD_STARTED ||
2220				time_after(jiffies,
2221					sysfs_regions->upd_timeout_jiffies))
2222			sysfs_regions->upd_status =
2223				DAMOS_TRIED_REGIONS_UPD_FINISHED;
2224	}
2225}
2226
2227/* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
2228int damon_sysfs_schemes_clear_regions(
2229		struct damon_sysfs_schemes *sysfs_schemes,
2230		struct damon_ctx *ctx)
2231{
2232	struct damos *scheme;
2233	int schemes_idx = 0;
2234
2235	damon_for_each_scheme(scheme, ctx) {
2236		struct damon_sysfs_scheme *sysfs_scheme;
2237
2238		/* user could have removed the scheme sysfs dir */
2239		if (schemes_idx >= sysfs_schemes->nr)
2240			break;
2241
2242		sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++];
2243		damon_sysfs_scheme_regions_rm_dirs(
2244				sysfs_scheme->tried_regions);
2245		sysfs_scheme->tried_regions->total_bytes = 0;
2246	}
2247	return 0;
2248}
2249
2250static struct damos *damos_sysfs_nth_scheme(int n, struct damon_ctx *ctx)
2251{
2252	struct damos *scheme;
2253	int i = 0;
2254
2255	damon_for_each_scheme(scheme, ctx) {
2256		if (i == n)
2257			return scheme;
2258		i++;
2259	}
2260	return NULL;
2261}
2262
2263static void damos_tried_regions_init_upd_status(
2264		struct damon_sysfs_schemes *sysfs_schemes,
2265		struct damon_ctx *ctx)
2266{
2267	int i;
2268	struct damos *scheme;
2269	struct damon_sysfs_scheme_regions *sysfs_regions;
2270
2271	for (i = 0; i < sysfs_schemes->nr; i++) {
2272		sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions;
2273		scheme = damos_sysfs_nth_scheme(i, ctx);
2274		if (!scheme) {
2275			sysfs_regions->upd_status =
2276				DAMOS_TRIED_REGIONS_UPD_FINISHED;
2277			continue;
2278		}
2279		sysfs_regions->upd_status = DAMOS_TRIED_REGIONS_UPD_IDLE;
2280		sysfs_regions->upd_timeout_jiffies = jiffies +
2281			2 * usecs_to_jiffies(scheme->apply_interval_us ?
2282					scheme->apply_interval_us :
2283					ctx->attrs.aggr_interval);
2284	}
2285}
2286
2287/* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
2288int damon_sysfs_schemes_update_regions_start(
2289		struct damon_sysfs_schemes *sysfs_schemes,
2290		struct damon_ctx *ctx, bool total_bytes_only)
2291{
2292	damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
2293	damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
2294	damos_tried_regions_init_upd_status(sysfs_schemes, ctx);
2295	damos_regions_upd_total_bytes_only = total_bytes_only;
2296	ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
2297	return 0;
2298}
2299
2300bool damos_sysfs_regions_upd_done(void)
2301{
2302	struct damon_sysfs_schemes *sysfs_schemes =
2303		damon_sysfs_schemes_for_damos_callback;
2304	struct damon_sysfs_scheme_regions *sysfs_regions;
2305	int i;
2306
2307	for (i = 0; i < sysfs_schemes->nr; i++) {
2308		sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions;
2309		if (sysfs_regions->upd_status !=
2310				DAMOS_TRIED_REGIONS_UPD_FINISHED)
2311			return false;
2312	}
2313	return true;
2314}
2315
2316/*
2317 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock.  Caller
2318 * should unlock damon_sysfs_lock which held before
2319 * damon_sysfs_schemes_update_regions_start()
2320 */
2321int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx)
2322{
2323	damon_sysfs_schemes_for_damos_callback = NULL;
2324	ctx->callback.before_damos_apply = NULL;
2325	damon_sysfs_schemes_region_idx = 0;
2326	return 0;
2327}