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