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