1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * DAMON Debugfs Interface 4 * 5 * Author: SeongJae Park <sjpark@amazon.de> 6 */ 7 8 #define pr_fmt(fmt) "damon-dbgfs: " fmt 9 10 #include <linux/damon.h> 11 #include <linux/debugfs.h> 12 #include <linux/file.h> 13 #include <linux/mm.h> 14 #include <linux/module.h> 15 #include <linux/page_idle.h> 16 #include <linux/slab.h> 17 18 static struct damon_ctx **dbgfs_ctxs; 19 static int dbgfs_nr_ctxs; 20 static struct dentry **dbgfs_dirs; 21 static DEFINE_MUTEX(damon_dbgfs_lock); 22 23 /* 24 * Returns non-empty string on success, negative error code otherwise. 25 */ 26 static char *user_input_str(const char __user *buf, size_t count, loff_t *ppos) 27 { 28 char *kbuf; 29 ssize_t ret; 30 31 /* We do not accept continuous write */ 32 if (*ppos) 33 return ERR_PTR(-EINVAL); 34 35 kbuf = kmalloc(count + 1, GFP_KERNEL | __GFP_NOWARN); 36 if (!kbuf) 37 return ERR_PTR(-ENOMEM); 38 39 ret = simple_write_to_buffer(kbuf, count + 1, ppos, buf, count); 40 if (ret != count) { 41 kfree(kbuf); 42 return ERR_PTR(-EIO); 43 } 44 kbuf[ret] = '\0'; 45 46 return kbuf; 47 } 48 49 static ssize_t dbgfs_attrs_read(struct file *file, 50 char __user *buf, size_t count, loff_t *ppos) 51 { 52 struct damon_ctx *ctx = file->private_data; 53 char kbuf[128]; 54 int ret; 55 56 mutex_lock(&ctx->kdamond_lock); 57 ret = scnprintf(kbuf, ARRAY_SIZE(kbuf), "%lu %lu %lu %lu %lu\n", 58 ctx->sample_interval, ctx->aggr_interval, 59 ctx->primitive_update_interval, ctx->min_nr_regions, 60 ctx->max_nr_regions); 61 mutex_unlock(&ctx->kdamond_lock); 62 63 return simple_read_from_buffer(buf, count, ppos, kbuf, ret); 64 } 65 66 static ssize_t dbgfs_attrs_write(struct file *file, 67 const char __user *buf, size_t count, loff_t *ppos) 68 { 69 struct damon_ctx *ctx = file->private_data; 70 unsigned long s, a, r, minr, maxr; 71 char *kbuf; 72 ssize_t ret; 73 74 kbuf = user_input_str(buf, count, ppos); 75 if (IS_ERR(kbuf)) 76 return PTR_ERR(kbuf); 77 78 if (sscanf(kbuf, "%lu %lu %lu %lu %lu", 79 &s, &a, &r, &minr, &maxr) != 5) { 80 ret = -EINVAL; 81 goto out; 82 } 83 84 mutex_lock(&ctx->kdamond_lock); 85 if (ctx->kdamond) { 86 ret = -EBUSY; 87 goto unlock_out; 88 } 89 90 ret = damon_set_attrs(ctx, s, a, r, minr, maxr); 91 if (!ret) 92 ret = count; 93 unlock_out: 94 mutex_unlock(&ctx->kdamond_lock); 95 out: 96 kfree(kbuf); 97 return ret; 98 } 99 100 static ssize_t sprint_schemes(struct damon_ctx *c, char *buf, ssize_t len) 101 { 102 struct damos *s; 103 int written = 0; 104 int rc; 105 106 damon_for_each_scheme(s, c) { 107 rc = scnprintf(&buf[written], len - written, 108 "%lu %lu %u %u %u %u %d %lu %lu %lu %u %u %u %d %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", 109 s->min_sz_region, s->max_sz_region, 110 s->min_nr_accesses, s->max_nr_accesses, 111 s->min_age_region, s->max_age_region, 112 s->action, 113 s->quota.ms, s->quota.sz, 114 s->quota.reset_interval, 115 s->quota.weight_sz, 116 s->quota.weight_nr_accesses, 117 s->quota.weight_age, 118 s->wmarks.metric, s->wmarks.interval, 119 s->wmarks.high, s->wmarks.mid, s->wmarks.low, 120 s->stat.nr_tried, s->stat.sz_tried, 121 s->stat.nr_applied, s->stat.sz_applied, 122 s->stat.qt_exceeds); 123 if (!rc) 124 return -ENOMEM; 125 126 written += rc; 127 } 128 return written; 129 } 130 131 static ssize_t dbgfs_schemes_read(struct file *file, char __user *buf, 132 size_t count, loff_t *ppos) 133 { 134 struct damon_ctx *ctx = file->private_data; 135 char *kbuf; 136 ssize_t len; 137 138 kbuf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN); 139 if (!kbuf) 140 return -ENOMEM; 141 142 mutex_lock(&ctx->kdamond_lock); 143 len = sprint_schemes(ctx, kbuf, count); 144 mutex_unlock(&ctx->kdamond_lock); 145 if (len < 0) 146 goto out; 147 len = simple_read_from_buffer(buf, count, ppos, kbuf, len); 148 149 out: 150 kfree(kbuf); 151 return len; 152 } 153 154 static void free_schemes_arr(struct damos **schemes, ssize_t nr_schemes) 155 { 156 ssize_t i; 157 158 for (i = 0; i < nr_schemes; i++) 159 kfree(schemes[i]); 160 kfree(schemes); 161 } 162 163 static bool damos_action_valid(int action) 164 { 165 switch (action) { 166 case DAMOS_WILLNEED: 167 case DAMOS_COLD: 168 case DAMOS_PAGEOUT: 169 case DAMOS_HUGEPAGE: 170 case DAMOS_NOHUGEPAGE: 171 case DAMOS_STAT: 172 return true; 173 default: 174 return false; 175 } 176 } 177 178 /* 179 * Converts a string into an array of struct damos pointers 180 * 181 * Returns an array of struct damos pointers that converted if the conversion 182 * success, or NULL otherwise. 183 */ 184 static struct damos **str_to_schemes(const char *str, ssize_t len, 185 ssize_t *nr_schemes) 186 { 187 struct damos *scheme, **schemes; 188 const int max_nr_schemes = 256; 189 int pos = 0, parsed, ret; 190 unsigned long min_sz, max_sz; 191 unsigned int min_nr_a, max_nr_a, min_age, max_age; 192 unsigned int action; 193 194 schemes = kmalloc_array(max_nr_schemes, sizeof(scheme), 195 GFP_KERNEL); 196 if (!schemes) 197 return NULL; 198 199 *nr_schemes = 0; 200 while (pos < len && *nr_schemes < max_nr_schemes) { 201 struct damos_quota quota = {}; 202 struct damos_watermarks wmarks; 203 204 ret = sscanf(&str[pos], 205 "%lu %lu %u %u %u %u %u %lu %lu %lu %u %u %u %u %lu %lu %lu %lu%n", 206 &min_sz, &max_sz, &min_nr_a, &max_nr_a, 207 &min_age, &max_age, &action, "a.ms, 208 "a.sz, "a.reset_interval, 209 "a.weight_sz, "a.weight_nr_accesses, 210 "a.weight_age, &wmarks.metric, 211 &wmarks.interval, &wmarks.high, &wmarks.mid, 212 &wmarks.low, &parsed); 213 if (ret != 18) 214 break; 215 if (!damos_action_valid(action)) 216 goto fail; 217 218 if (min_sz > max_sz || min_nr_a > max_nr_a || min_age > max_age) 219 goto fail; 220 221 if (wmarks.high < wmarks.mid || wmarks.high < wmarks.low || 222 wmarks.mid < wmarks.low) 223 goto fail; 224 225 pos += parsed; 226 scheme = damon_new_scheme(min_sz, max_sz, min_nr_a, max_nr_a, 227 min_age, max_age, action, "a, &wmarks); 228 if (!scheme) 229 goto fail; 230 231 schemes[*nr_schemes] = scheme; 232 *nr_schemes += 1; 233 } 234 return schemes; 235 fail: 236 free_schemes_arr(schemes, *nr_schemes); 237 return NULL; 238 } 239 240 static ssize_t dbgfs_schemes_write(struct file *file, const char __user *buf, 241 size_t count, loff_t *ppos) 242 { 243 struct damon_ctx *ctx = file->private_data; 244 char *kbuf; 245 struct damos **schemes; 246 ssize_t nr_schemes = 0, ret; 247 248 kbuf = user_input_str(buf, count, ppos); 249 if (IS_ERR(kbuf)) 250 return PTR_ERR(kbuf); 251 252 schemes = str_to_schemes(kbuf, count, &nr_schemes); 253 if (!schemes) { 254 ret = -EINVAL; 255 goto out; 256 } 257 258 mutex_lock(&ctx->kdamond_lock); 259 if (ctx->kdamond) { 260 ret = -EBUSY; 261 goto unlock_out; 262 } 263 264 ret = damon_set_schemes(ctx, schemes, nr_schemes); 265 if (!ret) { 266 ret = count; 267 nr_schemes = 0; 268 } 269 270 unlock_out: 271 mutex_unlock(&ctx->kdamond_lock); 272 free_schemes_arr(schemes, nr_schemes); 273 out: 274 kfree(kbuf); 275 return ret; 276 } 277 278 static inline bool targetid_is_pid(const struct damon_ctx *ctx) 279 { 280 return ctx->primitive.target_valid == damon_va_target_valid; 281 } 282 283 static ssize_t sprint_target_ids(struct damon_ctx *ctx, char *buf, ssize_t len) 284 { 285 struct damon_target *t; 286 unsigned long id; 287 int written = 0; 288 int rc; 289 290 damon_for_each_target(t, ctx) { 291 id = t->id; 292 if (targetid_is_pid(ctx)) 293 /* Show pid numbers to debugfs users */ 294 id = (unsigned long)pid_vnr((struct pid *)id); 295 296 rc = scnprintf(&buf[written], len - written, "%lu ", id); 297 if (!rc) 298 return -ENOMEM; 299 written += rc; 300 } 301 if (written) 302 written -= 1; 303 written += scnprintf(&buf[written], len - written, "\n"); 304 return written; 305 } 306 307 static ssize_t dbgfs_target_ids_read(struct file *file, 308 char __user *buf, size_t count, loff_t *ppos) 309 { 310 struct damon_ctx *ctx = file->private_data; 311 ssize_t len; 312 char ids_buf[320]; 313 314 mutex_lock(&ctx->kdamond_lock); 315 len = sprint_target_ids(ctx, ids_buf, 320); 316 mutex_unlock(&ctx->kdamond_lock); 317 if (len < 0) 318 return len; 319 320 return simple_read_from_buffer(buf, count, ppos, ids_buf, len); 321 } 322 323 /* 324 * Converts a string into an array of unsigned long integers 325 * 326 * Returns an array of unsigned long integers if the conversion success, or 327 * NULL otherwise. 328 */ 329 static unsigned long *str_to_target_ids(const char *str, ssize_t len, 330 ssize_t *nr_ids) 331 { 332 unsigned long *ids; 333 const int max_nr_ids = 32; 334 unsigned long id; 335 int pos = 0, parsed, ret; 336 337 *nr_ids = 0; 338 ids = kmalloc_array(max_nr_ids, sizeof(id), GFP_KERNEL); 339 if (!ids) 340 return NULL; 341 while (*nr_ids < max_nr_ids && pos < len) { 342 ret = sscanf(&str[pos], "%lu%n", &id, &parsed); 343 pos += parsed; 344 if (ret != 1) 345 break; 346 ids[*nr_ids] = id; 347 *nr_ids += 1; 348 } 349 350 return ids; 351 } 352 353 static void dbgfs_put_pids(unsigned long *ids, int nr_ids) 354 { 355 int i; 356 357 for (i = 0; i < nr_ids; i++) 358 put_pid((struct pid *)ids[i]); 359 } 360 361 /* 362 * dbgfs_set_targets() - Set monitoring targets. 363 * @ctx: monitoring context 364 * @ids: array of target ids 365 * @nr_ids: number of entries in @ids 366 * 367 * This function should not be called while the kdamond is running. 368 * 369 * Return: 0 on success, negative error code otherwise. 370 */ 371 static int dbgfs_set_targets(struct damon_ctx *ctx, 372 unsigned long *ids, ssize_t nr_ids) 373 { 374 ssize_t i; 375 struct damon_target *t, *next; 376 377 damon_for_each_target_safe(t, next, ctx) { 378 if (targetid_is_pid(ctx)) 379 put_pid((struct pid *)t->id); 380 damon_destroy_target(t); 381 } 382 383 for (i = 0; i < nr_ids; i++) { 384 t = damon_new_target(ids[i]); 385 if (!t) { 386 /* The caller should do cleanup of the ids itself */ 387 damon_for_each_target_safe(t, next, ctx) 388 damon_destroy_target(t); 389 if (targetid_is_pid(ctx)) 390 dbgfs_put_pids(ids, nr_ids); 391 return -ENOMEM; 392 } 393 damon_add_target(ctx, t); 394 } 395 396 return 0; 397 } 398 399 static ssize_t dbgfs_target_ids_write(struct file *file, 400 const char __user *buf, size_t count, loff_t *ppos) 401 { 402 struct damon_ctx *ctx = file->private_data; 403 bool id_is_pid = true; 404 char *kbuf; 405 unsigned long *targets; 406 ssize_t nr_targets; 407 ssize_t ret; 408 int i; 409 410 kbuf = user_input_str(buf, count, ppos); 411 if (IS_ERR(kbuf)) 412 return PTR_ERR(kbuf); 413 414 if (!strncmp(kbuf, "paddr\n", count)) { 415 id_is_pid = false; 416 /* target id is meaningless here, but we set it just for fun */ 417 scnprintf(kbuf, count, "42 "); 418 } 419 420 targets = str_to_target_ids(kbuf, count, &nr_targets); 421 if (!targets) { 422 ret = -ENOMEM; 423 goto out; 424 } 425 426 if (id_is_pid) { 427 for (i = 0; i < nr_targets; i++) { 428 targets[i] = (unsigned long)find_get_pid( 429 (int)targets[i]); 430 if (!targets[i]) { 431 dbgfs_put_pids(targets, i); 432 ret = -EINVAL; 433 goto free_targets_out; 434 } 435 } 436 } 437 438 mutex_lock(&ctx->kdamond_lock); 439 if (ctx->kdamond) { 440 if (id_is_pid) 441 dbgfs_put_pids(targets, nr_targets); 442 ret = -EBUSY; 443 goto unlock_out; 444 } 445 446 /* remove previously set targets */ 447 dbgfs_set_targets(ctx, NULL, 0); 448 449 /* Configure the context for the address space type */ 450 if (id_is_pid) 451 damon_va_set_primitives(ctx); 452 else 453 damon_pa_set_primitives(ctx); 454 455 ret = dbgfs_set_targets(ctx, targets, nr_targets); 456 if (!ret) 457 ret = count; 458 459 unlock_out: 460 mutex_unlock(&ctx->kdamond_lock); 461 free_targets_out: 462 kfree(targets); 463 out: 464 kfree(kbuf); 465 return ret; 466 } 467 468 static ssize_t sprint_init_regions(struct damon_ctx *c, char *buf, ssize_t len) 469 { 470 struct damon_target *t; 471 struct damon_region *r; 472 int target_idx = 0; 473 int written = 0; 474 int rc; 475 476 damon_for_each_target(t, c) { 477 damon_for_each_region(r, t) { 478 rc = scnprintf(&buf[written], len - written, 479 "%d %lu %lu\n", 480 target_idx, r->ar.start, r->ar.end); 481 if (!rc) 482 return -ENOMEM; 483 written += rc; 484 } 485 target_idx++; 486 } 487 return written; 488 } 489 490 static ssize_t dbgfs_init_regions_read(struct file *file, char __user *buf, 491 size_t count, loff_t *ppos) 492 { 493 struct damon_ctx *ctx = file->private_data; 494 char *kbuf; 495 ssize_t len; 496 497 kbuf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN); 498 if (!kbuf) 499 return -ENOMEM; 500 501 mutex_lock(&ctx->kdamond_lock); 502 if (ctx->kdamond) { 503 mutex_unlock(&ctx->kdamond_lock); 504 len = -EBUSY; 505 goto out; 506 } 507 508 len = sprint_init_regions(ctx, kbuf, count); 509 mutex_unlock(&ctx->kdamond_lock); 510 if (len < 0) 511 goto out; 512 len = simple_read_from_buffer(buf, count, ppos, kbuf, len); 513 514 out: 515 kfree(kbuf); 516 return len; 517 } 518 519 static int add_init_region(struct damon_ctx *c, int target_idx, 520 struct damon_addr_range *ar) 521 { 522 struct damon_target *t; 523 struct damon_region *r, *prev; 524 unsigned long idx = 0; 525 int rc = -EINVAL; 526 527 if (ar->start >= ar->end) 528 return -EINVAL; 529 530 damon_for_each_target(t, c) { 531 if (idx++ == target_idx) { 532 r = damon_new_region(ar->start, ar->end); 533 if (!r) 534 return -ENOMEM; 535 damon_add_region(r, t); 536 if (damon_nr_regions(t) > 1) { 537 prev = damon_prev_region(r); 538 if (prev->ar.end > r->ar.start) { 539 damon_destroy_region(r, t); 540 return -EINVAL; 541 } 542 } 543 rc = 0; 544 } 545 } 546 return rc; 547 } 548 549 static int set_init_regions(struct damon_ctx *c, const char *str, ssize_t len) 550 { 551 struct damon_target *t; 552 struct damon_region *r, *next; 553 int pos = 0, parsed, ret; 554 int target_idx; 555 struct damon_addr_range ar; 556 int err; 557 558 damon_for_each_target(t, c) { 559 damon_for_each_region_safe(r, next, t) 560 damon_destroy_region(r, t); 561 } 562 563 while (pos < len) { 564 ret = sscanf(&str[pos], "%d %lu %lu%n", 565 &target_idx, &ar.start, &ar.end, &parsed); 566 if (ret != 3) 567 break; 568 err = add_init_region(c, target_idx, &ar); 569 if (err) 570 goto fail; 571 pos += parsed; 572 } 573 574 return 0; 575 576 fail: 577 damon_for_each_target(t, c) { 578 damon_for_each_region_safe(r, next, t) 579 damon_destroy_region(r, t); 580 } 581 return err; 582 } 583 584 static ssize_t dbgfs_init_regions_write(struct file *file, 585 const char __user *buf, size_t count, 586 loff_t *ppos) 587 { 588 struct damon_ctx *ctx = file->private_data; 589 char *kbuf; 590 ssize_t ret = count; 591 int err; 592 593 kbuf = user_input_str(buf, count, ppos); 594 if (IS_ERR(kbuf)) 595 return PTR_ERR(kbuf); 596 597 mutex_lock(&ctx->kdamond_lock); 598 if (ctx->kdamond) { 599 ret = -EBUSY; 600 goto unlock_out; 601 } 602 603 err = set_init_regions(ctx, kbuf, ret); 604 if (err) 605 ret = err; 606 607 unlock_out: 608 mutex_unlock(&ctx->kdamond_lock); 609 kfree(kbuf); 610 return ret; 611 } 612 613 static ssize_t dbgfs_kdamond_pid_read(struct file *file, 614 char __user *buf, size_t count, loff_t *ppos) 615 { 616 struct damon_ctx *ctx = file->private_data; 617 char *kbuf; 618 ssize_t len; 619 620 kbuf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN); 621 if (!kbuf) 622 return -ENOMEM; 623 624 mutex_lock(&ctx->kdamond_lock); 625 if (ctx->kdamond) 626 len = scnprintf(kbuf, count, "%d\n", ctx->kdamond->pid); 627 else 628 len = scnprintf(kbuf, count, "none\n"); 629 mutex_unlock(&ctx->kdamond_lock); 630 if (!len) 631 goto out; 632 len = simple_read_from_buffer(buf, count, ppos, kbuf, len); 633 634 out: 635 kfree(kbuf); 636 return len; 637 } 638 639 static int damon_dbgfs_open(struct inode *inode, struct file *file) 640 { 641 file->private_data = inode->i_private; 642 643 return nonseekable_open(inode, file); 644 } 645 646 static const struct file_operations attrs_fops = { 647 .open = damon_dbgfs_open, 648 .read = dbgfs_attrs_read, 649 .write = dbgfs_attrs_write, 650 }; 651 652 static const struct file_operations schemes_fops = { 653 .open = damon_dbgfs_open, 654 .read = dbgfs_schemes_read, 655 .write = dbgfs_schemes_write, 656 }; 657 658 static const struct file_operations target_ids_fops = { 659 .open = damon_dbgfs_open, 660 .read = dbgfs_target_ids_read, 661 .write = dbgfs_target_ids_write, 662 }; 663 664 static const struct file_operations init_regions_fops = { 665 .open = damon_dbgfs_open, 666 .read = dbgfs_init_regions_read, 667 .write = dbgfs_init_regions_write, 668 }; 669 670 static const struct file_operations kdamond_pid_fops = { 671 .open = damon_dbgfs_open, 672 .read = dbgfs_kdamond_pid_read, 673 }; 674 675 static void dbgfs_fill_ctx_dir(struct dentry *dir, struct damon_ctx *ctx) 676 { 677 const char * const file_names[] = {"attrs", "schemes", "target_ids", 678 "init_regions", "kdamond_pid"}; 679 const struct file_operations *fops[] = {&attrs_fops, &schemes_fops, 680 &target_ids_fops, &init_regions_fops, &kdamond_pid_fops}; 681 int i; 682 683 for (i = 0; i < ARRAY_SIZE(file_names); i++) 684 debugfs_create_file(file_names[i], 0600, dir, ctx, fops[i]); 685 } 686 687 static void dbgfs_before_terminate(struct damon_ctx *ctx) 688 { 689 struct damon_target *t, *next; 690 691 if (!targetid_is_pid(ctx)) 692 return; 693 694 mutex_lock(&ctx->kdamond_lock); 695 damon_for_each_target_safe(t, next, ctx) { 696 put_pid((struct pid *)t->id); 697 damon_destroy_target(t); 698 } 699 mutex_unlock(&ctx->kdamond_lock); 700 } 701 702 static struct damon_ctx *dbgfs_new_ctx(void) 703 { 704 struct damon_ctx *ctx; 705 706 ctx = damon_new_ctx(); 707 if (!ctx) 708 return NULL; 709 710 damon_va_set_primitives(ctx); 711 ctx->callback.before_terminate = dbgfs_before_terminate; 712 return ctx; 713 } 714 715 static void dbgfs_destroy_ctx(struct damon_ctx *ctx) 716 { 717 damon_destroy_ctx(ctx); 718 } 719 720 /* 721 * Make a context of @name and create a debugfs directory for it. 722 * 723 * This function should be called while holding damon_dbgfs_lock. 724 * 725 * Returns 0 on success, negative error code otherwise. 726 */ 727 static int dbgfs_mk_context(char *name) 728 { 729 struct dentry *root, **new_dirs, *new_dir; 730 struct damon_ctx **new_ctxs, *new_ctx; 731 732 if (damon_nr_running_ctxs()) 733 return -EBUSY; 734 735 new_ctxs = krealloc(dbgfs_ctxs, sizeof(*dbgfs_ctxs) * 736 (dbgfs_nr_ctxs + 1), GFP_KERNEL); 737 if (!new_ctxs) 738 return -ENOMEM; 739 dbgfs_ctxs = new_ctxs; 740 741 new_dirs = krealloc(dbgfs_dirs, sizeof(*dbgfs_dirs) * 742 (dbgfs_nr_ctxs + 1), GFP_KERNEL); 743 if (!new_dirs) 744 return -ENOMEM; 745 dbgfs_dirs = new_dirs; 746 747 root = dbgfs_dirs[0]; 748 if (!root) 749 return -ENOENT; 750 751 new_dir = debugfs_create_dir(name, root); 752 dbgfs_dirs[dbgfs_nr_ctxs] = new_dir; 753 754 new_ctx = dbgfs_new_ctx(); 755 if (!new_ctx) { 756 debugfs_remove(new_dir); 757 dbgfs_dirs[dbgfs_nr_ctxs] = NULL; 758 return -ENOMEM; 759 } 760 761 dbgfs_ctxs[dbgfs_nr_ctxs] = new_ctx; 762 dbgfs_fill_ctx_dir(dbgfs_dirs[dbgfs_nr_ctxs], 763 dbgfs_ctxs[dbgfs_nr_ctxs]); 764 dbgfs_nr_ctxs++; 765 766 return 0; 767 } 768 769 static ssize_t dbgfs_mk_context_write(struct file *file, 770 const char __user *buf, size_t count, loff_t *ppos) 771 { 772 char *kbuf; 773 char *ctx_name; 774 ssize_t ret; 775 776 kbuf = user_input_str(buf, count, ppos); 777 if (IS_ERR(kbuf)) 778 return PTR_ERR(kbuf); 779 ctx_name = kmalloc(count + 1, GFP_KERNEL); 780 if (!ctx_name) { 781 kfree(kbuf); 782 return -ENOMEM; 783 } 784 785 /* Trim white space */ 786 if (sscanf(kbuf, "%s", ctx_name) != 1) { 787 ret = -EINVAL; 788 goto out; 789 } 790 791 mutex_lock(&damon_dbgfs_lock); 792 ret = dbgfs_mk_context(ctx_name); 793 if (!ret) 794 ret = count; 795 mutex_unlock(&damon_dbgfs_lock); 796 797 out: 798 kfree(kbuf); 799 kfree(ctx_name); 800 return ret; 801 } 802 803 /* 804 * Remove a context of @name and its debugfs directory. 805 * 806 * This function should be called while holding damon_dbgfs_lock. 807 * 808 * Return 0 on success, negative error code otherwise. 809 */ 810 static int dbgfs_rm_context(char *name) 811 { 812 struct dentry *root, *dir, **new_dirs; 813 struct damon_ctx **new_ctxs; 814 int i, j; 815 816 if (damon_nr_running_ctxs()) 817 return -EBUSY; 818 819 root = dbgfs_dirs[0]; 820 if (!root) 821 return -ENOENT; 822 823 dir = debugfs_lookup(name, root); 824 if (!dir) 825 return -ENOENT; 826 827 new_dirs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_dirs), 828 GFP_KERNEL); 829 if (!new_dirs) 830 return -ENOMEM; 831 832 new_ctxs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_ctxs), 833 GFP_KERNEL); 834 if (!new_ctxs) { 835 kfree(new_dirs); 836 return -ENOMEM; 837 } 838 839 for (i = 0, j = 0; i < dbgfs_nr_ctxs; i++) { 840 if (dbgfs_dirs[i] == dir) { 841 debugfs_remove(dbgfs_dirs[i]); 842 dbgfs_destroy_ctx(dbgfs_ctxs[i]); 843 continue; 844 } 845 new_dirs[j] = dbgfs_dirs[i]; 846 new_ctxs[j++] = dbgfs_ctxs[i]; 847 } 848 849 kfree(dbgfs_dirs); 850 kfree(dbgfs_ctxs); 851 852 dbgfs_dirs = new_dirs; 853 dbgfs_ctxs = new_ctxs; 854 dbgfs_nr_ctxs--; 855 856 return 0; 857 } 858 859 static ssize_t dbgfs_rm_context_write(struct file *file, 860 const char __user *buf, size_t count, loff_t *ppos) 861 { 862 char *kbuf; 863 ssize_t ret; 864 char *ctx_name; 865 866 kbuf = user_input_str(buf, count, ppos); 867 if (IS_ERR(kbuf)) 868 return PTR_ERR(kbuf); 869 ctx_name = kmalloc(count + 1, GFP_KERNEL); 870 if (!ctx_name) { 871 kfree(kbuf); 872 return -ENOMEM; 873 } 874 875 /* Trim white space */ 876 if (sscanf(kbuf, "%s", ctx_name) != 1) { 877 ret = -EINVAL; 878 goto out; 879 } 880 881 mutex_lock(&damon_dbgfs_lock); 882 ret = dbgfs_rm_context(ctx_name); 883 if (!ret) 884 ret = count; 885 mutex_unlock(&damon_dbgfs_lock); 886 887 out: 888 kfree(kbuf); 889 kfree(ctx_name); 890 return ret; 891 } 892 893 static ssize_t dbgfs_monitor_on_read(struct file *file, 894 char __user *buf, size_t count, loff_t *ppos) 895 { 896 char monitor_on_buf[5]; 897 bool monitor_on = damon_nr_running_ctxs() != 0; 898 int len; 899 900 len = scnprintf(monitor_on_buf, 5, monitor_on ? "on\n" : "off\n"); 901 902 return simple_read_from_buffer(buf, count, ppos, monitor_on_buf, len); 903 } 904 905 static ssize_t dbgfs_monitor_on_write(struct file *file, 906 const char __user *buf, size_t count, loff_t *ppos) 907 { 908 ssize_t ret; 909 char *kbuf; 910 911 kbuf = user_input_str(buf, count, ppos); 912 if (IS_ERR(kbuf)) 913 return PTR_ERR(kbuf); 914 915 /* Remove white space */ 916 if (sscanf(kbuf, "%s", kbuf) != 1) { 917 kfree(kbuf); 918 return -EINVAL; 919 } 920 921 mutex_lock(&damon_dbgfs_lock); 922 if (!strncmp(kbuf, "on", count)) { 923 int i; 924 925 for (i = 0; i < dbgfs_nr_ctxs; i++) { 926 if (damon_targets_empty(dbgfs_ctxs[i])) { 927 kfree(kbuf); 928 mutex_unlock(&damon_dbgfs_lock); 929 return -EINVAL; 930 } 931 } 932 ret = damon_start(dbgfs_ctxs, dbgfs_nr_ctxs); 933 } else if (!strncmp(kbuf, "off", count)) { 934 ret = damon_stop(dbgfs_ctxs, dbgfs_nr_ctxs); 935 } else { 936 ret = -EINVAL; 937 } 938 mutex_unlock(&damon_dbgfs_lock); 939 940 if (!ret) 941 ret = count; 942 kfree(kbuf); 943 return ret; 944 } 945 946 static const struct file_operations mk_contexts_fops = { 947 .write = dbgfs_mk_context_write, 948 }; 949 950 static const struct file_operations rm_contexts_fops = { 951 .write = dbgfs_rm_context_write, 952 }; 953 954 static const struct file_operations monitor_on_fops = { 955 .read = dbgfs_monitor_on_read, 956 .write = dbgfs_monitor_on_write, 957 }; 958 959 static int __init __damon_dbgfs_init(void) 960 { 961 struct dentry *dbgfs_root; 962 const char * const file_names[] = {"mk_contexts", "rm_contexts", 963 "monitor_on"}; 964 const struct file_operations *fops[] = {&mk_contexts_fops, 965 &rm_contexts_fops, &monitor_on_fops}; 966 int i; 967 968 dbgfs_root = debugfs_create_dir("damon", NULL); 969 970 for (i = 0; i < ARRAY_SIZE(file_names); i++) 971 debugfs_create_file(file_names[i], 0600, dbgfs_root, NULL, 972 fops[i]); 973 dbgfs_fill_ctx_dir(dbgfs_root, dbgfs_ctxs[0]); 974 975 dbgfs_dirs = kmalloc_array(1, sizeof(dbgfs_root), GFP_KERNEL); 976 if (!dbgfs_dirs) { 977 debugfs_remove(dbgfs_root); 978 return -ENOMEM; 979 } 980 dbgfs_dirs[0] = dbgfs_root; 981 982 return 0; 983 } 984 985 /* 986 * Functions for the initialization 987 */ 988 989 static int __init damon_dbgfs_init(void) 990 { 991 int rc = -ENOMEM; 992 993 mutex_lock(&damon_dbgfs_lock); 994 dbgfs_ctxs = kmalloc(sizeof(*dbgfs_ctxs), GFP_KERNEL); 995 if (!dbgfs_ctxs) 996 goto out; 997 dbgfs_ctxs[0] = dbgfs_new_ctx(); 998 if (!dbgfs_ctxs[0]) { 999 kfree(dbgfs_ctxs); 1000 goto out; 1001 } 1002 dbgfs_nr_ctxs = 1; 1003 1004 rc = __damon_dbgfs_init(); 1005 if (rc) { 1006 kfree(dbgfs_ctxs[0]); 1007 kfree(dbgfs_ctxs); 1008 pr_err("%s: dbgfs init failed\n", __func__); 1009 } 1010 1011 out: 1012 mutex_unlock(&damon_dbgfs_lock); 1013 return rc; 1014 } 1015 1016 module_init(damon_dbgfs_init); 1017 1018 #include "dbgfs-test.h" 1019