Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
   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;
  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 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
 116struct damon_sysfs_scheme_regions {
 117	struct kobject kobj;
 118	struct list_head regions_list;
 119	int nr_regions;
 120};
 121
 122static struct damon_sysfs_scheme_regions *
 123damon_sysfs_scheme_regions_alloc(void)
 124{
 125	struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
 126			GFP_KERNEL);
 127
 128	regions->kobj = (struct kobject){};
 129	INIT_LIST_HEAD(&regions->regions_list);
 130	regions->nr_regions = 0;
 131	return regions;
 132}
 133
 134static void damon_sysfs_scheme_regions_rm_dirs(
 135		struct damon_sysfs_scheme_regions *regions)
 136{
 137	struct damon_sysfs_scheme_region *r, *next;
 138
 139	list_for_each_entry_safe(r, next, &regions->regions_list, list) {
 140		/* release function deletes it from the list */
 141		kobject_put(&r->kobj);
 142		regions->nr_regions--;
 143	}
 144}
 145
 146static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
 147{
 148	kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
 149}
 150
 151static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
 152	NULL,
 153};
 154ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
 155
 156static struct kobj_type damon_sysfs_scheme_regions_ktype = {
 157	.release = damon_sysfs_scheme_regions_release,
 158	.sysfs_ops = &kobj_sysfs_ops,
 159	.default_groups = damon_sysfs_scheme_regions_groups,
 160};
 161
 162/*
 163 * schemes/stats directory
 164 */
 165
 166struct damon_sysfs_stats {
 167	struct kobject kobj;
 168	unsigned long nr_tried;
 169	unsigned long sz_tried;
 170	unsigned long nr_applied;
 171	unsigned long sz_applied;
 172	unsigned long qt_exceeds;
 173};
 174
 175static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
 176{
 177	return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
 178}
 179
 180static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
 181		char *buf)
 182{
 183	struct damon_sysfs_stats *stats = container_of(kobj,
 184			struct damon_sysfs_stats, kobj);
 185
 186	return sysfs_emit(buf, "%lu\n", stats->nr_tried);
 187}
 188
 189static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
 190		char *buf)
 191{
 192	struct damon_sysfs_stats *stats = container_of(kobj,
 193			struct damon_sysfs_stats, kobj);
 194
 195	return sysfs_emit(buf, "%lu\n", stats->sz_tried);
 196}
 197
 198static ssize_t nr_applied_show(struct kobject *kobj,
 199		struct kobj_attribute *attr, char *buf)
 200{
 201	struct damon_sysfs_stats *stats = container_of(kobj,
 202			struct damon_sysfs_stats, kobj);
 203
 204	return sysfs_emit(buf, "%lu\n", stats->nr_applied);
 205}
 206
 207static ssize_t sz_applied_show(struct kobject *kobj,
 208		struct kobj_attribute *attr, char *buf)
 209{
 210	struct damon_sysfs_stats *stats = container_of(kobj,
 211			struct damon_sysfs_stats, kobj);
 212
 213	return sysfs_emit(buf, "%lu\n", stats->sz_applied);
 214}
 215
 216static ssize_t qt_exceeds_show(struct kobject *kobj,
 217		struct kobj_attribute *attr, char *buf)
 218{
 219	struct damon_sysfs_stats *stats = container_of(kobj,
 220			struct damon_sysfs_stats, kobj);
 221
 222	return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
 223}
 224
 225static void damon_sysfs_stats_release(struct kobject *kobj)
 226{
 227	kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
 228}
 229
 230static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
 231		__ATTR_RO_MODE(nr_tried, 0400);
 232
 233static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
 234		__ATTR_RO_MODE(sz_tried, 0400);
 235
 236static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
 237		__ATTR_RO_MODE(nr_applied, 0400);
 238
 239static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
 240		__ATTR_RO_MODE(sz_applied, 0400);
 241
 242static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
 243		__ATTR_RO_MODE(qt_exceeds, 0400);
 244
 245static struct attribute *damon_sysfs_stats_attrs[] = {
 246	&damon_sysfs_stats_nr_tried_attr.attr,
 247	&damon_sysfs_stats_sz_tried_attr.attr,
 248	&damon_sysfs_stats_nr_applied_attr.attr,
 249	&damon_sysfs_stats_sz_applied_attr.attr,
 250	&damon_sysfs_stats_qt_exceeds_attr.attr,
 251	NULL,
 252};
 253ATTRIBUTE_GROUPS(damon_sysfs_stats);
 254
 255static struct kobj_type damon_sysfs_stats_ktype = {
 256	.release = damon_sysfs_stats_release,
 257	.sysfs_ops = &kobj_sysfs_ops,
 258	.default_groups = damon_sysfs_stats_groups,
 259};
 260
 261/*
 262 * watermarks directory
 263 */
 264
 265struct damon_sysfs_watermarks {
 266	struct kobject kobj;
 267	enum damos_wmark_metric metric;
 268	unsigned long interval_us;
 269	unsigned long high;
 270	unsigned long mid;
 271	unsigned long low;
 272};
 273
 274static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
 275		enum damos_wmark_metric metric, unsigned long interval_us,
 276		unsigned long high, unsigned long mid, unsigned long low)
 277{
 278	struct damon_sysfs_watermarks *watermarks = kmalloc(
 279			sizeof(*watermarks), GFP_KERNEL);
 280
 281	if (!watermarks)
 282		return NULL;
 283	watermarks->kobj = (struct kobject){};
 284	watermarks->metric = metric;
 285	watermarks->interval_us = interval_us;
 286	watermarks->high = high;
 287	watermarks->mid = mid;
 288	watermarks->low = low;
 289	return watermarks;
 290}
 291
 292/* Should match with enum damos_wmark_metric */
 293static const char * const damon_sysfs_wmark_metric_strs[] = {
 294	"none",
 295	"free_mem_rate",
 296};
 297
 298static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
 299		char *buf)
 300{
 301	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 302			struct damon_sysfs_watermarks, kobj);
 303
 304	return sysfs_emit(buf, "%s\n",
 305			damon_sysfs_wmark_metric_strs[watermarks->metric]);
 306}
 307
 308static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
 309		const char *buf, size_t count)
 310{
 311	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 312			struct damon_sysfs_watermarks, kobj);
 313	enum damos_wmark_metric metric;
 314
 315	for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
 316		if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
 317			watermarks->metric = metric;
 318			return count;
 319		}
 320	}
 321	return -EINVAL;
 322}
 323
 324static ssize_t interval_us_show(struct kobject *kobj,
 325		struct kobj_attribute *attr, char *buf)
 326{
 327	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 328			struct damon_sysfs_watermarks, kobj);
 329
 330	return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
 331}
 332
 333static ssize_t interval_us_store(struct kobject *kobj,
 334		struct kobj_attribute *attr, const char *buf, size_t count)
 335{
 336	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 337			struct damon_sysfs_watermarks, kobj);
 338	int err = kstrtoul(buf, 0, &watermarks->interval_us);
 339
 340	return err ? err : count;
 341}
 342
 343static ssize_t high_show(struct kobject *kobj,
 344		struct kobj_attribute *attr, char *buf)
 345{
 346	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 347			struct damon_sysfs_watermarks, kobj);
 348
 349	return sysfs_emit(buf, "%lu\n", watermarks->high);
 350}
 351
 352static ssize_t high_store(struct kobject *kobj,
 353		struct kobj_attribute *attr, const char *buf, size_t count)
 354{
 355	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 356			struct damon_sysfs_watermarks, kobj);
 357	int err = kstrtoul(buf, 0, &watermarks->high);
 358
 359	return err ? err : count;
 360}
 361
 362static ssize_t mid_show(struct kobject *kobj,
 363		struct kobj_attribute *attr, char *buf)
 364{
 365	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 366			struct damon_sysfs_watermarks, kobj);
 367
 368	return sysfs_emit(buf, "%lu\n", watermarks->mid);
 369}
 370
 371static ssize_t mid_store(struct kobject *kobj,
 372		struct kobj_attribute *attr, const char *buf, size_t count)
 373{
 374	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 375			struct damon_sysfs_watermarks, kobj);
 376	int err = kstrtoul(buf, 0, &watermarks->mid);
 377
 378	return err ? err : count;
 379}
 380
 381static ssize_t low_show(struct kobject *kobj,
 382		struct kobj_attribute *attr, char *buf)
 383{
 384	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 385			struct damon_sysfs_watermarks, kobj);
 386
 387	return sysfs_emit(buf, "%lu\n", watermarks->low);
 388}
 389
 390static ssize_t low_store(struct kobject *kobj,
 391		struct kobj_attribute *attr, const char *buf, size_t count)
 392{
 393	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 394			struct damon_sysfs_watermarks, kobj);
 395	int err = kstrtoul(buf, 0, &watermarks->low);
 396
 397	return err ? err : count;
 398}
 399
 400static void damon_sysfs_watermarks_release(struct kobject *kobj)
 401{
 402	kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
 403}
 404
 405static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
 406		__ATTR_RW_MODE(metric, 0600);
 407
 408static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
 409		__ATTR_RW_MODE(interval_us, 0600);
 410
 411static struct kobj_attribute damon_sysfs_watermarks_high_attr =
 412		__ATTR_RW_MODE(high, 0600);
 413
 414static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
 415		__ATTR_RW_MODE(mid, 0600);
 416
 417static struct kobj_attribute damon_sysfs_watermarks_low_attr =
 418		__ATTR_RW_MODE(low, 0600);
 419
 420static struct attribute *damon_sysfs_watermarks_attrs[] = {
 421	&damon_sysfs_watermarks_metric_attr.attr,
 422	&damon_sysfs_watermarks_interval_us_attr.attr,
 423	&damon_sysfs_watermarks_high_attr.attr,
 424	&damon_sysfs_watermarks_mid_attr.attr,
 425	&damon_sysfs_watermarks_low_attr.attr,
 426	NULL,
 427};
 428ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
 429
 430static struct kobj_type damon_sysfs_watermarks_ktype = {
 431	.release = damon_sysfs_watermarks_release,
 432	.sysfs_ops = &kobj_sysfs_ops,
 433	.default_groups = damon_sysfs_watermarks_groups,
 434};
 435
 436/*
 437 * scheme/weights directory
 438 */
 439
 440struct damon_sysfs_weights {
 441	struct kobject kobj;
 442	unsigned int sz;
 443	unsigned int nr_accesses;
 444	unsigned int age;
 445};
 446
 447static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
 448		unsigned int nr_accesses, unsigned int age)
 449{
 450	struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
 451			GFP_KERNEL);
 452
 453	if (!weights)
 454		return NULL;
 455	weights->kobj = (struct kobject){};
 456	weights->sz = sz;
 457	weights->nr_accesses = nr_accesses;
 458	weights->age = age;
 459	return weights;
 460}
 461
 462static ssize_t sz_permil_show(struct kobject *kobj,
 463		struct kobj_attribute *attr, char *buf)
 464{
 465	struct damon_sysfs_weights *weights = container_of(kobj,
 466			struct damon_sysfs_weights, kobj);
 467
 468	return sysfs_emit(buf, "%u\n", weights->sz);
 469}
 470
 471static ssize_t sz_permil_store(struct kobject *kobj,
 472		struct kobj_attribute *attr, const char *buf, size_t count)
 473{
 474	struct damon_sysfs_weights *weights = container_of(kobj,
 475			struct damon_sysfs_weights, kobj);
 476	int err = kstrtouint(buf, 0, &weights->sz);
 477
 478	return err ? err : count;
 479}
 480
 481static ssize_t nr_accesses_permil_show(struct kobject *kobj,
 482		struct kobj_attribute *attr, char *buf)
 483{
 484	struct damon_sysfs_weights *weights = container_of(kobj,
 485			struct damon_sysfs_weights, kobj);
 486
 487	return sysfs_emit(buf, "%u\n", weights->nr_accesses);
 488}
 489
 490static ssize_t nr_accesses_permil_store(struct kobject *kobj,
 491		struct kobj_attribute *attr, const char *buf, size_t count)
 492{
 493	struct damon_sysfs_weights *weights = container_of(kobj,
 494			struct damon_sysfs_weights, kobj);
 495	int err = kstrtouint(buf, 0, &weights->nr_accesses);
 496
 497	return err ? err : count;
 498}
 499
 500static ssize_t age_permil_show(struct kobject *kobj,
 501		struct kobj_attribute *attr, char *buf)
 502{
 503	struct damon_sysfs_weights *weights = container_of(kobj,
 504			struct damon_sysfs_weights, kobj);
 505
 506	return sysfs_emit(buf, "%u\n", weights->age);
 507}
 508
 509static ssize_t age_permil_store(struct kobject *kobj,
 510		struct kobj_attribute *attr, const char *buf, size_t count)
 511{
 512	struct damon_sysfs_weights *weights = container_of(kobj,
 513			struct damon_sysfs_weights, kobj);
 514	int err = kstrtouint(buf, 0, &weights->age);
 515
 516	return err ? err : count;
 517}
 518
 519static void damon_sysfs_weights_release(struct kobject *kobj)
 520{
 521	kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
 522}
 523
 524static struct kobj_attribute damon_sysfs_weights_sz_attr =
 525		__ATTR_RW_MODE(sz_permil, 0600);
 526
 527static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
 528		__ATTR_RW_MODE(nr_accesses_permil, 0600);
 529
 530static struct kobj_attribute damon_sysfs_weights_age_attr =
 531		__ATTR_RW_MODE(age_permil, 0600);
 532
 533static struct attribute *damon_sysfs_weights_attrs[] = {
 534	&damon_sysfs_weights_sz_attr.attr,
 535	&damon_sysfs_weights_nr_accesses_attr.attr,
 536	&damon_sysfs_weights_age_attr.attr,
 537	NULL,
 538};
 539ATTRIBUTE_GROUPS(damon_sysfs_weights);
 540
 541static struct kobj_type damon_sysfs_weights_ktype = {
 542	.release = damon_sysfs_weights_release,
 543	.sysfs_ops = &kobj_sysfs_ops,
 544	.default_groups = damon_sysfs_weights_groups,
 545};
 546
 547/*
 548 * quotas directory
 549 */
 550
 551struct damon_sysfs_quotas {
 552	struct kobject kobj;
 553	struct damon_sysfs_weights *weights;
 554	unsigned long ms;
 555	unsigned long sz;
 556	unsigned long reset_interval_ms;
 557};
 558
 559static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
 560{
 561	return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
 562}
 563
 564static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
 565{
 566	struct damon_sysfs_weights *weights;
 567	int err;
 568
 569	weights = damon_sysfs_weights_alloc(0, 0, 0);
 570	if (!weights)
 571		return -ENOMEM;
 572
 573	err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
 574			&quotas->kobj, "weights");
 575	if (err)
 576		kobject_put(&weights->kobj);
 577	else
 578		quotas->weights = weights;
 579	return err;
 580}
 581
 582static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
 583{
 584	kobject_put(&quotas->weights->kobj);
 585}
 586
 587static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
 588		char *buf)
 589{
 590	struct damon_sysfs_quotas *quotas = container_of(kobj,
 591			struct damon_sysfs_quotas, kobj);
 592
 593	return sysfs_emit(buf, "%lu\n", quotas->ms);
 594}
 595
 596static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
 597		const char *buf, size_t count)
 598{
 599	struct damon_sysfs_quotas *quotas = container_of(kobj,
 600			struct damon_sysfs_quotas, kobj);
 601	int err = kstrtoul(buf, 0, &quotas->ms);
 602
 603	if (err)
 604		return -EINVAL;
 605	return count;
 606}
 607
 608static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
 609		char *buf)
 610{
 611	struct damon_sysfs_quotas *quotas = container_of(kobj,
 612			struct damon_sysfs_quotas, kobj);
 613
 614	return sysfs_emit(buf, "%lu\n", quotas->sz);
 615}
 616
 617static ssize_t bytes_store(struct kobject *kobj,
 618		struct kobj_attribute *attr, const char *buf, size_t count)
 619{
 620	struct damon_sysfs_quotas *quotas = container_of(kobj,
 621			struct damon_sysfs_quotas, kobj);
 622	int err = kstrtoul(buf, 0, &quotas->sz);
 623
 624	if (err)
 625		return -EINVAL;
 626	return count;
 627}
 628
 629static ssize_t reset_interval_ms_show(struct kobject *kobj,
 630		struct kobj_attribute *attr, char *buf)
 631{
 632	struct damon_sysfs_quotas *quotas = container_of(kobj,
 633			struct damon_sysfs_quotas, kobj);
 634
 635	return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
 636}
 637
 638static ssize_t reset_interval_ms_store(struct kobject *kobj,
 639		struct kobj_attribute *attr, const char *buf, size_t count)
 640{
 641	struct damon_sysfs_quotas *quotas = container_of(kobj,
 642			struct damon_sysfs_quotas, kobj);
 643	int err = kstrtoul(buf, 0, &quotas->reset_interval_ms);
 644
 645	if (err)
 646		return -EINVAL;
 647	return count;
 648}
 649
 650static void damon_sysfs_quotas_release(struct kobject *kobj)
 651{
 652	kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
 653}
 654
 655static struct kobj_attribute damon_sysfs_quotas_ms_attr =
 656		__ATTR_RW_MODE(ms, 0600);
 657
 658static struct kobj_attribute damon_sysfs_quotas_sz_attr =
 659		__ATTR_RW_MODE(bytes, 0600);
 660
 661static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
 662		__ATTR_RW_MODE(reset_interval_ms, 0600);
 663
 664static struct attribute *damon_sysfs_quotas_attrs[] = {
 665	&damon_sysfs_quotas_ms_attr.attr,
 666	&damon_sysfs_quotas_sz_attr.attr,
 667	&damon_sysfs_quotas_reset_interval_ms_attr.attr,
 668	NULL,
 669};
 670ATTRIBUTE_GROUPS(damon_sysfs_quotas);
 671
 672static struct kobj_type damon_sysfs_quotas_ktype = {
 673	.release = damon_sysfs_quotas_release,
 674	.sysfs_ops = &kobj_sysfs_ops,
 675	.default_groups = damon_sysfs_quotas_groups,
 676};
 677
 678/*
 679 * access_pattern directory
 680 */
 681
 682struct damon_sysfs_access_pattern {
 683	struct kobject kobj;
 684	struct damon_sysfs_ul_range *sz;
 685	struct damon_sysfs_ul_range *nr_accesses;
 686	struct damon_sysfs_ul_range *age;
 687};
 688
 689static
 690struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
 691{
 692	struct damon_sysfs_access_pattern *access_pattern =
 693		kmalloc(sizeof(*access_pattern), GFP_KERNEL);
 694
 695	if (!access_pattern)
 696		return NULL;
 697	access_pattern->kobj = (struct kobject){};
 698	return access_pattern;
 699}
 700
 701static int damon_sysfs_access_pattern_add_range_dir(
 702		struct damon_sysfs_access_pattern *access_pattern,
 703		struct damon_sysfs_ul_range **range_dir_ptr,
 704		char *name)
 705{
 706	struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
 707	int err;
 708
 709	if (!range)
 710		return -ENOMEM;
 711	err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
 712			&access_pattern->kobj, name);
 713	if (err)
 714		kobject_put(&range->kobj);
 715	else
 716		*range_dir_ptr = range;
 717	return err;
 718}
 719
 720static int damon_sysfs_access_pattern_add_dirs(
 721		struct damon_sysfs_access_pattern *access_pattern)
 722{
 723	int err;
 724
 725	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
 726			&access_pattern->sz, "sz");
 727	if (err)
 728		goto put_sz_out;
 729
 730	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
 731			&access_pattern->nr_accesses, "nr_accesses");
 732	if (err)
 733		goto put_nr_accesses_sz_out;
 734
 735	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
 736			&access_pattern->age, "age");
 737	if (err)
 738		goto put_age_nr_accesses_sz_out;
 739	return 0;
 740
 741put_age_nr_accesses_sz_out:
 742	kobject_put(&access_pattern->age->kobj);
 743	access_pattern->age = NULL;
 744put_nr_accesses_sz_out:
 745	kobject_put(&access_pattern->nr_accesses->kobj);
 746	access_pattern->nr_accesses = NULL;
 747put_sz_out:
 748	kobject_put(&access_pattern->sz->kobj);
 749	access_pattern->sz = NULL;
 750	return err;
 751}
 752
 753static void damon_sysfs_access_pattern_rm_dirs(
 754		struct damon_sysfs_access_pattern *access_pattern)
 755{
 756	kobject_put(&access_pattern->sz->kobj);
 757	kobject_put(&access_pattern->nr_accesses->kobj);
 758	kobject_put(&access_pattern->age->kobj);
 759}
 760
 761static void damon_sysfs_access_pattern_release(struct kobject *kobj)
 762{
 763	kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
 764}
 765
 766static struct attribute *damon_sysfs_access_pattern_attrs[] = {
 767	NULL,
 768};
 769ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
 770
 771static struct kobj_type damon_sysfs_access_pattern_ktype = {
 772	.release = damon_sysfs_access_pattern_release,
 773	.sysfs_ops = &kobj_sysfs_ops,
 774	.default_groups = damon_sysfs_access_pattern_groups,
 775};
 776
 777/*
 778 * scheme directory
 779 */
 780
 781struct damon_sysfs_scheme {
 782	struct kobject kobj;
 783	enum damos_action action;
 784	struct damon_sysfs_access_pattern *access_pattern;
 785	struct damon_sysfs_quotas *quotas;
 786	struct damon_sysfs_watermarks *watermarks;
 787	struct damon_sysfs_stats *stats;
 788	struct damon_sysfs_scheme_regions *tried_regions;
 789};
 790
 791/* This should match with enum damos_action */
 792static const char * const damon_sysfs_damos_action_strs[] = {
 793	"willneed",
 794	"cold",
 795	"pageout",
 796	"hugepage",
 797	"nohugepage",
 798	"lru_prio",
 799	"lru_deprio",
 800	"stat",
 801};
 802
 803static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
 804		enum damos_action action)
 805{
 806	struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
 807				GFP_KERNEL);
 808
 809	if (!scheme)
 810		return NULL;
 811	scheme->kobj = (struct kobject){};
 812	scheme->action = action;
 813	return scheme;
 814}
 815
 816static int damon_sysfs_scheme_set_access_pattern(
 817		struct damon_sysfs_scheme *scheme)
 818{
 819	struct damon_sysfs_access_pattern *access_pattern;
 820	int err;
 821
 822	access_pattern = damon_sysfs_access_pattern_alloc();
 823	if (!access_pattern)
 824		return -ENOMEM;
 825	err = kobject_init_and_add(&access_pattern->kobj,
 826			&damon_sysfs_access_pattern_ktype, &scheme->kobj,
 827			"access_pattern");
 828	if (err)
 829		goto out;
 830	err = damon_sysfs_access_pattern_add_dirs(access_pattern);
 831	if (err)
 832		goto out;
 833	scheme->access_pattern = access_pattern;
 834	return 0;
 835
 836out:
 837	kobject_put(&access_pattern->kobj);
 838	return err;
 839}
 840
 841static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
 842{
 843	struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
 844	int err;
 845
 846	if (!quotas)
 847		return -ENOMEM;
 848	err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
 849			&scheme->kobj, "quotas");
 850	if (err)
 851		goto out;
 852	err = damon_sysfs_quotas_add_dirs(quotas);
 853	if (err)
 854		goto out;
 855	scheme->quotas = quotas;
 856	return 0;
 857
 858out:
 859	kobject_put(&quotas->kobj);
 860	return err;
 861}
 862
 863static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
 864{
 865	struct damon_sysfs_watermarks *watermarks =
 866		damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
 867	int err;
 868
 869	if (!watermarks)
 870		return -ENOMEM;
 871	err = kobject_init_and_add(&watermarks->kobj,
 872			&damon_sysfs_watermarks_ktype, &scheme->kobj,
 873			"watermarks");
 874	if (err)
 875		kobject_put(&watermarks->kobj);
 876	else
 877		scheme->watermarks = watermarks;
 878	return err;
 879}
 880
 881static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
 882{
 883	struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
 884	int err;
 885
 886	if (!stats)
 887		return -ENOMEM;
 888	err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
 889			&scheme->kobj, "stats");
 890	if (err)
 891		kobject_put(&stats->kobj);
 892	else
 893		scheme->stats = stats;
 894	return err;
 895}
 896
 897static int damon_sysfs_scheme_set_tried_regions(
 898		struct damon_sysfs_scheme *scheme)
 899{
 900	struct damon_sysfs_scheme_regions *tried_regions =
 901		damon_sysfs_scheme_regions_alloc();
 902	int err;
 903
 904	if (!tried_regions)
 905		return -ENOMEM;
 906	err = kobject_init_and_add(&tried_regions->kobj,
 907			&damon_sysfs_scheme_regions_ktype, &scheme->kobj,
 908			"tried_regions");
 909	if (err)
 910		kobject_put(&tried_regions->kobj);
 911	else
 912		scheme->tried_regions = tried_regions;
 913	return err;
 914}
 915
 916static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
 917{
 918	int err;
 919
 920	err = damon_sysfs_scheme_set_access_pattern(scheme);
 921	if (err)
 922		return err;
 923	err = damon_sysfs_scheme_set_quotas(scheme);
 924	if (err)
 925		goto put_access_pattern_out;
 926	err = damon_sysfs_scheme_set_watermarks(scheme);
 927	if (err)
 928		goto put_quotas_access_pattern_out;
 929	err = damon_sysfs_scheme_set_stats(scheme);
 930	if (err)
 931		goto put_watermarks_quotas_access_pattern_out;
 932	err = damon_sysfs_scheme_set_tried_regions(scheme);
 933	if (err)
 934		goto put_tried_regions_out;
 935	return 0;
 936
 937put_tried_regions_out:
 938	kobject_put(&scheme->tried_regions->kobj);
 939	scheme->tried_regions = NULL;
 940put_watermarks_quotas_access_pattern_out:
 941	kobject_put(&scheme->watermarks->kobj);
 942	scheme->watermarks = NULL;
 943put_quotas_access_pattern_out:
 944	kobject_put(&scheme->quotas->kobj);
 945	scheme->quotas = NULL;
 946put_access_pattern_out:
 947	kobject_put(&scheme->access_pattern->kobj);
 948	scheme->access_pattern = NULL;
 949	return err;
 950}
 951
 952static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
 953{
 954	damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
 955	kobject_put(&scheme->access_pattern->kobj);
 956	damon_sysfs_quotas_rm_dirs(scheme->quotas);
 957	kobject_put(&scheme->quotas->kobj);
 958	kobject_put(&scheme->watermarks->kobj);
 959	kobject_put(&scheme->stats->kobj);
 960	damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
 961	kobject_put(&scheme->tried_regions->kobj);
 962}
 963
 964static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
 965		char *buf)
 966{
 967	struct damon_sysfs_scheme *scheme = container_of(kobj,
 968			struct damon_sysfs_scheme, kobj);
 969
 970	return sysfs_emit(buf, "%s\n",
 971			damon_sysfs_damos_action_strs[scheme->action]);
 972}
 973
 974static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
 975		const char *buf, size_t count)
 976{
 977	struct damon_sysfs_scheme *scheme = container_of(kobj,
 978			struct damon_sysfs_scheme, kobj);
 979	enum damos_action action;
 980
 981	for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
 982		if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
 983			scheme->action = action;
 984			return count;
 985		}
 986	}
 987	return -EINVAL;
 988}
 989
 990static void damon_sysfs_scheme_release(struct kobject *kobj)
 991{
 992	kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
 993}
 994
 995static struct kobj_attribute damon_sysfs_scheme_action_attr =
 996		__ATTR_RW_MODE(action, 0600);
 997
 998static struct attribute *damon_sysfs_scheme_attrs[] = {
 999	&damon_sysfs_scheme_action_attr.attr,
1000	NULL,
1001};
1002ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1003
1004static struct kobj_type damon_sysfs_scheme_ktype = {
1005	.release = damon_sysfs_scheme_release,
1006	.sysfs_ops = &kobj_sysfs_ops,
1007	.default_groups = damon_sysfs_scheme_groups,
1008};
1009
1010/*
1011 * schemes directory
1012 */
1013
1014struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1015{
1016	return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1017}
1018
1019void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1020{
1021	struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1022	int i;
1023
1024	for (i = 0; i < schemes->nr; i++) {
1025		damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1026		kobject_put(&schemes_arr[i]->kobj);
1027	}
1028	schemes->nr = 0;
1029	kfree(schemes_arr);
1030	schemes->schemes_arr = NULL;
1031}
1032
1033static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1034		int nr_schemes)
1035{
1036	struct damon_sysfs_scheme **schemes_arr, *scheme;
1037	int err, i;
1038
1039	damon_sysfs_schemes_rm_dirs(schemes);
1040	if (!nr_schemes)
1041		return 0;
1042
1043	schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1044			GFP_KERNEL | __GFP_NOWARN);
1045	if (!schemes_arr)
1046		return -ENOMEM;
1047	schemes->schemes_arr = schemes_arr;
1048
1049	for (i = 0; i < nr_schemes; i++) {
1050		scheme = damon_sysfs_scheme_alloc(DAMOS_STAT);
1051		if (!scheme) {
1052			damon_sysfs_schemes_rm_dirs(schemes);
1053			return -ENOMEM;
1054		}
1055
1056		err = kobject_init_and_add(&scheme->kobj,
1057				&damon_sysfs_scheme_ktype, &schemes->kobj,
1058				"%d", i);
1059		if (err)
1060			goto out;
1061		err = damon_sysfs_scheme_add_dirs(scheme);
1062		if (err)
1063			goto out;
1064
1065		schemes_arr[i] = scheme;
1066		schemes->nr++;
1067	}
1068	return 0;
1069
1070out:
1071	damon_sysfs_schemes_rm_dirs(schemes);
1072	kobject_put(&scheme->kobj);
1073	return err;
1074}
1075
1076static ssize_t nr_schemes_show(struct kobject *kobj,
1077		struct kobj_attribute *attr, char *buf)
1078{
1079	struct damon_sysfs_schemes *schemes = container_of(kobj,
1080			struct damon_sysfs_schemes, kobj);
1081
1082	return sysfs_emit(buf, "%d\n", schemes->nr);
1083}
1084
1085static ssize_t nr_schemes_store(struct kobject *kobj,
1086		struct kobj_attribute *attr, const char *buf, size_t count)
1087{
1088	struct damon_sysfs_schemes *schemes;
1089	int nr, err = kstrtoint(buf, 0, &nr);
1090
1091	if (err)
1092		return err;
1093	if (nr < 0)
1094		return -EINVAL;
1095
1096	schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1097
1098	if (!mutex_trylock(&damon_sysfs_lock))
1099		return -EBUSY;
1100	err = damon_sysfs_schemes_add_dirs(schemes, nr);
1101	mutex_unlock(&damon_sysfs_lock);
1102	if (err)
1103		return err;
1104	return count;
1105}
1106
1107static void damon_sysfs_schemes_release(struct kobject *kobj)
1108{
1109	kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1110}
1111
1112static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1113		__ATTR_RW_MODE(nr_schemes, 0600);
1114
1115static struct attribute *damon_sysfs_schemes_attrs[] = {
1116	&damon_sysfs_schemes_nr_attr.attr,
1117	NULL,
1118};
1119ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1120
1121struct kobj_type damon_sysfs_schemes_ktype = {
1122	.release = damon_sysfs_schemes_release,
1123	.sysfs_ops = &kobj_sysfs_ops,
1124	.default_groups = damon_sysfs_schemes_groups,
1125};
1126
1127static struct damos *damon_sysfs_mk_scheme(
1128		struct damon_sysfs_scheme *sysfs_scheme)
1129{
1130	struct damon_sysfs_access_pattern *access_pattern =
1131		sysfs_scheme->access_pattern;
1132	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1133	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1134	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1135
1136	struct damos_access_pattern pattern = {
1137		.min_sz_region = access_pattern->sz->min,
1138		.max_sz_region = access_pattern->sz->max,
1139		.min_nr_accesses = access_pattern->nr_accesses->min,
1140		.max_nr_accesses = access_pattern->nr_accesses->max,
1141		.min_age_region = access_pattern->age->min,
1142		.max_age_region = access_pattern->age->max,
1143	};
1144	struct damos_quota quota = {
1145		.ms = sysfs_quotas->ms,
1146		.sz = sysfs_quotas->sz,
1147		.reset_interval = sysfs_quotas->reset_interval_ms,
1148		.weight_sz = sysfs_weights->sz,
1149		.weight_nr_accesses = sysfs_weights->nr_accesses,
1150		.weight_age = sysfs_weights->age,
1151	};
1152	struct damos_watermarks wmarks = {
1153		.metric = sysfs_wmarks->metric,
1154		.interval = sysfs_wmarks->interval_us,
1155		.high = sysfs_wmarks->high,
1156		.mid = sysfs_wmarks->mid,
1157		.low = sysfs_wmarks->low,
1158	};
1159
1160	return damon_new_scheme(&pattern, sysfs_scheme->action, &quota,
1161			&wmarks);
1162}
1163
1164static void damon_sysfs_update_scheme(struct damos *scheme,
1165		struct damon_sysfs_scheme *sysfs_scheme)
1166{
1167	struct damon_sysfs_access_pattern *access_pattern =
1168		sysfs_scheme->access_pattern;
1169	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1170	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1171	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1172
1173	scheme->pattern.min_sz_region = access_pattern->sz->min;
1174	scheme->pattern.max_sz_region = access_pattern->sz->max;
1175	scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min;
1176	scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max;
1177	scheme->pattern.min_age_region = access_pattern->age->min;
1178	scheme->pattern.max_age_region = access_pattern->age->max;
1179
1180	scheme->action = sysfs_scheme->action;
1181
1182	scheme->quota.ms = sysfs_quotas->ms;
1183	scheme->quota.sz = sysfs_quotas->sz;
1184	scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms;
1185	scheme->quota.weight_sz = sysfs_weights->sz;
1186	scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses;
1187	scheme->quota.weight_age = sysfs_weights->age;
1188
1189	scheme->wmarks.metric = sysfs_wmarks->metric;
1190	scheme->wmarks.interval = sysfs_wmarks->interval_us;
1191	scheme->wmarks.high = sysfs_wmarks->high;
1192	scheme->wmarks.mid = sysfs_wmarks->mid;
1193	scheme->wmarks.low = sysfs_wmarks->low;
1194}
1195
1196int damon_sysfs_set_schemes(struct damon_ctx *ctx,
1197		struct damon_sysfs_schemes *sysfs_schemes)
1198{
1199	struct damos *scheme, *next;
1200	int i = 0;
1201
1202	damon_for_each_scheme_safe(scheme, next, ctx) {
1203		if (i < sysfs_schemes->nr)
1204			damon_sysfs_update_scheme(scheme,
1205					sysfs_schemes->schemes_arr[i]);
1206		else
1207			damon_destroy_scheme(scheme);
1208		i++;
1209	}
1210
1211	for (; i < sysfs_schemes->nr; i++) {
1212		struct damos *scheme, *next;
1213
1214		scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
1215		if (!scheme) {
1216			damon_for_each_scheme_safe(scheme, next, ctx)
1217				damon_destroy_scheme(scheme);
1218			return -ENOMEM;
1219		}
1220		damon_add_scheme(ctx, scheme);
1221	}
1222	return 0;
1223}
1224
1225void damon_sysfs_schemes_update_stats(
1226		struct damon_sysfs_schemes *sysfs_schemes,
1227		struct damon_ctx *ctx)
1228{
1229	struct damos *scheme;
1230	int schemes_idx = 0;
1231
1232	damon_for_each_scheme(scheme, ctx) {
1233		struct damon_sysfs_stats *sysfs_stats;
1234
1235		/* user could have removed the scheme sysfs dir */
1236		if (schemes_idx >= sysfs_schemes->nr)
1237			break;
1238
1239		sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
1240		sysfs_stats->nr_tried = scheme->stat.nr_tried;
1241		sysfs_stats->sz_tried = scheme->stat.sz_tried;
1242		sysfs_stats->nr_applied = scheme->stat.nr_applied;
1243		sysfs_stats->sz_applied = scheme->stat.sz_applied;
1244		sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
1245	}
1246}
1247
1248/*
1249 * damon_sysfs_schemes that need to update its schemes regions dir.  Protected
1250 * by damon_sysfs_lock
1251 */
1252static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback;
1253static int damon_sysfs_schemes_region_idx;
1254
1255/*
1256 * DAMON callback that called before damos apply.  While this callback is
1257 * registered, damon_sysfs_lock should be held to ensure the regions
1258 * directories exist.
1259 */
1260static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx,
1261		struct damon_target *t, struct damon_region *r,
1262		struct damos *s)
1263{
1264	struct damos *scheme;
1265	struct damon_sysfs_scheme_regions *sysfs_regions;
1266	struct damon_sysfs_scheme_region *region;
1267	struct damon_sysfs_schemes *sysfs_schemes =
1268		damon_sysfs_schemes_for_damos_callback;
1269	int schemes_idx = 0;
1270
1271	damon_for_each_scheme(scheme, ctx) {
1272		if (scheme == s)
1273			break;
1274		schemes_idx++;
1275	}
1276
1277	/* user could have removed the scheme sysfs dir */
1278	if (schemes_idx >= sysfs_schemes->nr)
1279		return 0;
1280
1281	sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
1282	region = damon_sysfs_scheme_region_alloc(r);
1283	list_add_tail(&region->list, &sysfs_regions->regions_list);
1284	sysfs_regions->nr_regions++;
1285	if (kobject_init_and_add(&region->kobj,
1286				&damon_sysfs_scheme_region_ktype,
1287				&sysfs_regions->kobj, "%d",
1288				damon_sysfs_schemes_region_idx++)) {
1289		kobject_put(&region->kobj);
1290	}
1291	return 0;
1292}
1293
1294/* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1295int damon_sysfs_schemes_clear_regions(
1296		struct damon_sysfs_schemes *sysfs_schemes,
1297		struct damon_ctx *ctx)
1298{
1299	struct damos *scheme;
1300	int schemes_idx = 0;
1301
1302	damon_for_each_scheme(scheme, ctx) {
1303		struct damon_sysfs_scheme *sysfs_scheme;
1304
1305		/* user could have removed the scheme sysfs dir */
1306		if (schemes_idx >= sysfs_schemes->nr)
1307			break;
1308
1309		sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++];
1310		damon_sysfs_scheme_regions_rm_dirs(
1311				sysfs_scheme->tried_regions);
1312	}
1313	return 0;
1314}
1315
1316/* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1317int damon_sysfs_schemes_update_regions_start(
1318		struct damon_sysfs_schemes *sysfs_schemes,
1319		struct damon_ctx *ctx)
1320{
1321	damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
1322	damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
1323	ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
1324	return 0;
1325}
1326
1327/*
1328 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock.  Caller
1329 * should unlock damon_sysfs_lock which held before
1330 * damon_sysfs_schemes_update_regions_start()
1331 */
1332int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx)
1333{
1334	damon_sysfs_schemes_for_damos_callback = NULL;
1335	ctx->callback.before_damos_apply = NULL;
1336	damon_sysfs_schemes_region_idx = 0;
1337	return 0;
1338}