File Index
Files and directories
Sign in
FILE

sysfs-schemes.c

File preview with syntax highlighting.

linux-6.19.14/mm/damon/sysfs-schemes.c C
   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#include <linux/numa.h>
  10
  11#include "sysfs-common.h"
  12
  13/*
  14 * scheme region directory
  15 */
  16
  17struct damon_sysfs_scheme_region {
  18	struct kobject kobj;
  19	struct damon_addr_range ar;
  20	unsigned int nr_accesses;
  21	unsigned int age;
  22	unsigned long sz_filter_passed;
  23	struct list_head list;
  24};
  25
  26static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc(
  27		struct damon_region *region)
  28{
  29	struct damon_sysfs_scheme_region *sysfs_region = kmalloc(
  30			sizeof(*sysfs_region), GFP_KERNEL);
  31
  32	if (!sysfs_region)
  33		return NULL;
  34	sysfs_region->kobj = (struct kobject){};
  35	sysfs_region->ar = region->ar;
  36	sysfs_region->nr_accesses = region->nr_accesses_bp / 10000;
  37	sysfs_region->age = region->age;
  38	INIT_LIST_HEAD(&sysfs_region->list);
  39	return sysfs_region;
  40}
  41
  42static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr,
  43		char *buf)
  44{
  45	struct damon_sysfs_scheme_region *region = container_of(kobj,
  46			struct damon_sysfs_scheme_region, kobj);
  47
  48	return sysfs_emit(buf, "%lu\n", region->ar.start);
  49}
  50
  51static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr,
  52		char *buf)
  53{
  54	struct damon_sysfs_scheme_region *region = container_of(kobj,
  55			struct damon_sysfs_scheme_region, kobj);
  56
  57	return sysfs_emit(buf, "%lu\n", region->ar.end);
  58}
  59
  60static ssize_t nr_accesses_show(struct kobject *kobj,
  61		struct kobj_attribute *attr, char *buf)
  62{
  63	struct damon_sysfs_scheme_region *region = container_of(kobj,
  64			struct damon_sysfs_scheme_region, kobj);
  65
  66	return sysfs_emit(buf, "%u\n", region->nr_accesses);
  67}
  68
  69static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr,
  70		char *buf)
  71{
  72	struct damon_sysfs_scheme_region *region = container_of(kobj,
  73			struct damon_sysfs_scheme_region, kobj);
  74
  75	return sysfs_emit(buf, "%u\n", region->age);
  76}
  77
  78static ssize_t sz_filter_passed_show(struct kobject *kobj,
  79		struct kobj_attribute *attr, char *buf)
  80{
  81	struct damon_sysfs_scheme_region *region = container_of(kobj,
  82			struct damon_sysfs_scheme_region, kobj);
  83
  84	return sysfs_emit(buf, "%lu\n", region->sz_filter_passed);
  85}
  86
  87static void damon_sysfs_scheme_region_release(struct kobject *kobj)
  88{
  89	struct damon_sysfs_scheme_region *region = container_of(kobj,
  90			struct damon_sysfs_scheme_region, kobj);
  91
  92	list_del(&region->list);
  93	kfree(region);
  94}
  95
  96static struct kobj_attribute damon_sysfs_scheme_region_start_attr =
  97		__ATTR_RO_MODE(start, 0400);
  98
  99static struct kobj_attribute damon_sysfs_scheme_region_end_attr =
 100		__ATTR_RO_MODE(end, 0400);
 101
 102static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr =
 103		__ATTR_RO_MODE(nr_accesses, 0400);
 104
 105static struct kobj_attribute damon_sysfs_scheme_region_age_attr =
 106		__ATTR_RO_MODE(age, 0400);
 107
 108static struct kobj_attribute damon_sysfs_scheme_region_sz_filter_passed_attr =
 109		__ATTR_RO_MODE(sz_filter_passed, 0400);
 110
 111static struct attribute *damon_sysfs_scheme_region_attrs[] = {
 112	&damon_sysfs_scheme_region_start_attr.attr,
 113	&damon_sysfs_scheme_region_end_attr.attr,
 114	&damon_sysfs_scheme_region_nr_accesses_attr.attr,
 115	&damon_sysfs_scheme_region_age_attr.attr,
 116	&damon_sysfs_scheme_region_sz_filter_passed_attr.attr,
 117	NULL,
 118};
 119ATTRIBUTE_GROUPS(damon_sysfs_scheme_region);
 120
 121static const struct kobj_type damon_sysfs_scheme_region_ktype = {
 122	.release = damon_sysfs_scheme_region_release,
 123	.sysfs_ops = &kobj_sysfs_ops,
 124	.default_groups = damon_sysfs_scheme_region_groups,
 125};
 126
 127/*
 128 * scheme regions directory
 129 */
 130
 131struct damon_sysfs_scheme_regions {
 132	struct kobject kobj;
 133	struct list_head regions_list;
 134	int nr_regions;
 135	unsigned long total_bytes;
 136};
 137
 138static struct damon_sysfs_scheme_regions *
 139damon_sysfs_scheme_regions_alloc(void)
 140{
 141	struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
 142			GFP_KERNEL);
 143
 144	if (!regions)
 145		return NULL;
 146
 147	regions->kobj = (struct kobject){};
 148	INIT_LIST_HEAD(&regions->regions_list);
 149	regions->nr_regions = 0;
 150	regions->total_bytes = 0;
 151	return regions;
 152}
 153
 154static ssize_t total_bytes_show(struct kobject *kobj,
 155		struct kobj_attribute *attr, char *buf)
 156{
 157	struct damon_sysfs_scheme_regions *regions = container_of(kobj,
 158			struct damon_sysfs_scheme_regions, kobj);
 159
 160	return sysfs_emit(buf, "%lu\n", regions->total_bytes);
 161}
 162
 163static void damon_sysfs_scheme_regions_rm_dirs(
 164		struct damon_sysfs_scheme_regions *regions)
 165{
 166	struct damon_sysfs_scheme_region *r, *next;
 167
 168	list_for_each_entry_safe(r, next, &regions->regions_list, list) {
 169		/* release function deletes it from the list */
 170		kobject_put(&r->kobj);
 171		regions->nr_regions--;
 172	}
 173}
 174
 175static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
 176{
 177	kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
 178}
 179
 180static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr =
 181		__ATTR_RO_MODE(total_bytes, 0400);
 182
 183static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
 184	&damon_sysfs_scheme_regions_total_bytes_attr.attr,
 185	NULL,
 186};
 187ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
 188
 189static const struct kobj_type damon_sysfs_scheme_regions_ktype = {
 190	.release = damon_sysfs_scheme_regions_release,
 191	.sysfs_ops = &kobj_sysfs_ops,
 192	.default_groups = damon_sysfs_scheme_regions_groups,
 193};
 194
 195/*
 196 * schemes/stats directory
 197 */
 198
 199struct damon_sysfs_stats {
 200	struct kobject kobj;
 201	unsigned long nr_tried;
 202	unsigned long sz_tried;
 203	unsigned long nr_applied;
 204	unsigned long sz_applied;
 205	unsigned long sz_ops_filter_passed;
 206	unsigned long qt_exceeds;
 207};
 208
 209static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
 210{
 211	return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
 212}
 213
 214static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
 215		char *buf)
 216{
 217	struct damon_sysfs_stats *stats = container_of(kobj,
 218			struct damon_sysfs_stats, kobj);
 219
 220	return sysfs_emit(buf, "%lu\n", stats->nr_tried);
 221}
 222
 223static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
 224		char *buf)
 225{
 226	struct damon_sysfs_stats *stats = container_of(kobj,
 227			struct damon_sysfs_stats, kobj);
 228
 229	return sysfs_emit(buf, "%lu\n", stats->sz_tried);
 230}
 231
 232static ssize_t nr_applied_show(struct kobject *kobj,
 233		struct kobj_attribute *attr, char *buf)
 234{
 235	struct damon_sysfs_stats *stats = container_of(kobj,
 236			struct damon_sysfs_stats, kobj);
 237
 238	return sysfs_emit(buf, "%lu\n", stats->nr_applied);
 239}
 240
 241static ssize_t sz_applied_show(struct kobject *kobj,
 242		struct kobj_attribute *attr, char *buf)
 243{
 244	struct damon_sysfs_stats *stats = container_of(kobj,
 245			struct damon_sysfs_stats, kobj);
 246
 247	return sysfs_emit(buf, "%lu\n", stats->sz_applied);
 248}
 249
 250static ssize_t sz_ops_filter_passed_show(struct kobject *kobj,
 251		struct kobj_attribute *attr, char *buf)
 252{
 253	struct damon_sysfs_stats *stats = container_of(kobj,
 254			struct damon_sysfs_stats, kobj);
 255
 256	return sysfs_emit(buf, "%lu\n", stats->sz_ops_filter_passed);
 257}
 258
 259static ssize_t qt_exceeds_show(struct kobject *kobj,
 260		struct kobj_attribute *attr, char *buf)
 261{
 262	struct damon_sysfs_stats *stats = container_of(kobj,
 263			struct damon_sysfs_stats, kobj);
 264
 265	return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
 266}
 267
 268static void damon_sysfs_stats_release(struct kobject *kobj)
 269{
 270	kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
 271}
 272
 273static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
 274		__ATTR_RO_MODE(nr_tried, 0400);
 275
 276static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
 277		__ATTR_RO_MODE(sz_tried, 0400);
 278
 279static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
 280		__ATTR_RO_MODE(nr_applied, 0400);
 281
 282static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
 283		__ATTR_RO_MODE(sz_applied, 0400);
 284
 285static struct kobj_attribute damon_sysfs_stats_sz_ops_filter_passed_attr =
 286		__ATTR_RO_MODE(sz_ops_filter_passed, 0400);
 287
 288static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
 289		__ATTR_RO_MODE(qt_exceeds, 0400);
 290
 291static struct attribute *damon_sysfs_stats_attrs[] = {
 292	&damon_sysfs_stats_nr_tried_attr.attr,
 293	&damon_sysfs_stats_sz_tried_attr.attr,
 294	&damon_sysfs_stats_nr_applied_attr.attr,
 295	&damon_sysfs_stats_sz_applied_attr.attr,
 296	&damon_sysfs_stats_sz_ops_filter_passed_attr.attr,
 297	&damon_sysfs_stats_qt_exceeds_attr.attr,
 298	NULL,
 299};
 300ATTRIBUTE_GROUPS(damon_sysfs_stats);
 301
 302static const struct kobj_type damon_sysfs_stats_ktype = {
 303	.release = damon_sysfs_stats_release,
 304	.sysfs_ops = &kobj_sysfs_ops,
 305	.default_groups = damon_sysfs_stats_groups,
 306};
 307
 308/*
 309 * filter directory
 310 */
 311
 312/*
 313 * enum damos_sysfs_filter_handle_layer - Layers handling filters of a dir.
 314 */
 315enum damos_sysfs_filter_handle_layer {
 316	DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE,
 317	DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS,
 318	DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH,
 319};
 320
 321struct damon_sysfs_scheme_filter {
 322	struct kobject kobj;
 323	enum damos_sysfs_filter_handle_layer handle_layer;
 324	enum damos_filter_type type;
 325	bool matching;
 326	bool allow;
 327	char *memcg_path;
 328	struct damon_addr_range addr_range;
 329	struct damon_size_range sz_range;
 330	int target_idx;
 331};
 332
 333static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(
 334		enum damos_sysfs_filter_handle_layer layer)
 335{
 336	struct damon_sysfs_scheme_filter *filter;
 337
 338	filter = kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL);
 339	if (filter)
 340		filter->handle_layer = layer;
 341	return filter;
 342}
 343
 344struct damos_sysfs_filter_type_name {
 345	enum damos_filter_type type;
 346	char *name;
 347};
 348
 349static const struct damos_sysfs_filter_type_name
 350damos_sysfs_filter_type_names[] = {
 351	{
 352		.type = DAMOS_FILTER_TYPE_ANON,
 353		.name = "anon",
 354	},
 355	{
 356		.type = DAMOS_FILTER_TYPE_ACTIVE,
 357		.name = "active",
 358	},
 359	{
 360		.type = DAMOS_FILTER_TYPE_MEMCG,
 361		.name = "memcg",
 362	},
 363	{
 364		.type = DAMOS_FILTER_TYPE_YOUNG,
 365		.name = "young",
 366	},
 367	{
 368		.type = DAMOS_FILTER_TYPE_HUGEPAGE_SIZE,
 369		.name = "hugepage_size",
 370	},
 371	{
 372		.type = DAMOS_FILTER_TYPE_UNMAPPED,
 373		.name = "unmapped",
 374	},
 375	{
 376		.type = DAMOS_FILTER_TYPE_ADDR,
 377		.name = "addr",
 378	},
 379	{
 380		.type = DAMOS_FILTER_TYPE_TARGET,
 381		.name = "target",
 382	},
 383};
 384
 385static ssize_t type_show(struct kobject *kobj,
 386		struct kobj_attribute *attr, char *buf)
 387{
 388	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 389			struct damon_sysfs_scheme_filter, kobj);
 390	int i;
 391
 392	for (i = 0; i < ARRAY_SIZE(damos_sysfs_filter_type_names); i++) {
 393		const struct damos_sysfs_filter_type_name *type_name;
 394
 395		type_name = &damos_sysfs_filter_type_names[i];
 396		if (type_name->type == filter->type)
 397			return sysfs_emit(buf, "%s\n", type_name->name);
 398	}
 399	return -EINVAL;
 400}
 401
 402static bool damos_sysfs_scheme_filter_valid_type(
 403		enum damos_sysfs_filter_handle_layer layer,
 404		enum damos_filter_type type)
 405{
 406	switch (layer) {
 407	case DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH:
 408		return true;
 409	case DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE:
 410		return !damos_filter_for_ops(type);
 411	case DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS:
 412		return damos_filter_for_ops(type);
 413	default:
 414		break;
 415	}
 416	return false;
 417}
 418
 419static ssize_t type_store(struct kobject *kobj,
 420		struct kobj_attribute *attr, const char *buf, size_t count)
 421{
 422	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 423			struct damon_sysfs_scheme_filter, kobj);
 424	ssize_t ret = -EINVAL;
 425	int i;
 426
 427	for (i = 0; i < ARRAY_SIZE(damos_sysfs_filter_type_names); i++) {
 428		const struct damos_sysfs_filter_type_name *type_name;
 429
 430		type_name = &damos_sysfs_filter_type_names[i];
 431		if (sysfs_streq(buf, type_name->name)) {
 432			if (!damos_sysfs_scheme_filter_valid_type(
 433						filter->handle_layer,
 434						type_name->type))
 435				break;
 436			filter->type = type_name->type;
 437			ret = count;
 438			break;
 439		}
 440	}
 441	return ret;
 442}
 443
 444static ssize_t matching_show(struct kobject *kobj,
 445		struct kobj_attribute *attr, char *buf)
 446{
 447	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 448			struct damon_sysfs_scheme_filter, kobj);
 449
 450	return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
 451}
 452
 453static ssize_t matching_store(struct kobject *kobj,
 454		struct kobj_attribute *attr, const char *buf, size_t count)
 455{
 456	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 457			struct damon_sysfs_scheme_filter, kobj);
 458	bool matching;
 459	int err = kstrtobool(buf, &matching);
 460
 461	if (err)
 462		return err;
 463
 464	filter->matching = matching;
 465	return count;
 466}
 467
 468static ssize_t allow_show(struct kobject *kobj,
 469		struct kobj_attribute *attr, char *buf)
 470{
 471	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 472			struct damon_sysfs_scheme_filter, kobj);
 473
 474	return sysfs_emit(buf, "%c\n", filter->allow ? 'Y' : 'N');
 475}
 476
 477static ssize_t allow_store(struct kobject *kobj,
 478		struct kobj_attribute *attr, const char *buf, size_t count)
 479{
 480	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 481			struct damon_sysfs_scheme_filter, kobj);
 482	bool allow;
 483	int err = kstrtobool(buf, &allow);
 484
 485	if (err)
 486		return err;
 487
 488	filter->allow = allow;
 489	return count;
 490}
 491
 492static ssize_t memcg_path_show(struct kobject *kobj,
 493		struct kobj_attribute *attr, char *buf)
 494{
 495	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 496			struct damon_sysfs_scheme_filter, kobj);
 497
 498	return sysfs_emit(buf, "%s\n",
 499			filter->memcg_path ? filter->memcg_path : "");
 500}
 501
 502static ssize_t memcg_path_store(struct kobject *kobj,
 503		struct kobj_attribute *attr, const char *buf, size_t count)
 504{
 505	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 506			struct damon_sysfs_scheme_filter, kobj);
 507	char *path = kmalloc_array(size_add(count, 1), sizeof(*path),
 508				   GFP_KERNEL);
 509
 510	if (!path)
 511		return -ENOMEM;
 512
 513	strscpy(path, buf, count + 1);
 514	kfree(filter->memcg_path);
 515	filter->memcg_path = path;
 516	return count;
 517}
 518
 519static ssize_t addr_start_show(struct kobject *kobj,
 520		struct kobj_attribute *attr, char *buf)
 521{
 522	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 523			struct damon_sysfs_scheme_filter, kobj);
 524
 525	return sysfs_emit(buf, "%lu\n", filter->addr_range.start);
 526}
 527
 528static ssize_t addr_start_store(struct kobject *kobj,
 529		struct kobj_attribute *attr, const char *buf, size_t count)
 530{
 531	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 532			struct damon_sysfs_scheme_filter, kobj);
 533	int err = kstrtoul(buf, 0, &filter->addr_range.start);
 534
 535	return err ? err : count;
 536}
 537
 538static ssize_t addr_end_show(struct kobject *kobj,
 539		struct kobj_attribute *attr, char *buf)
 540{
 541	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 542			struct damon_sysfs_scheme_filter, kobj);
 543
 544	return sysfs_emit(buf, "%lu\n", filter->addr_range.end);
 545}
 546
 547static ssize_t addr_end_store(struct kobject *kobj,
 548		struct kobj_attribute *attr, const char *buf, size_t count)
 549{
 550	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 551			struct damon_sysfs_scheme_filter, kobj);
 552	int err = kstrtoul(buf, 0, &filter->addr_range.end);
 553
 554	return err ? err : count;
 555}
 556
 557static ssize_t min_show(struct kobject *kobj,
 558		struct kobj_attribute *attr, char *buf)
 559{
 560	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 561			struct damon_sysfs_scheme_filter, kobj);
 562
 563	return sysfs_emit(buf, "%lu\n", filter->sz_range.min);
 564}
 565
 566static ssize_t min_store(struct kobject *kobj,
 567		struct kobj_attribute *attr, const char *buf, size_t count)
 568{
 569	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 570			struct damon_sysfs_scheme_filter, kobj);
 571	int err = kstrtoul(buf, 0, &filter->sz_range.min);
 572
 573	return err ? err : count;
 574}
 575
 576static ssize_t max_show(struct kobject *kobj,
 577		struct kobj_attribute *attr, char *buf)
 578{
 579	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 580			struct damon_sysfs_scheme_filter, kobj);
 581
 582	return sysfs_emit(buf, "%lu\n", filter->sz_range.max);
 583}
 584
 585static ssize_t max_store(struct kobject *kobj,
 586		struct kobj_attribute *attr, const char *buf, size_t count)
 587{
 588	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 589			struct damon_sysfs_scheme_filter, kobj);
 590	int err = kstrtoul(buf, 0, &filter->sz_range.max);
 591
 592	return err ? err : count;
 593}
 594
 595static ssize_t damon_target_idx_show(struct kobject *kobj,
 596		struct kobj_attribute *attr, char *buf)
 597{
 598	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 599			struct damon_sysfs_scheme_filter, kobj);
 600
 601	return sysfs_emit(buf, "%d\n", filter->target_idx);
 602}
 603
 604static ssize_t damon_target_idx_store(struct kobject *kobj,
 605		struct kobj_attribute *attr, const char *buf, size_t count)
 606{
 607	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 608			struct damon_sysfs_scheme_filter, kobj);
 609	int err = kstrtoint(buf, 0, &filter->target_idx);
 610
 611	return err ? err : count;
 612}
 613
 614static void damon_sysfs_scheme_filter_release(struct kobject *kobj)
 615{
 616	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
 617			struct damon_sysfs_scheme_filter, kobj);
 618
 619	kfree(filter->memcg_path);
 620	kfree(filter);
 621}
 622
 623static struct kobj_attribute damon_sysfs_scheme_filter_type_attr =
 624		__ATTR_RW_MODE(type, 0600);
 625
 626static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr =
 627		__ATTR_RW_MODE(matching, 0600);
 628
 629static struct kobj_attribute damon_sysfs_scheme_filter_allow_attr =
 630		__ATTR_RW_MODE(allow, 0600);
 631
 632static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr =
 633		__ATTR_RW_MODE(memcg_path, 0600);
 634
 635static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr =
 636		__ATTR_RW_MODE(addr_start, 0600);
 637
 638static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr =
 639		__ATTR_RW_MODE(addr_end, 0600);
 640
 641static struct kobj_attribute damon_sysfs_scheme_filter_min_attr =
 642		__ATTR_RW_MODE(min, 0600);
 643
 644static struct kobj_attribute damon_sysfs_scheme_filter_max_attr =
 645		__ATTR_RW_MODE(max, 0600);
 646
 647static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr =
 648		__ATTR_RW_MODE(damon_target_idx, 0600);
 649
 650static struct attribute *damon_sysfs_scheme_filter_attrs[] = {
 651	&damon_sysfs_scheme_filter_type_attr.attr,
 652	&damon_sysfs_scheme_filter_matching_attr.attr,
 653	&damon_sysfs_scheme_filter_allow_attr.attr,
 654	&damon_sysfs_scheme_filter_memcg_path_attr.attr,
 655	&damon_sysfs_scheme_filter_addr_start_attr.attr,
 656	&damon_sysfs_scheme_filter_addr_end_attr.attr,
 657	&damon_sysfs_scheme_filter_min_attr.attr,
 658	&damon_sysfs_scheme_filter_max_attr.attr,
 659	&damon_sysfs_scheme_filter_damon_target_idx_attr.attr,
 660	NULL,
 661};
 662ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter);
 663
 664static const struct kobj_type damon_sysfs_scheme_filter_ktype = {
 665	.release = damon_sysfs_scheme_filter_release,
 666	.sysfs_ops = &kobj_sysfs_ops,
 667	.default_groups = damon_sysfs_scheme_filter_groups,
 668};
 669
 670/*
 671 * filters directory
 672 */
 673
 674struct damon_sysfs_scheme_filters {
 675	struct kobject kobj;
 676	enum damos_sysfs_filter_handle_layer handle_layer;
 677	struct damon_sysfs_scheme_filter **filters_arr;
 678	int nr;
 679};
 680
 681static struct damon_sysfs_scheme_filters *
 682damon_sysfs_scheme_filters_alloc(enum damos_sysfs_filter_handle_layer layer)
 683{
 684	struct damon_sysfs_scheme_filters *filters;
 685
 686	filters = kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL);
 687	if (filters)
 688		filters->handle_layer = layer;
 689	return filters;
 690}
 691
 692static void damon_sysfs_scheme_filters_rm_dirs(
 693		struct damon_sysfs_scheme_filters *filters)
 694{
 695	struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr;
 696	int i;
 697
 698	for (i = 0; i < filters->nr; i++)
 699		kobject_put(&filters_arr[i]->kobj);
 700	filters->nr = 0;
 701	kfree(filters_arr);
 702	filters->filters_arr = NULL;
 703}
 704
 705static int damon_sysfs_scheme_filters_add_dirs(
 706		struct damon_sysfs_scheme_filters *filters, int nr_filters)
 707{
 708	struct damon_sysfs_scheme_filter **filters_arr, *filter;
 709	int err, i;
 710
 711	damon_sysfs_scheme_filters_rm_dirs(filters);
 712	if (!nr_filters)
 713		return 0;
 714
 715	filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
 716			GFP_KERNEL | __GFP_NOWARN);
 717	if (!filters_arr)
 718		return -ENOMEM;
 719	filters->filters_arr = filters_arr;
 720
 721	for (i = 0; i < nr_filters; i++) {
 722		filter = damon_sysfs_scheme_filter_alloc(
 723				filters->handle_layer);
 724		if (!filter) {
 725			damon_sysfs_scheme_filters_rm_dirs(filters);
 726			return -ENOMEM;
 727		}
 728
 729		err = kobject_init_and_add(&filter->kobj,
 730				&damon_sysfs_scheme_filter_ktype,
 731				&filters->kobj, "%d", i);
 732		if (err) {
 733			kobject_put(&filter->kobj);
 734			damon_sysfs_scheme_filters_rm_dirs(filters);
 735			return err;
 736		}
 737
 738		filters_arr[i] = filter;
 739		filters->nr++;
 740	}
 741	return 0;
 742}
 743
 744static ssize_t nr_filters_show(struct kobject *kobj,
 745		struct kobj_attribute *attr, char *buf)
 746{
 747	struct damon_sysfs_scheme_filters *filters = container_of(kobj,
 748			struct damon_sysfs_scheme_filters, kobj);
 749
 750	return sysfs_emit(buf, "%d\n", filters->nr);
 751}
 752
 753static ssize_t nr_filters_store(struct kobject *kobj,
 754		struct kobj_attribute *attr, const char *buf, size_t count)
 755{
 756	struct damon_sysfs_scheme_filters *filters;
 757	int nr, err = kstrtoint(buf, 0, &nr);
 758
 759	if (err)
 760		return err;
 761	if (nr < 0)
 762		return -EINVAL;
 763
 764	filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj);
 765
 766	if (!mutex_trylock(&damon_sysfs_lock))
 767		return -EBUSY;
 768	err = damon_sysfs_scheme_filters_add_dirs(filters, nr);
 769	mutex_unlock(&damon_sysfs_lock);
 770	if (err)
 771		return err;
 772
 773	return count;
 774}
 775
 776static void damon_sysfs_scheme_filters_release(struct kobject *kobj)
 777{
 778	kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj));
 779}
 780
 781static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr =
 782		__ATTR_RW_MODE(nr_filters, 0600);
 783
 784static struct attribute *damon_sysfs_scheme_filters_attrs[] = {
 785	&damon_sysfs_scheme_filters_nr_attr.attr,
 786	NULL,
 787};
 788ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters);
 789
 790static const struct kobj_type damon_sysfs_scheme_filters_ktype = {
 791	.release = damon_sysfs_scheme_filters_release,
 792	.sysfs_ops = &kobj_sysfs_ops,
 793	.default_groups = damon_sysfs_scheme_filters_groups,
 794};
 795
 796/*
 797 * watermarks directory
 798 */
 799
 800struct damon_sysfs_watermarks {
 801	struct kobject kobj;
 802	enum damos_wmark_metric metric;
 803	unsigned long interval_us;
 804	unsigned long high;
 805	unsigned long mid;
 806	unsigned long low;
 807};
 808
 809static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
 810		enum damos_wmark_metric metric, unsigned long interval_us,
 811		unsigned long high, unsigned long mid, unsigned long low)
 812{
 813	struct damon_sysfs_watermarks *watermarks = kmalloc(
 814			sizeof(*watermarks), GFP_KERNEL);
 815
 816	if (!watermarks)
 817		return NULL;
 818	watermarks->kobj = (struct kobject){};
 819	watermarks->metric = metric;
 820	watermarks->interval_us = interval_us;
 821	watermarks->high = high;
 822	watermarks->mid = mid;
 823	watermarks->low = low;
 824	return watermarks;
 825}
 826
 827struct damos_sysfs_wmark_metric_name {
 828	enum damos_wmark_metric metric;
 829	char *name;
 830};
 831
 832static const struct damos_sysfs_wmark_metric_name
 833damos_sysfs_wmark_metric_names[] = {
 834	{
 835		.metric = DAMOS_WMARK_NONE,
 836		.name = "none",
 837	},
 838	{
 839		.metric = DAMOS_WMARK_FREE_MEM_RATE,
 840		.name = "free_mem_rate",
 841	},
 842};
 843
 844static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
 845		char *buf)
 846{
 847	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 848			struct damon_sysfs_watermarks, kobj);
 849	int i;
 850
 851	for (i = 0; i < ARRAY_SIZE(damos_sysfs_wmark_metric_names); i++) {
 852		const struct damos_sysfs_wmark_metric_name *metric_name;
 853
 854		metric_name = &damos_sysfs_wmark_metric_names[i];
 855		if (metric_name->metric == watermarks->metric)
 856			return sysfs_emit(buf, "%s\n", metric_name->name);
 857	}
 858	return -EINVAL;
 859}
 860
 861static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
 862		const char *buf, size_t count)
 863{
 864	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 865			struct damon_sysfs_watermarks, kobj);
 866	int i;
 867
 868	for (i = 0; i < ARRAY_SIZE(damos_sysfs_wmark_metric_names); i++) {
 869		const struct damos_sysfs_wmark_metric_name *metric_name;
 870
 871		metric_name = &damos_sysfs_wmark_metric_names[i];
 872		if (sysfs_streq(buf, metric_name->name)) {
 873			watermarks->metric = metric_name->metric;
 874			return count;
 875		}
 876	}
 877	return -EINVAL;
 878}
 879
 880static ssize_t interval_us_show(struct kobject *kobj,
 881		struct kobj_attribute *attr, char *buf)
 882{
 883	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 884			struct damon_sysfs_watermarks, kobj);
 885
 886	return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
 887}
 888
 889static ssize_t interval_us_store(struct kobject *kobj,
 890		struct kobj_attribute *attr, const char *buf, size_t count)
 891{
 892	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 893			struct damon_sysfs_watermarks, kobj);
 894	int err = kstrtoul(buf, 0, &watermarks->interval_us);
 895
 896	return err ? err : count;
 897}
 898
 899static ssize_t high_show(struct kobject *kobj,
 900		struct kobj_attribute *attr, char *buf)
 901{
 902	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 903			struct damon_sysfs_watermarks, kobj);
 904
 905	return sysfs_emit(buf, "%lu\n", watermarks->high);
 906}
 907
 908static ssize_t high_store(struct kobject *kobj,
 909		struct kobj_attribute *attr, const char *buf, size_t count)
 910{
 911	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 912			struct damon_sysfs_watermarks, kobj);
 913	int err = kstrtoul(buf, 0, &watermarks->high);
 914
 915	return err ? err : count;
 916}
 917
 918static ssize_t mid_show(struct kobject *kobj,
 919		struct kobj_attribute *attr, char *buf)
 920{
 921	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 922			struct damon_sysfs_watermarks, kobj);
 923
 924	return sysfs_emit(buf, "%lu\n", watermarks->mid);
 925}
 926
 927static ssize_t mid_store(struct kobject *kobj,
 928		struct kobj_attribute *attr, const char *buf, size_t count)
 929{
 930	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 931			struct damon_sysfs_watermarks, kobj);
 932	int err = kstrtoul(buf, 0, &watermarks->mid);
 933
 934	return err ? err : count;
 935}
 936
 937static ssize_t low_show(struct kobject *kobj,
 938		struct kobj_attribute *attr, char *buf)
 939{
 940	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 941			struct damon_sysfs_watermarks, kobj);
 942
 943	return sysfs_emit(buf, "%lu\n", watermarks->low);
 944}
 945
 946static ssize_t low_store(struct kobject *kobj,
 947		struct kobj_attribute *attr, const char *buf, size_t count)
 948{
 949	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
 950			struct damon_sysfs_watermarks, kobj);
 951	int err = kstrtoul(buf, 0, &watermarks->low);
 952
 953	return err ? err : count;
 954}
 955
 956static void damon_sysfs_watermarks_release(struct kobject *kobj)
 957{
 958	kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
 959}
 960
 961static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
 962		__ATTR_RW_MODE(metric, 0600);
 963
 964static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
 965		__ATTR_RW_MODE(interval_us, 0600);
 966
 967static struct kobj_attribute damon_sysfs_watermarks_high_attr =
 968		__ATTR_RW_MODE(high, 0600);
 969
 970static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
 971		__ATTR_RW_MODE(mid, 0600);
 972
 973static struct kobj_attribute damon_sysfs_watermarks_low_attr =
 974		__ATTR_RW_MODE(low, 0600);
 975
 976static struct attribute *damon_sysfs_watermarks_attrs[] = {
 977	&damon_sysfs_watermarks_metric_attr.attr,
 978	&damon_sysfs_watermarks_interval_us_attr.attr,
 979	&damon_sysfs_watermarks_high_attr.attr,
 980	&damon_sysfs_watermarks_mid_attr.attr,
 981	&damon_sysfs_watermarks_low_attr.attr,
 982	NULL,
 983};
 984ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
 985
 986static const struct kobj_type damon_sysfs_watermarks_ktype = {
 987	.release = damon_sysfs_watermarks_release,
 988	.sysfs_ops = &kobj_sysfs_ops,
 989	.default_groups = damon_sysfs_watermarks_groups,
 990};
 991
 992/*
 993 * quota goal directory
 994 */
 995
 996struct damos_sysfs_quota_goal {
 997	struct kobject kobj;
 998	enum damos_quota_goal_metric metric;
 999	unsigned long target_value;
1000	unsigned long current_value;
1001	int nid;
1002	char *path;
1003};
1004
1005static struct damos_sysfs_quota_goal *damos_sysfs_quota_goal_alloc(void)
1006{
1007	return kzalloc(sizeof(struct damos_sysfs_quota_goal), GFP_KERNEL);
1008}
1009
1010struct damos_sysfs_qgoal_metric_name {
1011	enum damos_quota_goal_metric metric;
1012	char *name;
1013};
1014
1015static
1016struct damos_sysfs_qgoal_metric_name damos_sysfs_qgoal_metric_names[] = {
1017	{
1018		.metric = DAMOS_QUOTA_USER_INPUT,
1019		.name = "user_input",
1020	},
1021	{
1022		.metric = DAMOS_QUOTA_SOME_MEM_PSI_US,
1023		.name = "some_mem_psi_us",
1024	},
1025	{
1026		.metric = DAMOS_QUOTA_NODE_MEM_USED_BP,
1027		.name = "node_mem_used_bp",
1028	},
1029	{
1030		.metric = DAMOS_QUOTA_NODE_MEM_FREE_BP,
1031		.name = "node_mem_free_bp",
1032	},
1033	{
1034		.metric = DAMOS_QUOTA_NODE_MEMCG_USED_BP,
1035		.name = "node_memcg_used_bp",
1036	},
1037	{
1038		.metric = DAMOS_QUOTA_NODE_MEMCG_FREE_BP,
1039		.name = "node_memcg_free_bp",
1040	},
1041};
1042
1043static ssize_t target_metric_show(struct kobject *kobj,
1044		struct kobj_attribute *attr, char *buf)
1045{
1046	struct damos_sysfs_quota_goal *goal = container_of(kobj,
1047			struct damos_sysfs_quota_goal, kobj);
1048	int i;
1049
1050	for (i = 0; i < ARRAY_SIZE(damos_sysfs_qgoal_metric_names); i++) {
1051		struct damos_sysfs_qgoal_metric_name *metric_name;
1052
1053		metric_name = &damos_sysfs_qgoal_metric_names[i];
1054		if (metric_name->metric == goal->metric)
1055			return sysfs_emit(buf, "%s\n", metric_name->name);
1056	}
1057	return -EINVAL;
1058}
1059
1060static ssize_t target_metric_store(struct kobject *kobj,
1061		struct kobj_attribute *attr, const char *buf, size_t count)
1062{
1063	struct damos_sysfs_quota_goal *goal = container_of(kobj,
1064			struct damos_sysfs_quota_goal, kobj);
1065	int i;
1066
1067	for (i = 0; i < ARRAY_SIZE(damos_sysfs_qgoal_metric_names); i++) {
1068		struct damos_sysfs_qgoal_metric_name *metric_name;
1069
1070		metric_name = &damos_sysfs_qgoal_metric_names[i];
1071		if (sysfs_streq(buf, metric_name->name)) {
1072			goal->metric = metric_name->metric;
1073			return count;
1074		}
1075	}
1076	return -EINVAL;
1077}
1078
1079static ssize_t target_value_show(struct kobject *kobj,
1080		struct kobj_attribute *attr, char *buf)
1081{
1082	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
1083			damos_sysfs_quota_goal, kobj);
1084
1085	return sysfs_emit(buf, "%lu\n", goal->target_value);
1086}
1087
1088static ssize_t target_value_store(struct kobject *kobj,
1089		struct kobj_attribute *attr, const char *buf, size_t count)
1090{
1091	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
1092			damos_sysfs_quota_goal, kobj);
1093	int err = kstrtoul(buf, 0, &goal->target_value);
1094
1095	return err ? err : count;
1096}
1097
1098static ssize_t current_value_show(struct kobject *kobj,
1099		struct kobj_attribute *attr, char *buf)
1100{
1101	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
1102			damos_sysfs_quota_goal, kobj);
1103
1104	return sysfs_emit(buf, "%lu\n", goal->current_value);
1105}
1106
1107static ssize_t current_value_store(struct kobject *kobj,
1108		struct kobj_attribute *attr, const char *buf, size_t count)
1109{
1110	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
1111			damos_sysfs_quota_goal, kobj);
1112	int err = kstrtoul(buf, 0, &goal->current_value);
1113
1114	/* feed callback should check existence of this file and read value */
1115	return err ? err : count;
1116}
1117
1118static ssize_t nid_show(struct kobject *kobj,
1119		struct kobj_attribute *attr, char *buf)
1120{
1121	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
1122			damos_sysfs_quota_goal, kobj);
1123
1124
1125	return sysfs_emit(buf, "%d\n", goal->nid);
1126}
1127
1128static ssize_t nid_store(struct kobject *kobj,
1129		struct kobj_attribute *attr, const char *buf, size_t count)
1130{
1131	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
1132			damos_sysfs_quota_goal, kobj);
1133	int err = kstrtoint(buf, 0, &goal->nid);
1134
1135	/* feed callback should check existence of this file and read value */
1136	return err ? err : count;
1137}
1138
1139static ssize_t path_show(struct kobject *kobj,
1140		struct kobj_attribute *attr, char *buf)
1141{
1142	struct damos_sysfs_quota_goal *goal = container_of(kobj,
1143			struct damos_sysfs_quota_goal, kobj);
1144
1145	return sysfs_emit(buf, "%s\n", goal->path ? goal->path : "");
1146}
1147
1148static ssize_t path_store(struct kobject *kobj,
1149		struct kobj_attribute *attr, const char *buf, size_t count)
1150{
1151	struct damos_sysfs_quota_goal *goal = container_of(kobj,
1152			struct damos_sysfs_quota_goal, kobj);
1153	char *path = kmalloc_array(size_add(count, 1), sizeof(*path),
1154				   GFP_KERNEL);
1155
1156	if (!path)
1157		return -ENOMEM;
1158
1159	strscpy(path, buf, count + 1);
1160	kfree(goal->path);
1161	goal->path = path;
1162	return count;
1163}
1164
1165static void damos_sysfs_quota_goal_release(struct kobject *kobj)
1166{
1167	struct damos_sysfs_quota_goal *goal = container_of(kobj,
1168			struct damos_sysfs_quota_goal, kobj);
1169
1170	kfree(goal->path);
1171	kfree(goal);
1172}
1173
1174static struct kobj_attribute damos_sysfs_quota_goal_target_metric_attr =
1175		__ATTR_RW_MODE(target_metric, 0600);
1176
1177static struct kobj_attribute damos_sysfs_quota_goal_target_value_attr =
1178		__ATTR_RW_MODE(target_value, 0600);
1179
1180static struct kobj_attribute damos_sysfs_quota_goal_current_value_attr =
1181		__ATTR_RW_MODE(current_value, 0600);
1182
1183static struct kobj_attribute damos_sysfs_quota_goal_nid_attr =
1184		__ATTR_RW_MODE(nid, 0600);
1185
1186static struct kobj_attribute damos_sysfs_quota_goal_path_attr =
1187		__ATTR_RW_MODE(path, 0600);
1188
1189static struct attribute *damos_sysfs_quota_goal_attrs[] = {
1190	&damos_sysfs_quota_goal_target_metric_attr.attr,
1191	&damos_sysfs_quota_goal_target_value_attr.attr,
1192	&damos_sysfs_quota_goal_current_value_attr.attr,
1193	&damos_sysfs_quota_goal_nid_attr.attr,
1194	&damos_sysfs_quota_goal_path_attr.attr,
1195	NULL,
1196};
1197ATTRIBUTE_GROUPS(damos_sysfs_quota_goal);
1198
1199static const struct kobj_type damos_sysfs_quota_goal_ktype = {
1200	.release = damos_sysfs_quota_goal_release,
1201	.sysfs_ops = &kobj_sysfs_ops,
1202	.default_groups = damos_sysfs_quota_goal_groups,
1203};
1204
1205/*
1206 * quota goals directory
1207 */
1208
1209struct damos_sysfs_quota_goals {
1210	struct kobject kobj;
1211	struct damos_sysfs_quota_goal **goals_arr;	/* counted by nr */
1212	int nr;
1213};
1214
1215static struct damos_sysfs_quota_goals *damos_sysfs_quota_goals_alloc(void)
1216{
1217	return kzalloc(sizeof(struct damos_sysfs_quota_goals), GFP_KERNEL);
1218}
1219
1220static void damos_sysfs_quota_goals_rm_dirs(
1221		struct damos_sysfs_quota_goals *goals)
1222{
1223	struct damos_sysfs_quota_goal **goals_arr = goals->goals_arr;
1224	int i;
1225
1226	for (i = 0; i < goals->nr; i++)
1227		kobject_put(&goals_arr[i]->kobj);
1228	goals->nr = 0;
1229	kfree(goals_arr);
1230	goals->goals_arr = NULL;
1231}
1232
1233static int damos_sysfs_quota_goals_add_dirs(
1234		struct damos_sysfs_quota_goals *goals, int nr_goals)
1235{
1236	struct damos_sysfs_quota_goal **goals_arr, *goal;
1237	int err, i;
1238
1239	damos_sysfs_quota_goals_rm_dirs(goals);
1240	if (!nr_goals)
1241		return 0;
1242
1243	goals_arr = kmalloc_array(nr_goals, sizeof(*goals_arr),
1244			GFP_KERNEL | __GFP_NOWARN);
1245	if (!goals_arr)
1246		return -ENOMEM;
1247	goals->goals_arr = goals_arr;
1248
1249	for (i = 0; i < nr_goals; i++) {
1250		goal = damos_sysfs_quota_goal_alloc();
1251		if (!goal) {
1252			damos_sysfs_quota_goals_rm_dirs(goals);
1253			return -ENOMEM;
1254		}
1255
1256		err = kobject_init_and_add(&goal->kobj,
1257				&damos_sysfs_quota_goal_ktype, &goals->kobj,
1258				"%d", i);
1259		if (err) {
1260			kobject_put(&goal->kobj);
1261			damos_sysfs_quota_goals_rm_dirs(goals);
1262			return err;
1263		}
1264
1265		goals_arr[i] = goal;
1266		goals->nr++;
1267	}
1268	return 0;
1269}
1270
1271static ssize_t nr_goals_show(struct kobject *kobj,
1272		struct kobj_attribute *attr, char *buf)
1273{
1274	struct damos_sysfs_quota_goals *goals = container_of(kobj,
1275			struct damos_sysfs_quota_goals, kobj);
1276
1277	return sysfs_emit(buf, "%d\n", goals->nr);
1278}
1279
1280static ssize_t nr_goals_store(struct kobject *kobj,
1281		struct kobj_attribute *attr, const char *buf, size_t count)
1282{
1283	struct damos_sysfs_quota_goals *goals;
1284	int nr, err = kstrtoint(buf, 0, &nr);
1285
1286	if (err)
1287		return err;
1288	if (nr < 0)
1289		return -EINVAL;
1290
1291	goals = container_of(kobj, struct damos_sysfs_quota_goals, kobj);
1292
1293	if (!mutex_trylock(&damon_sysfs_lock))
1294		return -EBUSY;
1295	err = damos_sysfs_quota_goals_add_dirs(goals, nr);
1296	mutex_unlock(&damon_sysfs_lock);
1297	if (err)
1298		return err;
1299
1300	return count;
1301}
1302
1303static void damos_sysfs_quota_goals_release(struct kobject *kobj)
1304{
1305	kfree(container_of(kobj, struct damos_sysfs_quota_goals, kobj));
1306}
1307
1308static struct kobj_attribute damos_sysfs_quota_goals_nr_attr =
1309		__ATTR_RW_MODE(nr_goals, 0600);
1310
1311static struct attribute *damos_sysfs_quota_goals_attrs[] = {
1312	&damos_sysfs_quota_goals_nr_attr.attr,
1313	NULL,
1314};
1315ATTRIBUTE_GROUPS(damos_sysfs_quota_goals);
1316
1317static const struct kobj_type damos_sysfs_quota_goals_ktype = {
1318	.release = damos_sysfs_quota_goals_release,
1319	.sysfs_ops = &kobj_sysfs_ops,
1320	.default_groups = damos_sysfs_quota_goals_groups,
1321};
1322
1323/*
1324 * scheme/weights directory
1325 */
1326
1327struct damon_sysfs_weights {
1328	struct kobject kobj;
1329	unsigned int sz;
1330	unsigned int nr_accesses;
1331	unsigned int age;
1332};
1333
1334static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
1335		unsigned int nr_accesses, unsigned int age)
1336{
1337	struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
1338			GFP_KERNEL);
1339
1340	if (!weights)
1341		return NULL;
1342	weights->kobj = (struct kobject){};
1343	weights->sz = sz;
1344	weights->nr_accesses = nr_accesses;
1345	weights->age = age;
1346	return weights;
1347}
1348
1349static ssize_t sz_permil_show(struct kobject *kobj,
1350		struct kobj_attribute *attr, char *buf)
1351{
1352	struct damon_sysfs_weights *weights = container_of(kobj,
1353			struct damon_sysfs_weights, kobj);
1354
1355	return sysfs_emit(buf, "%u\n", weights->sz);
1356}
1357
1358static ssize_t sz_permil_store(struct kobject *kobj,
1359		struct kobj_attribute *attr, const char *buf, size_t count)
1360{
1361	struct damon_sysfs_weights *weights = container_of(kobj,
1362			struct damon_sysfs_weights, kobj);
1363	int err = kstrtouint(buf, 0, &weights->sz);
1364
1365	return err ? err : count;
1366}
1367
1368static ssize_t nr_accesses_permil_show(struct kobject *kobj,
1369		struct kobj_attribute *attr, char *buf)
1370{
1371	struct damon_sysfs_weights *weights = container_of(kobj,
1372			struct damon_sysfs_weights, kobj);
1373
1374	return sysfs_emit(buf, "%u\n", weights->nr_accesses);
1375}
1376
1377static ssize_t nr_accesses_permil_store(struct kobject *kobj,
1378		struct kobj_attribute *attr, const char *buf, size_t count)
1379{
1380	struct damon_sysfs_weights *weights = container_of(kobj,
1381			struct damon_sysfs_weights, kobj);
1382	int err = kstrtouint(buf, 0, &weights->nr_accesses);
1383
1384	return err ? err : count;
1385}
1386
1387static ssize_t age_permil_show(struct kobject *kobj,
1388		struct kobj_attribute *attr, char *buf)
1389{
1390	struct damon_sysfs_weights *weights = container_of(kobj,
1391			struct damon_sysfs_weights, kobj);
1392
1393	return sysfs_emit(buf, "%u\n", weights->age);
1394}
1395
1396static ssize_t age_permil_store(struct kobject *kobj,
1397		struct kobj_attribute *attr, const char *buf, size_t count)
1398{
1399	struct damon_sysfs_weights *weights = container_of(kobj,
1400			struct damon_sysfs_weights, kobj);
1401	int err = kstrtouint(buf, 0, &weights->age);
1402
1403	return err ? err : count;
1404}
1405
1406static void damon_sysfs_weights_release(struct kobject *kobj)
1407{
1408	kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
1409}
1410
1411static struct kobj_attribute damon_sysfs_weights_sz_attr =
1412		__ATTR_RW_MODE(sz_permil, 0600);
1413
1414static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
1415		__ATTR_RW_MODE(nr_accesses_permil, 0600);
1416
1417static struct kobj_attribute damon_sysfs_weights_age_attr =
1418		__ATTR_RW_MODE(age_permil, 0600);
1419
1420static struct attribute *damon_sysfs_weights_attrs[] = {
1421	&damon_sysfs_weights_sz_attr.attr,
1422	&damon_sysfs_weights_nr_accesses_attr.attr,
1423	&damon_sysfs_weights_age_attr.attr,
1424	NULL,
1425};
1426ATTRIBUTE_GROUPS(damon_sysfs_weights);
1427
1428static const struct kobj_type damon_sysfs_weights_ktype = {
1429	.release = damon_sysfs_weights_release,
1430	.sysfs_ops = &kobj_sysfs_ops,
1431	.default_groups = damon_sysfs_weights_groups,
1432};
1433
1434/*
1435 * quotas directory
1436 */
1437
1438struct damon_sysfs_quotas {
1439	struct kobject kobj;
1440	struct damon_sysfs_weights *weights;
1441	struct damos_sysfs_quota_goals *goals;
1442	unsigned long ms;
1443	unsigned long sz;
1444	unsigned long reset_interval_ms;
1445	unsigned long effective_sz;	/* Effective size quota in bytes */
1446};
1447
1448static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
1449{
1450	return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
1451}
1452
1453static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
1454{
1455	struct damon_sysfs_weights *weights;
1456	struct damos_sysfs_quota_goals *goals;
1457	int err;
1458
1459	weights = damon_sysfs_weights_alloc(0, 0, 0);
1460	if (!weights)
1461		return -ENOMEM;
1462
1463	err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
1464			&quotas->kobj, "weights");
1465	if (err) {
1466		kobject_put(&weights->kobj);
1467		return err;
1468	}
1469	quotas->weights = weights;
1470
1471	goals = damos_sysfs_quota_goals_alloc();
1472	if (!goals) {
1473		kobject_put(&weights->kobj);
1474		return -ENOMEM;
1475	}
1476	err = kobject_init_and_add(&goals->kobj,
1477			&damos_sysfs_quota_goals_ktype, &quotas->kobj,
1478			"goals");
1479	if (err) {
1480		kobject_put(&weights->kobj);
1481		kobject_put(&goals->kobj);
1482	} else {
1483		quotas->goals = goals;
1484	}
1485
1486	return err;
1487}
1488
1489static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
1490{
1491	kobject_put(&quotas->weights->kobj);
1492	damos_sysfs_quota_goals_rm_dirs(quotas->goals);
1493	kobject_put(&quotas->goals->kobj);
1494}
1495
1496static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
1497		char *buf)
1498{
1499	struct damon_sysfs_quotas *quotas = container_of(kobj,
1500			struct damon_sysfs_quotas, kobj);
1501
1502	return sysfs_emit(buf, "%lu\n", quotas->ms);
1503}
1504
1505static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
1506		const char *buf, size_t count)
1507{
1508	struct damon_sysfs_quotas *quotas = container_of(kobj,
1509			struct damon_sysfs_quotas, kobj);
1510	int err = kstrtoul(buf, 0, &quotas->ms);
1511
1512	if (err)
1513		return -EINVAL;
1514	return count;
1515}
1516
1517static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
1518		char *buf)
1519{
1520	struct damon_sysfs_quotas *quotas = container_of(kobj,
1521			struct damon_sysfs_quotas, kobj);
1522
1523	return sysfs_emit(buf, "%lu\n", quotas->sz);
1524}
1525
1526static ssize_t bytes_store(struct kobject *kobj,
1527		struct kobj_attribute *attr, const char *buf, size_t count)
1528{
1529	struct damon_sysfs_quotas *quotas = container_of(kobj,
1530			struct damon_sysfs_quotas, kobj);
1531	int err = kstrtoul(buf, 0, &quotas->sz);
1532
1533	if (err)
1534		return -EINVAL;
1535	return count;
1536}
1537
1538static ssize_t reset_interval_ms_show(struct kobject *kobj,
1539		struct kobj_attribute *attr, char *buf)
1540{
1541	struct damon_sysfs_quotas *quotas = container_of(kobj,
1542			struct damon_sysfs_quotas, kobj);
1543
1544	return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
1545}
1546
1547static ssize_t reset_interval_ms_store(struct kobject *kobj,
1548		struct kobj_attribute *attr, const char *buf, size_t count)
1549{
1550	struct damon_sysfs_quotas *quotas = container_of(kobj,
1551			struct damon_sysfs_quotas, kobj);
1552	int err = kstrtoul(buf, 0, &quotas->reset_interval_ms);
1553
1554	if (err)
1555		return -EINVAL;
1556	return count;
1557}
1558
1559static ssize_t effective_bytes_show(struct kobject *kobj,
1560		struct kobj_attribute *attr, char *buf)
1561{
1562	struct damon_sysfs_quotas *quotas = container_of(kobj,
1563			struct damon_sysfs_quotas, kobj);
1564
1565	return sysfs_emit(buf, "%lu\n", quotas->effective_sz);
1566}
1567
1568static void damon_sysfs_quotas_release(struct kobject *kobj)
1569{
1570	kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
1571}
1572
1573static struct kobj_attribute damon_sysfs_quotas_ms_attr =
1574		__ATTR_RW_MODE(ms, 0600);
1575
1576static struct kobj_attribute damon_sysfs_quotas_sz_attr =
1577		__ATTR_RW_MODE(bytes, 0600);
1578
1579static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
1580		__ATTR_RW_MODE(reset_interval_ms, 0600);
1581
1582static struct kobj_attribute damon_sysfs_quotas_effective_bytes_attr =
1583		__ATTR_RO_MODE(effective_bytes, 0400);
1584
1585static struct attribute *damon_sysfs_quotas_attrs[] = {
1586	&damon_sysfs_quotas_ms_attr.attr,
1587	&damon_sysfs_quotas_sz_attr.attr,
1588	&damon_sysfs_quotas_reset_interval_ms_attr.attr,
1589	&damon_sysfs_quotas_effective_bytes_attr.attr,
1590	NULL,
1591};
1592ATTRIBUTE_GROUPS(damon_sysfs_quotas);
1593
1594static const struct kobj_type damon_sysfs_quotas_ktype = {
1595	.release = damon_sysfs_quotas_release,
1596	.sysfs_ops = &kobj_sysfs_ops,
1597	.default_groups = damon_sysfs_quotas_groups,
1598};
1599
1600/*
1601 * access_pattern directory
1602 */
1603
1604struct damon_sysfs_access_pattern {
1605	struct kobject kobj;
1606	struct damon_sysfs_ul_range *sz;
1607	struct damon_sysfs_ul_range *nr_accesses;
1608	struct damon_sysfs_ul_range *age;
1609};
1610
1611static
1612struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
1613{
1614	struct damon_sysfs_access_pattern *access_pattern =
1615		kmalloc(sizeof(*access_pattern), GFP_KERNEL);
1616
1617	if (!access_pattern)
1618		return NULL;
1619	access_pattern->kobj = (struct kobject){};
1620	return access_pattern;
1621}
1622
1623static int damon_sysfs_access_pattern_add_range_dir(
1624		struct damon_sysfs_access_pattern *access_pattern,
1625		struct damon_sysfs_ul_range **range_dir_ptr,
1626		char *name)
1627{
1628	struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
1629	int err;
1630
1631	if (!range)
1632		return -ENOMEM;
1633	err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
1634			&access_pattern->kobj, "%s", name);
1635	if (err)
1636		kobject_put(&range->kobj);
1637	else
1638		*range_dir_ptr = range;
1639	return err;
1640}
1641
1642static int damon_sysfs_access_pattern_add_dirs(
1643		struct damon_sysfs_access_pattern *access_pattern)
1644{
1645	int err;
1646
1647	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1648			&access_pattern->sz, "sz");
1649	if (err)
1650		goto put_sz_out;
1651
1652	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1653			&access_pattern->nr_accesses, "nr_accesses");
1654	if (err)
1655		goto put_nr_accesses_sz_out;
1656
1657	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1658			&access_pattern->age, "age");
1659	if (err)
1660		goto put_age_nr_accesses_sz_out;
1661	return 0;
1662
1663put_age_nr_accesses_sz_out:
1664	kobject_put(&access_pattern->age->kobj);
1665	access_pattern->age = NULL;
1666put_nr_accesses_sz_out:
1667	kobject_put(&access_pattern->nr_accesses->kobj);
1668	access_pattern->nr_accesses = NULL;
1669put_sz_out:
1670	kobject_put(&access_pattern->sz->kobj);
1671	access_pattern->sz = NULL;
1672	return err;
1673}
1674
1675static void damon_sysfs_access_pattern_rm_dirs(
1676		struct damon_sysfs_access_pattern *access_pattern)
1677{
1678	kobject_put(&access_pattern->sz->kobj);
1679	kobject_put(&access_pattern->nr_accesses->kobj);
1680	kobject_put(&access_pattern->age->kobj);
1681}
1682
1683static void damon_sysfs_access_pattern_release(struct kobject *kobj)
1684{
1685	kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
1686}
1687
1688static struct attribute *damon_sysfs_access_pattern_attrs[] = {
1689	NULL,
1690};
1691ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
1692
1693static const struct kobj_type damon_sysfs_access_pattern_ktype = {
1694	.release = damon_sysfs_access_pattern_release,
1695	.sysfs_ops = &kobj_sysfs_ops,
1696	.default_groups = damon_sysfs_access_pattern_groups,
1697};
1698
1699/*
1700 * dest (action destination) directory
1701 */
1702
1703struct damos_sysfs_dest {
1704	struct kobject kobj;
1705	unsigned int id;
1706	unsigned int weight;
1707};
1708
1709static struct damos_sysfs_dest *damos_sysfs_dest_alloc(void)
1710{
1711	return kzalloc(sizeof(struct damos_sysfs_dest), GFP_KERNEL);
1712}
1713
1714static ssize_t id_show(
1715		struct kobject *kobj, struct kobj_attribute *attr, char *buf)
1716{
1717	struct damos_sysfs_dest *dest = container_of(kobj,
1718			struct damos_sysfs_dest, kobj);
1719
1720	return sysfs_emit(buf, "%u\n", dest->id);
1721}
1722
1723static ssize_t id_store(struct kobject *kobj,
1724		struct kobj_attribute *attr, const char *buf, size_t count)
1725{
1726	struct damos_sysfs_dest *dest = container_of(kobj,
1727			struct damos_sysfs_dest, kobj);
1728	int err = kstrtouint(buf, 0, &dest->id);
1729
1730	return err ? err : count;
1731}
1732
1733static ssize_t weight_show(
1734		struct kobject *kobj, struct kobj_attribute *attr, char *buf)
1735{
1736	struct damos_sysfs_dest *dest = container_of(kobj,
1737			struct damos_sysfs_dest, kobj);
1738
1739	return sysfs_emit(buf, "%u\n", dest->weight);
1740}
1741
1742static ssize_t weight_store(struct kobject *kobj,
1743		struct kobj_attribute *attr, const char *buf, size_t count)
1744{
1745	struct damos_sysfs_dest *dest = container_of(kobj,
1746			struct damos_sysfs_dest, kobj);
1747	int err = kstrtouint(buf, 0, &dest->weight);
1748
1749	return err ? err : count;
1750}
1751
1752static void damos_sysfs_dest_release(struct kobject *kobj)
1753{
1754	struct damos_sysfs_dest *dest = container_of(kobj,
1755			struct damos_sysfs_dest, kobj);
1756	kfree(dest);
1757}
1758
1759static struct kobj_attribute damos_sysfs_dest_id_attr =
1760		__ATTR_RW_MODE(id, 0600);
1761
1762static struct kobj_attribute damos_sysfs_dest_weight_attr =
1763		__ATTR_RW_MODE(weight, 0600);
1764
1765static struct attribute *damos_sysfs_dest_attrs[] = {
1766	&damos_sysfs_dest_id_attr.attr,
1767	&damos_sysfs_dest_weight_attr.attr,
1768	NULL,
1769};
1770ATTRIBUTE_GROUPS(damos_sysfs_dest);
1771
1772static const struct kobj_type damos_sysfs_dest_ktype = {
1773	.release = damos_sysfs_dest_release,
1774	.sysfs_ops = &kobj_sysfs_ops,
1775	.default_groups = damos_sysfs_dest_groups,
1776};
1777
1778/*
1779 * dests (action destinations) directory
1780 */
1781
1782struct damos_sysfs_dests {
1783	struct kobject kobj;
1784	struct damos_sysfs_dest **dests_arr;
1785	int nr;
1786};
1787
1788static struct damos_sysfs_dests *
1789damos_sysfs_dests_alloc(void)
1790{
1791	return kzalloc(sizeof(struct damos_sysfs_dests), GFP_KERNEL);
1792}
1793
1794static void damos_sysfs_dests_rm_dirs(
1795		struct damos_sysfs_dests *dests)
1796{
1797	struct damos_sysfs_dest **dests_arr = dests->dests_arr;
1798	int i;
1799
1800	for (i = 0; i < dests->nr; i++)
1801		kobject_put(&dests_arr[i]->kobj);
1802	dests->nr = 0;
1803	kfree(dests_arr);
1804	dests->dests_arr = NULL;
1805}
1806
1807static int damos_sysfs_dests_add_dirs(
1808		struct damos_sysfs_dests *dests, int nr_dests)
1809{
1810	struct damos_sysfs_dest **dests_arr, *dest;
1811	int err, i;
1812
1813	damos_sysfs_dests_rm_dirs(dests);
1814	if (!nr_dests)
1815		return 0;
1816
1817	dests_arr = kmalloc_array(nr_dests, sizeof(*dests_arr),
1818			GFP_KERNEL | __GFP_NOWARN);
1819	if (!dests_arr)
1820		return -ENOMEM;
1821	dests->dests_arr = dests_arr;
1822
1823	for (i = 0; i < nr_dests; i++) {
1824		dest = damos_sysfs_dest_alloc();
1825		if (!dest) {
1826			damos_sysfs_dests_rm_dirs(dests);
1827			return -ENOMEM;
1828		}
1829
1830		err = kobject_init_and_add(&dest->kobj,
1831				&damos_sysfs_dest_ktype,
1832				&dests->kobj, "%d", i);
1833		if (err) {
1834			kobject_put(&dest->kobj);
1835			damos_sysfs_dests_rm_dirs(dests);
1836			return err;
1837		}
1838
1839		dests_arr[i] = dest;
1840		dests->nr++;
1841	}
1842	return 0;
1843}
1844
1845static ssize_t nr_dests_show(struct kobject *kobj,
1846		struct kobj_attribute *attr, char *buf)
1847{
1848	struct damos_sysfs_dests *dests = container_of(kobj,
1849			struct damos_sysfs_dests, kobj);
1850
1851	return sysfs_emit(buf, "%d\n", dests->nr);
1852}
1853
1854static ssize_t nr_dests_store(struct kobject *kobj,
1855		struct kobj_attribute *attr, const char *buf, size_t count)
1856{
1857	struct damos_sysfs_dests *dests;
1858	int nr, err = kstrtoint(buf, 0, &nr);
1859
1860	if (err)
1861		return err;
1862	if (nr < 0)
1863		return -EINVAL;
1864
1865	dests = container_of(kobj, struct damos_sysfs_dests, kobj);
1866
1867	if (!mutex_trylock(&damon_sysfs_lock))
1868		return -EBUSY;
1869	err = damos_sysfs_dests_add_dirs(dests, nr);
1870	mutex_unlock(&damon_sysfs_lock);
1871	if (err)
1872		return err;
1873
1874	return count;
1875}
1876
1877static void damos_sysfs_dests_release(struct kobject *kobj)
1878{
1879	kfree(container_of(kobj, struct damos_sysfs_dests, kobj));
1880}
1881
1882static struct kobj_attribute damos_sysfs_dests_nr_attr =
1883		__ATTR_RW_MODE(nr_dests, 0600);
1884
1885static struct attribute *damos_sysfs_dests_attrs[] = {
1886	&damos_sysfs_dests_nr_attr.attr,
1887	NULL,
1888};
1889ATTRIBUTE_GROUPS(damos_sysfs_dests);
1890
1891static const struct kobj_type damos_sysfs_dests_ktype = {
1892	.release = damos_sysfs_dests_release,
1893	.sysfs_ops = &kobj_sysfs_ops,
1894	.default_groups = damos_sysfs_dests_groups,
1895};
1896
1897/*
1898 * scheme directory
1899 */
1900
1901struct damon_sysfs_scheme {
1902	struct kobject kobj;
1903	enum damos_action action;
1904	struct damon_sysfs_access_pattern *access_pattern;
1905	unsigned long apply_interval_us;
1906	struct damon_sysfs_quotas *quotas;
1907	struct damon_sysfs_watermarks *watermarks;
1908	struct damon_sysfs_scheme_filters *core_filters;
1909	struct damon_sysfs_scheme_filters *ops_filters;
1910	struct damon_sysfs_scheme_filters *filters;
1911	struct damon_sysfs_stats *stats;
1912	struct damon_sysfs_scheme_regions *tried_regions;
1913	int target_nid;
1914	struct damos_sysfs_dests *dests;
1915};
1916
1917struct damos_sysfs_action_name {
1918	enum damos_action action;
1919	char *name;
1920};
1921
1922static struct damos_sysfs_action_name damos_sysfs_action_names[] = {
1923	{
1924		.action = DAMOS_WILLNEED,
1925		.name = "willneed",
1926	},
1927	{
1928		.action = DAMOS_COLD,
1929		.name = "cold",
1930	},
1931	{
1932		.action = DAMOS_PAGEOUT,
1933		.name = "pageout",
1934	},
1935	{
1936		.action = DAMOS_HUGEPAGE,
1937		.name = "hugepage",
1938	},
1939	{
1940		.action = DAMOS_NOHUGEPAGE,
1941		.name = "nohugepage",
1942	},
1943	{
1944		.action = DAMOS_LRU_PRIO,
1945		.name = "lru_prio",
1946	},
1947	{
1948		.action = DAMOS_LRU_DEPRIO,
1949		.name = "lru_deprio",
1950	},
1951	{
1952		.action = DAMOS_MIGRATE_HOT,
1953		.name = "migrate_hot",
1954	},
1955	{
1956		.action = DAMOS_MIGRATE_COLD,
1957		.name = "migrate_cold",
1958	},
1959	{
1960		.action = DAMOS_STAT,
1961		.name = "stat",
1962	},
1963};
1964
1965static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
1966		enum damos_action action, unsigned long apply_interval_us)
1967{
1968	struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
1969				GFP_KERNEL);
1970
1971	if (!scheme)
1972		return NULL;
1973	scheme->kobj = (struct kobject){};
1974	scheme->action = action;
1975	scheme->apply_interval_us = apply_interval_us;
1976	scheme->target_nid = NUMA_NO_NODE;
1977	return scheme;
1978}
1979
1980static int damon_sysfs_scheme_set_access_pattern(
1981		struct damon_sysfs_scheme *scheme)
1982{
1983	struct damon_sysfs_access_pattern *access_pattern;
1984	int err;
1985
1986	access_pattern = damon_sysfs_access_pattern_alloc();
1987	if (!access_pattern)
1988		return -ENOMEM;
1989	err = kobject_init_and_add(&access_pattern->kobj,
1990			&damon_sysfs_access_pattern_ktype, &scheme->kobj,
1991			"access_pattern");
1992	if (err)
1993		goto out;
1994	err = damon_sysfs_access_pattern_add_dirs(access_pattern);
1995	if (err)
1996		goto out;
1997	scheme->access_pattern = access_pattern;
1998	return 0;
1999
2000out:
2001	kobject_put(&access_pattern->kobj);
2002	return err;
2003}
2004
2005static int damos_sysfs_set_dests(struct damon_sysfs_scheme *scheme)
2006{
2007	struct damos_sysfs_dests *dests = damos_sysfs_dests_alloc();
2008	int err;
2009
2010	if (!dests)
2011		return -ENOMEM;
2012	err = kobject_init_and_add(&dests->kobj, &damos_sysfs_dests_ktype,
2013			&scheme->kobj, "dests");
2014	if (err)
2015		kobject_put(&dests->kobj);
2016	else
2017		scheme->dests = dests;
2018	return err;
2019}
2020
2021static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
2022{
2023	struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
2024	int err;
2025
2026	if (!quotas)
2027		return -ENOMEM;
2028	err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
2029			&scheme->kobj, "quotas");
2030	if (err)
2031		goto out;
2032	err = damon_sysfs_quotas_add_dirs(quotas);
2033	if (err)
2034		goto out;
2035	scheme->quotas = quotas;
2036	return 0;
2037
2038out:
2039	kobject_put(&quotas->kobj);
2040	return err;
2041}
2042
2043static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
2044{
2045	struct damon_sysfs_watermarks *watermarks =
2046		damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
2047	int err;
2048
2049	if (!watermarks)
2050		return -ENOMEM;
2051	err = kobject_init_and_add(&watermarks->kobj,
2052			&damon_sysfs_watermarks_ktype, &scheme->kobj,
2053			"watermarks");
2054	if (err)
2055		kobject_put(&watermarks->kobj);
2056	else
2057		scheme->watermarks = watermarks;
2058	return err;
2059}
2060
2061static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme,
2062		enum damos_sysfs_filter_handle_layer layer, const char *name,
2063		struct damon_sysfs_scheme_filters **filters_ptr)
2064{
2065	struct damon_sysfs_scheme_filters *filters =
2066		damon_sysfs_scheme_filters_alloc(layer);
2067	int err;
2068
2069	if (!filters)
2070		return -ENOMEM;
2071	err = kobject_init_and_add(&filters->kobj,
2072			&damon_sysfs_scheme_filters_ktype, &scheme->kobj,
2073			"%s", name);
2074	if (err)
2075		kobject_put(&filters->kobj);
2076	else
2077		*filters_ptr = filters;
2078	return err;
2079}
2080
2081static int damos_sysfs_set_filter_dirs(struct damon_sysfs_scheme *scheme)
2082{
2083	int err;
2084
2085	err = damon_sysfs_scheme_set_filters(scheme,
2086			DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH, "filters",
2087			&scheme->filters);
2088	if (err)
2089		return err;
2090	err = damon_sysfs_scheme_set_filters(scheme,
2091			DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE, "core_filters",
2092			&scheme->core_filters);
2093	if (err)
2094		goto put_filters_out;
2095	err = damon_sysfs_scheme_set_filters(scheme,
2096			DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS, "ops_filters",
2097			&scheme->ops_filters);
2098	if (err)
2099		goto put_core_filters_out;
2100	return 0;
2101
2102put_core_filters_out:
2103	kobject_put(&scheme->core_filters->kobj);
2104	scheme->core_filters = NULL;
2105put_filters_out:
2106	kobject_put(&scheme->filters->kobj);
2107	scheme->filters = NULL;
2108	return err;
2109}
2110
2111static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
2112{
2113	struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
2114	int err;
2115
2116	if (!stats)
2117		return -ENOMEM;
2118	err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
2119			&scheme->kobj, "stats");
2120	if (err)
2121		kobject_put(&stats->kobj);
2122	else
2123		scheme->stats = stats;
2124	return err;
2125}
2126
2127static int damon_sysfs_scheme_set_tried_regions(
2128		struct damon_sysfs_scheme *scheme)
2129{
2130	struct damon_sysfs_scheme_regions *tried_regions =
2131		damon_sysfs_scheme_regions_alloc();
2132	int err;
2133
2134	if (!tried_regions)
2135		return -ENOMEM;
2136	err = kobject_init_and_add(&tried_regions->kobj,
2137			&damon_sysfs_scheme_regions_ktype, &scheme->kobj,
2138			"tried_regions");
2139	if (err)
2140		kobject_put(&tried_regions->kobj);
2141	else
2142		scheme->tried_regions = tried_regions;
2143	return err;
2144}
2145
2146static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
2147{
2148	int err;
2149
2150	err = damon_sysfs_scheme_set_access_pattern(scheme);
2151	if (err)
2152		return err;
2153	err = damos_sysfs_set_dests(scheme);
2154	if (err)
2155		goto rmdir_put_access_pattern_out;
2156	err = damon_sysfs_scheme_set_quotas(scheme);
2157	if (err)
2158		goto put_dests_out;
2159	err = damon_sysfs_scheme_set_watermarks(scheme);
2160	if (err)
2161		goto rmdir_put_quotas_access_pattern_out;
2162	err = damos_sysfs_set_filter_dirs(scheme);
2163	if (err)
2164		goto put_watermarks_quotas_access_pattern_out;
2165	err = damon_sysfs_scheme_set_stats(scheme);
2166	if (err)
2167		goto put_filters_watermarks_quotas_access_pattern_out;
2168	err = damon_sysfs_scheme_set_tried_regions(scheme);
2169	if (err)
2170		goto put_tried_regions_out;
2171	return 0;
2172
2173put_tried_regions_out:
2174	kobject_put(&scheme->tried_regions->kobj);
2175	scheme->tried_regions = NULL;
2176put_filters_watermarks_quotas_access_pattern_out:
2177	kobject_put(&scheme->ops_filters->kobj);
2178	scheme->ops_filters = NULL;
2179	kobject_put(&scheme->core_filters->kobj);
2180	scheme->core_filters = NULL;
2181	kobject_put(&scheme->filters->kobj);
2182	scheme->filters = NULL;
2183put_watermarks_quotas_access_pattern_out:
2184	kobject_put(&scheme->watermarks->kobj);
2185	scheme->watermarks = NULL;
2186rmdir_put_quotas_access_pattern_out:
2187	damon_sysfs_quotas_rm_dirs(scheme->quotas);
2188	kobject_put(&scheme->quotas->kobj);
2189	scheme->quotas = NULL;
2190put_dests_out:
2191	kobject_put(&scheme->dests->kobj);
2192	scheme->dests = NULL;
2193rmdir_put_access_pattern_out:
2194	damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
2195	kobject_put(&scheme->access_pattern->kobj);
2196	scheme->access_pattern = NULL;
2197	return err;
2198}
2199
2200static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
2201{
2202	damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
2203	kobject_put(&scheme->access_pattern->kobj);
2204	damos_sysfs_dests_rm_dirs(scheme->dests);
2205	kobject_put(&scheme->dests->kobj);
2206	damon_sysfs_quotas_rm_dirs(scheme->quotas);
2207	kobject_put(&scheme->quotas->kobj);
2208	kobject_put(&scheme->watermarks->kobj);
2209	damon_sysfs_scheme_filters_rm_dirs(scheme->filters);
2210	kobject_put(&scheme->filters->kobj);
2211	damon_sysfs_scheme_filters_rm_dirs(scheme->core_filters);
2212	kobject_put(&scheme->core_filters->kobj);
2213	damon_sysfs_scheme_filters_rm_dirs(scheme->ops_filters);
2214	kobject_put(&scheme->ops_filters->kobj);
2215	kobject_put(&scheme->stats->kobj);
2216	damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
2217	kobject_put(&scheme->tried_regions->kobj);
2218}
2219
2220static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
2221		char *buf)
2222{
2223	struct damon_sysfs_scheme *scheme = container_of(kobj,
2224			struct damon_sysfs_scheme, kobj);
2225	int i;
2226
2227	for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) {
2228		struct damos_sysfs_action_name *action_name;
2229
2230		action_name = &damos_sysfs_action_names[i];
2231		if (action_name->action == scheme->action)
2232			return sysfs_emit(buf, "%s\n", action_name->name);
2233	}
2234	return -EINVAL;
2235}
2236
2237static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
2238		const char *buf, size_t count)
2239{
2240	struct damon_sysfs_scheme *scheme = container_of(kobj,
2241			struct damon_sysfs_scheme, kobj);
2242	int i;
2243
2244	for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) {
2245		struct damos_sysfs_action_name *action_name;
2246
2247		action_name = &damos_sysfs_action_names[i];
2248		if (sysfs_streq(buf, action_name->name)) {
2249			scheme->action = action_name->action;
2250			return count;
2251		}
2252	}
2253	return -EINVAL;
2254}
2255
2256static ssize_t apply_interval_us_show(struct kobject *kobj,
2257		struct kobj_attribute *attr, char *buf)
2258{
2259	struct damon_sysfs_scheme *scheme = container_of(kobj,
2260			struct damon_sysfs_scheme, kobj);
2261
2262	return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us);
2263}
2264
2265static ssize_t apply_interval_us_store(struct kobject *kobj,
2266		struct kobj_attribute *attr, const char *buf, size_t count)
2267{
2268	struct damon_sysfs_scheme *scheme = container_of(kobj,
2269			struct damon_sysfs_scheme, kobj);
2270	int err = kstrtoul(buf, 0, &scheme->apply_interval_us);
2271
2272	return err ? err : count;
2273}
2274
2275static ssize_t target_nid_show(struct kobject *kobj,
2276		struct kobj_attribute *attr, char *buf)
2277{
2278	struct damon_sysfs_scheme *scheme = container_of(kobj,
2279			struct damon_sysfs_scheme, kobj);
2280
2281	return sysfs_emit(buf, "%d\n", scheme->target_nid);
2282}
2283
2284static ssize_t target_nid_store(struct kobject *kobj,
2285		struct kobj_attribute *attr, const char *buf, size_t count)
2286{
2287	struct damon_sysfs_scheme *scheme = container_of(kobj,
2288			struct damon_sysfs_scheme, kobj);
2289	int err = 0;
2290
2291	/* TODO: error handling for target_nid range. */
2292	err = kstrtoint(buf, 0, &scheme->target_nid);
2293
2294	return err ? err : count;
2295}
2296
2297static void damon_sysfs_scheme_release(struct kobject *kobj)
2298{
2299	kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
2300}
2301
2302static struct kobj_attribute damon_sysfs_scheme_action_attr =
2303		__ATTR_RW_MODE(action, 0600);
2304
2305static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr =
2306		__ATTR_RW_MODE(apply_interval_us, 0600);
2307
2308static struct kobj_attribute damon_sysfs_scheme_target_nid_attr =
2309		__ATTR_RW_MODE(target_nid, 0600);
2310
2311static struct attribute *damon_sysfs_scheme_attrs[] = {
2312	&damon_sysfs_scheme_action_attr.attr,
2313	&damon_sysfs_scheme_apply_interval_us_attr.attr,
2314	&damon_sysfs_scheme_target_nid_attr.attr,
2315	NULL,
2316};
2317ATTRIBUTE_GROUPS(damon_sysfs_scheme);
2318
2319static const struct kobj_type damon_sysfs_scheme_ktype = {
2320	.release = damon_sysfs_scheme_release,
2321	.sysfs_ops = &kobj_sysfs_ops,
2322	.default_groups = damon_sysfs_scheme_groups,
2323};
2324
2325/*
2326 * schemes directory
2327 */
2328
2329struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
2330{
2331	return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
2332}
2333
2334void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
2335{
2336	struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
2337	int i;
2338
2339	for (i = 0; i < schemes->nr; i++) {
2340		damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
2341		kobject_put(&schemes_arr[i]->kobj);
2342	}
2343	schemes->nr = 0;
2344	kfree(schemes_arr);
2345	schemes->schemes_arr = NULL;
2346}
2347
2348static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
2349		int nr_schemes)
2350{
2351	struct damon_sysfs_scheme **schemes_arr, *scheme;
2352	int err, i;
2353
2354	damon_sysfs_schemes_rm_dirs(schemes);
2355	if (!nr_schemes)
2356		return 0;
2357
2358	schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
2359			GFP_KERNEL | __GFP_NOWARN);
2360	if (!schemes_arr)
2361		return -ENOMEM;
2362	schemes->schemes_arr = schemes_arr;
2363
2364	for (i = 0; i < nr_schemes; i++) {
2365		/*
2366		 * apply_interval_us as 0 means same to aggregation interval
2367		 * (same to before-apply_interval behavior)
2368		 */
2369		scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0);
2370		if (!scheme) {
2371			damon_sysfs_schemes_rm_dirs(schemes);
2372			return -ENOMEM;
2373		}
2374
2375		err = kobject_init_and_add(&scheme->kobj,
2376				&damon_sysfs_scheme_ktype, &schemes->kobj,
2377				"%d", i);
2378		if (err)
2379			goto out;
2380		err = damon_sysfs_scheme_add_dirs(scheme);
2381		if (err)
2382			goto out;
2383
2384		schemes_arr[i] = scheme;
2385		schemes->nr++;
2386	}
2387	return 0;
2388
2389out:
2390	damon_sysfs_schemes_rm_dirs(schemes);
2391	kobject_put(&scheme->kobj);
2392	return err;
2393}
2394
2395static ssize_t nr_schemes_show(struct kobject *kobj,
2396		struct kobj_attribute *attr, char *buf)
2397{
2398	struct damon_sysfs_schemes *schemes = container_of(kobj,
2399			struct damon_sysfs_schemes, kobj);
2400
2401	return sysfs_emit(buf, "%d\n", schemes->nr);
2402}
2403
2404static ssize_t nr_schemes_store(struct kobject *kobj,
2405		struct kobj_attribute *attr, const char *buf, size_t count)
2406{
2407	struct damon_sysfs_schemes *schemes;
2408	int nr, err = kstrtoint(buf, 0, &nr);
2409
2410	if (err)
2411		return err;
2412	if (nr < 0)
2413		return -EINVAL;
2414
2415	schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
2416
2417	if (!mutex_trylock(&damon_sysfs_lock))
2418		return -EBUSY;
2419	err = damon_sysfs_schemes_add_dirs(schemes, nr);
2420	mutex_unlock(&damon_sysfs_lock);
2421	if (err)
2422		return err;
2423	return count;
2424}
2425
2426static void damon_sysfs_schemes_release(struct kobject *kobj)
2427{
2428	kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
2429}
2430
2431static struct kobj_attribute damon_sysfs_schemes_nr_attr =
2432		__ATTR_RW_MODE(nr_schemes, 0600);
2433
2434static struct attribute *damon_sysfs_schemes_attrs[] = {
2435	&damon_sysfs_schemes_nr_attr.attr,
2436	NULL,
2437};
2438ATTRIBUTE_GROUPS(damon_sysfs_schemes);
2439
2440const struct kobj_type damon_sysfs_schemes_ktype = {
2441	.release = damon_sysfs_schemes_release,
2442	.sysfs_ops = &kobj_sysfs_ops,
2443	.default_groups = damon_sysfs_schemes_groups,
2444};
2445
2446static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg,
2447		char *memcg_path_buf, char *path)
2448{
2449#ifdef CONFIG_MEMCG
2450	cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX);
2451	if (sysfs_streq(memcg_path_buf, path))
2452		return true;
2453#endif /* CONFIG_MEMCG */
2454	return false;
2455}
2456
2457static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id)
2458{
2459	struct mem_cgroup *memcg;
2460	char *path;
2461	bool found = false;
2462
2463	if (!memcg_path)
2464		return -EINVAL;
2465
2466	path = kmalloc_array(PATH_MAX, sizeof(*path), GFP_KERNEL);
2467	if (!path)
2468		return -ENOMEM;
2469
2470	for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg;
2471			memcg = mem_cgroup_iter(NULL, memcg, NULL)) {
2472		/* skip removed memcg */
2473		if (!mem_cgroup_id(memcg))
2474			continue;
2475		if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
2476			*id = mem_cgroup_id(memcg);
2477			found = true;
2478			break;
2479		}
2480	}
2481
2482	kfree(path);
2483	return found ? 0 : -EINVAL;
2484}
2485
2486static int damon_sysfs_add_scheme_filters(struct damos *scheme,
2487		struct damon_sysfs_scheme_filters *sysfs_filters)
2488{
2489	int i;
2490
2491	for (i = 0; i < sysfs_filters->nr; i++) {
2492		struct damon_sysfs_scheme_filter *sysfs_filter =
2493			sysfs_filters->filters_arr[i];
2494		struct damos_filter *filter =
2495			damos_new_filter(sysfs_filter->type,
2496					sysfs_filter->matching,
2497					sysfs_filter->allow);
2498		int err;
2499
2500		if (!filter)
2501			return -ENOMEM;
2502		if (filter->type == DAMOS_FILTER_TYPE_MEMCG) {
2503			err = damon_sysfs_memcg_path_to_id(
2504					sysfs_filter->memcg_path,
2505					&filter->memcg_id);
2506			if (err) {
2507				damos_destroy_filter(filter);
2508				return err;
2509			}
2510		} else if (filter->type == DAMOS_FILTER_TYPE_ADDR) {
2511			if (sysfs_filter->addr_range.end <
2512					sysfs_filter->addr_range.start) {
2513				damos_destroy_filter(filter);
2514				return -EINVAL;
2515			}
2516			filter->addr_range = sysfs_filter->addr_range;
2517		} else if (filter->type == DAMOS_FILTER_TYPE_TARGET) {
2518			filter->target_idx = sysfs_filter->target_idx;
2519		} else if (filter->type == DAMOS_FILTER_TYPE_HUGEPAGE_SIZE) {
2520			if (sysfs_filter->sz_range.min >
2521					sysfs_filter->sz_range.max) {
2522				damos_destroy_filter(filter);
2523				return -EINVAL;
2524			}
2525			filter->sz_range = sysfs_filter->sz_range;
2526		}
2527
2528		damos_add_filter(scheme, filter);
2529	}
2530	return 0;
2531}
2532
2533static int damos_sysfs_add_quota_score(
2534		struct damos_sysfs_quota_goals *sysfs_goals,
2535		struct damos_quota *quota)
2536{
2537	struct damos_quota_goal *goal;
2538	int i, err;
2539
2540	for (i = 0; i < sysfs_goals->nr; i++) {
2541		struct damos_sysfs_quota_goal *sysfs_goal =
2542			sysfs_goals->goals_arr[i];
2543
2544		if (!sysfs_goal->target_value)
2545			continue;
2546
2547		goal = damos_new_quota_goal(sysfs_goal->metric,
2548				sysfs_goal->target_value);
2549		if (!goal)
2550			return -ENOMEM;
2551		switch (sysfs_goal->metric) {
2552		case DAMOS_QUOTA_USER_INPUT:
2553			goal->current_value = sysfs_goal->current_value;
2554			break;
2555		case DAMOS_QUOTA_NODE_MEM_USED_BP:
2556		case DAMOS_QUOTA_NODE_MEM_FREE_BP:
2557			goal->nid = sysfs_goal->nid;
2558			break;
2559		case DAMOS_QUOTA_NODE_MEMCG_USED_BP:
2560		case DAMOS_QUOTA_NODE_MEMCG_FREE_BP:
2561			err = damon_sysfs_memcg_path_to_id(
2562					sysfs_goal->path, &goal->memcg_id);
2563			if (err) {
2564				damos_destroy_quota_goal(goal);
2565				return err;
2566			}
2567			goal->nid = sysfs_goal->nid;
2568			break;
2569		default:
2570			break;
2571		}
2572		damos_add_quota_goal(quota, goal);
2573	}
2574	return 0;
2575}
2576
2577int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes,
2578		struct damon_ctx *ctx)
2579{
2580	struct damos *scheme;
2581	struct damos_quota quota = {};
2582	int i = 0;
2583
2584	INIT_LIST_HEAD(&quota.goals);
2585	damon_for_each_scheme(scheme, ctx) {
2586		struct damon_sysfs_scheme *sysfs_scheme;
2587		struct damos_quota_goal *g, *g_next;
2588		int err;
2589
2590		/* user could have removed the scheme sysfs dir */
2591		if (i >= sysfs_schemes->nr)
2592			break;
2593
2594		sysfs_scheme = sysfs_schemes->schemes_arr[i];
2595		err = damos_sysfs_add_quota_score(sysfs_scheme->quotas->goals,
2596				&quota);
2597		if (err) {
2598			damos_for_each_quota_goal_safe(g, g_next, &quota)
2599				damos_destroy_quota_goal(g);
2600			return err;
2601		}
2602		err = damos_commit_quota_goals(&scheme->quota, &quota);
2603		damos_for_each_quota_goal_safe(g, g_next, &quota)
2604			damos_destroy_quota_goal(g);
2605		if (err)
2606			return err;
2607		i++;
2608	}
2609	return 0;
2610}
2611
2612void damos_sysfs_update_effective_quotas(
2613		struct damon_sysfs_schemes *sysfs_schemes,
2614		struct damon_ctx *ctx)
2615{
2616	struct damos *scheme;
2617	int schemes_idx = 0;
2618
2619	damon_for_each_scheme(scheme, ctx) {
2620		struct damon_sysfs_quotas *sysfs_quotas;
2621
2622		/* user could have removed the scheme sysfs dir */
2623		if (schemes_idx >= sysfs_schemes->nr)
2624			break;
2625
2626		sysfs_quotas =
2627			sysfs_schemes->schemes_arr[schemes_idx++]->quotas;
2628		sysfs_quotas->effective_sz = scheme->quota.esz;
2629	}
2630}
2631
2632static int damos_sysfs_add_migrate_dest(struct damos *scheme,
2633		struct damos_sysfs_dests *sysfs_dests)
2634{
2635	struct damos_migrate_dests *dests = &scheme->migrate_dests;
2636	int i;
2637
2638	dests->node_id_arr = kmalloc_array(sysfs_dests->nr,
2639			sizeof(*dests->node_id_arr), GFP_KERNEL);
2640	if (!dests->node_id_arr)
2641		return -ENOMEM;
2642	dests->weight_arr = kmalloc_array(sysfs_dests->nr,
2643			sizeof(*dests->weight_arr), GFP_KERNEL);
2644	if (!dests->weight_arr)
2645		/* ->node_id_arr will be freed by scheme destruction */
2646		return -ENOMEM;
2647	for (i = 0; i < sysfs_dests->nr; i++) {
2648		dests->node_id_arr[i] = sysfs_dests->dests_arr[i]->id;
2649		dests->weight_arr[i] = sysfs_dests->dests_arr[i]->weight;
2650	}
2651	dests->nr_dests = sysfs_dests->nr;
2652	return 0;
2653}
2654
2655static struct damos *damon_sysfs_mk_scheme(
2656		struct damon_sysfs_scheme *sysfs_scheme)
2657{
2658	struct damon_sysfs_access_pattern *access_pattern =
2659		sysfs_scheme->access_pattern;
2660	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
2661	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
2662	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
2663	struct damos *scheme;
2664	int err;
2665
2666	struct damos_access_pattern pattern = {
2667		.min_sz_region = access_pattern->sz->min,
2668		.max_sz_region = access_pattern->sz->max,
2669		.min_nr_accesses = access_pattern->nr_accesses->min,
2670		.max_nr_accesses = access_pattern->nr_accesses->max,
2671		.min_age_region = access_pattern->age->min,
2672		.max_age_region = access_pattern->age->max,
2673	};
2674	struct damos_quota quota = {
2675		.ms = sysfs_quotas->ms,
2676		.sz = sysfs_quotas->sz,
2677		.reset_interval = sysfs_quotas->reset_interval_ms,
2678		.weight_sz = sysfs_weights->sz,
2679		.weight_nr_accesses = sysfs_weights->nr_accesses,
2680		.weight_age = sysfs_weights->age,
2681	};
2682	struct damos_watermarks wmarks = {
2683		.metric = sysfs_wmarks->metric,
2684		.interval = sysfs_wmarks->interval_us,
2685		.high = sysfs_wmarks->high,
2686		.mid = sysfs_wmarks->mid,
2687		.low = sysfs_wmarks->low,
2688	};
2689
2690	scheme = damon_new_scheme(&pattern, sysfs_scheme->action,
2691			sysfs_scheme->apply_interval_us, &quota, &wmarks,
2692			sysfs_scheme->target_nid);
2693	if (!scheme)
2694		return NULL;
2695
2696	err = damos_sysfs_add_quota_score(sysfs_quotas->goals, &scheme->quota);
2697	if (err) {
2698		damon_destroy_scheme(scheme);
2699		return NULL;
2700	}
2701
2702	err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->core_filters);
2703	if (err) {
2704		damon_destroy_scheme(scheme);
2705		return NULL;
2706	}
2707	err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->ops_filters);
2708	if (err) {
2709		damon_destroy_scheme(scheme);
2710		return NULL;
2711	}
2712	err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->filters);
2713	if (err) {
2714		damon_destroy_scheme(scheme);
2715		return NULL;
2716	}
2717	err = damos_sysfs_add_migrate_dest(scheme, sysfs_scheme->dests);
2718	if (err) {
2719		damon_destroy_scheme(scheme);
2720		return NULL;
2721	}
2722	return scheme;
2723}
2724
2725int damon_sysfs_add_schemes(struct damon_ctx *ctx,
2726		struct damon_sysfs_schemes *sysfs_schemes)
2727{
2728	int i;
2729
2730	for (i = 0; i < sysfs_schemes->nr; i++) {
2731		struct damos *scheme, *next;
2732
2733		scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
2734		if (!scheme) {
2735			damon_for_each_scheme_safe(scheme, next, ctx)
2736				damon_destroy_scheme(scheme);
2737			return -ENOMEM;
2738		}
2739		damon_add_scheme(ctx, scheme);
2740	}
2741	return 0;
2742}
2743
2744void damon_sysfs_schemes_update_stats(
2745		struct damon_sysfs_schemes *sysfs_schemes,
2746		struct damon_ctx *ctx)
2747{
2748	struct damos *scheme;
2749	int schemes_idx = 0;
2750
2751	damon_for_each_scheme(scheme, ctx) {
2752		struct damon_sysfs_stats *sysfs_stats;
2753
2754		/* user could have removed the scheme sysfs dir */
2755		if (schemes_idx >= sysfs_schemes->nr)
2756			break;
2757
2758		sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
2759		sysfs_stats->nr_tried = scheme->stat.nr_tried;
2760		sysfs_stats->sz_tried = scheme->stat.sz_tried;
2761		sysfs_stats->nr_applied = scheme->stat.nr_applied;
2762		sysfs_stats->sz_applied = scheme->stat.sz_applied;
2763		sysfs_stats->sz_ops_filter_passed =
2764			scheme->stat.sz_ops_filter_passed;
2765		sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
2766	}
2767}
2768
2769/**
2770 * damos_sysfs_populate_region_dir() - Populate a schemes tried region dir.
2771 * @sysfs_schemes:	Schemes directory to populate regions directory.
2772 * @ctx:		Corresponding DAMON context.
2773 * @t:			DAMON target of @r.
2774 * @r:			DAMON region to populate the directory for.
2775 * @s:			Corresponding scheme.
2776 * @total_bytes_only:	Whether the request is for bytes update only.
2777 * @sz_filter_passed:	Bytes of @r that passed filters of @s.
2778 *
2779 * Called from DAMOS walk callback while holding damon_sysfs_lock.
2780 */
2781void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes,
2782		struct damon_ctx *ctx, struct damon_target *t,
2783		struct damon_region *r, struct damos *s, bool total_bytes_only,
2784		unsigned long sz_filter_passed)
2785{
2786	struct damos *scheme;
2787	struct damon_sysfs_scheme_regions *sysfs_regions;
2788	struct damon_sysfs_scheme_region *region;
2789	int schemes_idx = 0;
2790
2791	damon_for_each_scheme(scheme, ctx) {
2792		if (scheme == s)
2793			break;
2794		schemes_idx++;
2795	}
2796
2797	/* user could have removed the scheme sysfs dir */
2798	if (schemes_idx >= sysfs_schemes->nr)
2799		return;
2800
2801	sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
2802	sysfs_regions->total_bytes += r->ar.end - r->ar.start;
2803	if (total_bytes_only)
2804		return;
2805
2806	region = damon_sysfs_scheme_region_alloc(r);
2807	if (!region)
2808		return;
2809	region->sz_filter_passed = sz_filter_passed;
2810	list_add_tail(&region->list, &sysfs_regions->regions_list);
2811	sysfs_regions->nr_regions++;
2812	if (kobject_init_and_add(&region->kobj,
2813				&damon_sysfs_scheme_region_ktype,
2814				&sysfs_regions->kobj, "%d",
2815				sysfs_regions->nr_regions++)) {
2816		kobject_put(&region->kobj);
2817	}
2818}
2819
2820int damon_sysfs_schemes_clear_regions(
2821		struct damon_sysfs_schemes *sysfs_schemes)
2822{
2823	int i;
2824
2825	for (i = 0; i < sysfs_schemes->nr; i++) {
2826		struct damon_sysfs_scheme *sysfs_scheme;
2827
2828		sysfs_scheme = sysfs_schemes->schemes_arr[i];
2829		damon_sysfs_scheme_regions_rm_dirs(
2830				sysfs_scheme->tried_regions);
2831		sysfs_scheme->tried_regions->total_bytes = 0;
2832	}
2833	return 0;
2834}
~/ Read-only file preview.