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