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); 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 = count; 73 int err; 74 75 kbuf = user_input_str(buf, count, ppos); 76 if (IS_ERR(kbuf)) 77 return PTR_ERR(kbuf); 78 79 if (sscanf(kbuf, "%lu %lu %lu %lu %lu", 80 &s, &a, &r, &minr, &maxr) != 5) { 81 ret = -EINVAL; 82 goto out; 83 } 84 85 mutex_lock(&ctx->kdamond_lock); 86 if (ctx->kdamond) { 87 ret = -EBUSY; 88 goto unlock_out; 89 } 90 91 err = damon_set_attrs(ctx, s, a, r, minr, maxr); 92 if (err) 93 ret = err; 94 unlock_out: 95 mutex_unlock(&ctx->kdamond_lock); 96 out: 97 kfree(kbuf); 98 return ret; 99 } 100 101 static ssize_t sprint_schemes(struct damon_ctx *c, char *buf, ssize_t len) 102 { 103 struct damos *s; 104 int written = 0; 105 int rc; 106 107 damon_for_each_scheme(s, c) { 108 rc = scnprintf(&buf[written], len - written, 109 "%lu %lu %u %u %u %u %d %lu %lu\n", 110 s->min_sz_region, s->max_sz_region, 111 s->min_nr_accesses, s->max_nr_accesses, 112 s->min_age_region, s->max_age_region, 113 s->action, s->stat_count, s->stat_sz); 114 if (!rc) 115 return -ENOMEM; 116 117 written += rc; 118 } 119 return written; 120 } 121 122 static ssize_t dbgfs_schemes_read(struct file *file, char __user *buf, 123 size_t count, loff_t *ppos) 124 { 125 struct damon_ctx *ctx = file->private_data; 126 char *kbuf; 127 ssize_t len; 128 129 kbuf = kmalloc(count, GFP_KERNEL); 130 if (!kbuf) 131 return -ENOMEM; 132 133 mutex_lock(&ctx->kdamond_lock); 134 len = sprint_schemes(ctx, kbuf, count); 135 mutex_unlock(&ctx->kdamond_lock); 136 if (len < 0) 137 goto out; 138 len = simple_read_from_buffer(buf, count, ppos, kbuf, len); 139 140 out: 141 kfree(kbuf); 142 return len; 143 } 144 145 static void free_schemes_arr(struct damos **schemes, ssize_t nr_schemes) 146 { 147 ssize_t i; 148 149 for (i = 0; i < nr_schemes; i++) 150 kfree(schemes[i]); 151 kfree(schemes); 152 } 153 154 static bool damos_action_valid(int action) 155 { 156 switch (action) { 157 case DAMOS_WILLNEED: 158 case DAMOS_COLD: 159 case DAMOS_PAGEOUT: 160 case DAMOS_HUGEPAGE: 161 case DAMOS_NOHUGEPAGE: 162 case DAMOS_STAT: 163 return true; 164 default: 165 return false; 166 } 167 } 168 169 /* 170 * Converts a string into an array of struct damos pointers 171 * 172 * Returns an array of struct damos pointers that converted if the conversion 173 * success, or NULL otherwise. 174 */ 175 static struct damos **str_to_schemes(const char *str, ssize_t len, 176 ssize_t *nr_schemes) 177 { 178 struct damos *scheme, **schemes; 179 const int max_nr_schemes = 256; 180 int pos = 0, parsed, ret; 181 unsigned long min_sz, max_sz; 182 unsigned int min_nr_a, max_nr_a, min_age, max_age; 183 unsigned int action; 184 185 schemes = kmalloc_array(max_nr_schemes, sizeof(scheme), 186 GFP_KERNEL); 187 if (!schemes) 188 return NULL; 189 190 *nr_schemes = 0; 191 while (pos < len && *nr_schemes < max_nr_schemes) { 192 ret = sscanf(&str[pos], "%lu %lu %u %u %u %u %u%n", 193 &min_sz, &max_sz, &min_nr_a, &max_nr_a, 194 &min_age, &max_age, &action, &parsed); 195 if (ret != 7) 196 break; 197 if (!damos_action_valid(action)) { 198 pr_err("wrong action %d\n", action); 199 goto fail; 200 } 201 202 pos += parsed; 203 scheme = damon_new_scheme(min_sz, max_sz, min_nr_a, max_nr_a, 204 min_age, max_age, action); 205 if (!scheme) 206 goto fail; 207 208 schemes[*nr_schemes] = scheme; 209 *nr_schemes += 1; 210 } 211 return schemes; 212 fail: 213 free_schemes_arr(schemes, *nr_schemes); 214 return NULL; 215 } 216 217 static ssize_t dbgfs_schemes_write(struct file *file, const char __user *buf, 218 size_t count, loff_t *ppos) 219 { 220 struct damon_ctx *ctx = file->private_data; 221 char *kbuf; 222 struct damos **schemes; 223 ssize_t nr_schemes = 0, ret = count; 224 int err; 225 226 kbuf = user_input_str(buf, count, ppos); 227 if (IS_ERR(kbuf)) 228 return PTR_ERR(kbuf); 229 230 schemes = str_to_schemes(kbuf, ret, &nr_schemes); 231 if (!schemes) { 232 ret = -EINVAL; 233 goto out; 234 } 235 236 mutex_lock(&ctx->kdamond_lock); 237 if (ctx->kdamond) { 238 ret = -EBUSY; 239 goto unlock_out; 240 } 241 242 err = damon_set_schemes(ctx, schemes, nr_schemes); 243 if (err) 244 ret = err; 245 else 246 nr_schemes = 0; 247 unlock_out: 248 mutex_unlock(&ctx->kdamond_lock); 249 free_schemes_arr(schemes, nr_schemes); 250 out: 251 kfree(kbuf); 252 return ret; 253 } 254 255 static inline bool targetid_is_pid(const struct damon_ctx *ctx) 256 { 257 return ctx->primitive.target_valid == damon_va_target_valid; 258 } 259 260 static ssize_t sprint_target_ids(struct damon_ctx *ctx, char *buf, ssize_t len) 261 { 262 struct damon_target *t; 263 unsigned long id; 264 int written = 0; 265 int rc; 266 267 damon_for_each_target(t, ctx) { 268 id = t->id; 269 if (targetid_is_pid(ctx)) 270 /* Show pid numbers to debugfs users */ 271 id = (unsigned long)pid_vnr((struct pid *)id); 272 273 rc = scnprintf(&buf[written], len - written, "%lu ", id); 274 if (!rc) 275 return -ENOMEM; 276 written += rc; 277 } 278 if (written) 279 written -= 1; 280 written += scnprintf(&buf[written], len - written, "\n"); 281 return written; 282 } 283 284 static ssize_t dbgfs_target_ids_read(struct file *file, 285 char __user *buf, size_t count, loff_t *ppos) 286 { 287 struct damon_ctx *ctx = file->private_data; 288 ssize_t len; 289 char ids_buf[320]; 290 291 mutex_lock(&ctx->kdamond_lock); 292 len = sprint_target_ids(ctx, ids_buf, 320); 293 mutex_unlock(&ctx->kdamond_lock); 294 if (len < 0) 295 return len; 296 297 return simple_read_from_buffer(buf, count, ppos, ids_buf, len); 298 } 299 300 /* 301 * Converts a string into an array of unsigned long integers 302 * 303 * Returns an array of unsigned long integers if the conversion success, or 304 * NULL otherwise. 305 */ 306 static unsigned long *str_to_target_ids(const char *str, ssize_t len, 307 ssize_t *nr_ids) 308 { 309 unsigned long *ids; 310 const int max_nr_ids = 32; 311 unsigned long id; 312 int pos = 0, parsed, ret; 313 314 *nr_ids = 0; 315 ids = kmalloc_array(max_nr_ids, sizeof(id), GFP_KERNEL); 316 if (!ids) 317 return NULL; 318 while (*nr_ids < max_nr_ids && pos < len) { 319 ret = sscanf(&str[pos], "%lu%n", &id, &parsed); 320 pos += parsed; 321 if (ret != 1) 322 break; 323 ids[*nr_ids] = id; 324 *nr_ids += 1; 325 } 326 327 return ids; 328 } 329 330 static void dbgfs_put_pids(unsigned long *ids, int nr_ids) 331 { 332 int i; 333 334 for (i = 0; i < nr_ids; i++) 335 put_pid((struct pid *)ids[i]); 336 } 337 338 static ssize_t dbgfs_target_ids_write(struct file *file, 339 const char __user *buf, size_t count, loff_t *ppos) 340 { 341 struct damon_ctx *ctx = file->private_data; 342 char *kbuf, *nrs; 343 unsigned long *targets; 344 ssize_t nr_targets; 345 ssize_t ret = count; 346 int i; 347 int err; 348 349 kbuf = user_input_str(buf, count, ppos); 350 if (IS_ERR(kbuf)) 351 return PTR_ERR(kbuf); 352 353 nrs = kbuf; 354 355 targets = str_to_target_ids(nrs, ret, &nr_targets); 356 if (!targets) { 357 ret = -ENOMEM; 358 goto out; 359 } 360 361 if (targetid_is_pid(ctx)) { 362 for (i = 0; i < nr_targets; i++) { 363 targets[i] = (unsigned long)find_get_pid( 364 (int)targets[i]); 365 if (!targets[i]) { 366 dbgfs_put_pids(targets, i); 367 ret = -EINVAL; 368 goto free_targets_out; 369 } 370 } 371 } 372 373 mutex_lock(&ctx->kdamond_lock); 374 if (ctx->kdamond) { 375 if (targetid_is_pid(ctx)) 376 dbgfs_put_pids(targets, nr_targets); 377 ret = -EBUSY; 378 goto unlock_out; 379 } 380 381 err = damon_set_targets(ctx, targets, nr_targets); 382 if (err) { 383 if (targetid_is_pid(ctx)) 384 dbgfs_put_pids(targets, nr_targets); 385 ret = err; 386 } 387 388 unlock_out: 389 mutex_unlock(&ctx->kdamond_lock); 390 free_targets_out: 391 kfree(targets); 392 out: 393 kfree(kbuf); 394 return ret; 395 } 396 397 static ssize_t dbgfs_kdamond_pid_read(struct file *file, 398 char __user *buf, size_t count, loff_t *ppos) 399 { 400 struct damon_ctx *ctx = file->private_data; 401 char *kbuf; 402 ssize_t len; 403 404 kbuf = kmalloc(count, GFP_KERNEL); 405 if (!kbuf) 406 return -ENOMEM; 407 408 mutex_lock(&ctx->kdamond_lock); 409 if (ctx->kdamond) 410 len = scnprintf(kbuf, count, "%d\n", ctx->kdamond->pid); 411 else 412 len = scnprintf(kbuf, count, "none\n"); 413 mutex_unlock(&ctx->kdamond_lock); 414 if (!len) 415 goto out; 416 len = simple_read_from_buffer(buf, count, ppos, kbuf, len); 417 418 out: 419 kfree(kbuf); 420 return len; 421 } 422 423 static int damon_dbgfs_open(struct inode *inode, struct file *file) 424 { 425 file->private_data = inode->i_private; 426 427 return nonseekable_open(inode, file); 428 } 429 430 static const struct file_operations attrs_fops = { 431 .open = damon_dbgfs_open, 432 .read = dbgfs_attrs_read, 433 .write = dbgfs_attrs_write, 434 }; 435 436 static const struct file_operations schemes_fops = { 437 .open = damon_dbgfs_open, 438 .read = dbgfs_schemes_read, 439 .write = dbgfs_schemes_write, 440 }; 441 442 static const struct file_operations target_ids_fops = { 443 .open = damon_dbgfs_open, 444 .read = dbgfs_target_ids_read, 445 .write = dbgfs_target_ids_write, 446 }; 447 448 static const struct file_operations kdamond_pid_fops = { 449 .open = damon_dbgfs_open, 450 .read = dbgfs_kdamond_pid_read, 451 }; 452 453 static void dbgfs_fill_ctx_dir(struct dentry *dir, struct damon_ctx *ctx) 454 { 455 const char * const file_names[] = {"attrs", "schemes", "target_ids", 456 "kdamond_pid"}; 457 const struct file_operations *fops[] = {&attrs_fops, &schemes_fops, 458 &target_ids_fops, &kdamond_pid_fops}; 459 int i; 460 461 for (i = 0; i < ARRAY_SIZE(file_names); i++) 462 debugfs_create_file(file_names[i], 0600, dir, ctx, fops[i]); 463 } 464 465 static int dbgfs_before_terminate(struct damon_ctx *ctx) 466 { 467 struct damon_target *t, *next; 468 469 if (!targetid_is_pid(ctx)) 470 return 0; 471 472 damon_for_each_target_safe(t, next, ctx) { 473 put_pid((struct pid *)t->id); 474 damon_destroy_target(t); 475 } 476 return 0; 477 } 478 479 static struct damon_ctx *dbgfs_new_ctx(void) 480 { 481 struct damon_ctx *ctx; 482 483 ctx = damon_new_ctx(); 484 if (!ctx) 485 return NULL; 486 487 damon_va_set_primitives(ctx); 488 ctx->callback.before_terminate = dbgfs_before_terminate; 489 return ctx; 490 } 491 492 static void dbgfs_destroy_ctx(struct damon_ctx *ctx) 493 { 494 damon_destroy_ctx(ctx); 495 } 496 497 /* 498 * Make a context of @name and create a debugfs directory for it. 499 * 500 * This function should be called while holding damon_dbgfs_lock. 501 * 502 * Returns 0 on success, negative error code otherwise. 503 */ 504 static int dbgfs_mk_context(char *name) 505 { 506 struct dentry *root, **new_dirs, *new_dir; 507 struct damon_ctx **new_ctxs, *new_ctx; 508 509 if (damon_nr_running_ctxs()) 510 return -EBUSY; 511 512 new_ctxs = krealloc(dbgfs_ctxs, sizeof(*dbgfs_ctxs) * 513 (dbgfs_nr_ctxs + 1), GFP_KERNEL); 514 if (!new_ctxs) 515 return -ENOMEM; 516 dbgfs_ctxs = new_ctxs; 517 518 new_dirs = krealloc(dbgfs_dirs, sizeof(*dbgfs_dirs) * 519 (dbgfs_nr_ctxs + 1), GFP_KERNEL); 520 if (!new_dirs) 521 return -ENOMEM; 522 dbgfs_dirs = new_dirs; 523 524 root = dbgfs_dirs[0]; 525 if (!root) 526 return -ENOENT; 527 528 new_dir = debugfs_create_dir(name, root); 529 dbgfs_dirs[dbgfs_nr_ctxs] = new_dir; 530 531 new_ctx = dbgfs_new_ctx(); 532 if (!new_ctx) { 533 debugfs_remove(new_dir); 534 dbgfs_dirs[dbgfs_nr_ctxs] = NULL; 535 return -ENOMEM; 536 } 537 538 dbgfs_ctxs[dbgfs_nr_ctxs] = new_ctx; 539 dbgfs_fill_ctx_dir(dbgfs_dirs[dbgfs_nr_ctxs], 540 dbgfs_ctxs[dbgfs_nr_ctxs]); 541 dbgfs_nr_ctxs++; 542 543 return 0; 544 } 545 546 static ssize_t dbgfs_mk_context_write(struct file *file, 547 const char __user *buf, size_t count, loff_t *ppos) 548 { 549 char *kbuf; 550 char *ctx_name; 551 ssize_t ret = count; 552 int err; 553 554 kbuf = user_input_str(buf, count, ppos); 555 if (IS_ERR(kbuf)) 556 return PTR_ERR(kbuf); 557 ctx_name = kmalloc(count + 1, GFP_KERNEL); 558 if (!ctx_name) { 559 kfree(kbuf); 560 return -ENOMEM; 561 } 562 563 /* Trim white space */ 564 if (sscanf(kbuf, "%s", ctx_name) != 1) { 565 ret = -EINVAL; 566 goto out; 567 } 568 569 mutex_lock(&damon_dbgfs_lock); 570 err = dbgfs_mk_context(ctx_name); 571 if (err) 572 ret = err; 573 mutex_unlock(&damon_dbgfs_lock); 574 575 out: 576 kfree(kbuf); 577 kfree(ctx_name); 578 return ret; 579 } 580 581 /* 582 * Remove a context of @name and its debugfs directory. 583 * 584 * This function should be called while holding damon_dbgfs_lock. 585 * 586 * Return 0 on success, negative error code otherwise. 587 */ 588 static int dbgfs_rm_context(char *name) 589 { 590 struct dentry *root, *dir, **new_dirs; 591 struct damon_ctx **new_ctxs; 592 int i, j; 593 594 if (damon_nr_running_ctxs()) 595 return -EBUSY; 596 597 root = dbgfs_dirs[0]; 598 if (!root) 599 return -ENOENT; 600 601 dir = debugfs_lookup(name, root); 602 if (!dir) 603 return -ENOENT; 604 605 new_dirs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_dirs), 606 GFP_KERNEL); 607 if (!new_dirs) 608 return -ENOMEM; 609 610 new_ctxs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_ctxs), 611 GFP_KERNEL); 612 if (!new_ctxs) { 613 kfree(new_dirs); 614 return -ENOMEM; 615 } 616 617 for (i = 0, j = 0; i < dbgfs_nr_ctxs; i++) { 618 if (dbgfs_dirs[i] == dir) { 619 debugfs_remove(dbgfs_dirs[i]); 620 dbgfs_destroy_ctx(dbgfs_ctxs[i]); 621 continue; 622 } 623 new_dirs[j] = dbgfs_dirs[i]; 624 new_ctxs[j++] = dbgfs_ctxs[i]; 625 } 626 627 kfree(dbgfs_dirs); 628 kfree(dbgfs_ctxs); 629 630 dbgfs_dirs = new_dirs; 631 dbgfs_ctxs = new_ctxs; 632 dbgfs_nr_ctxs--; 633 634 return 0; 635 } 636 637 static ssize_t dbgfs_rm_context_write(struct file *file, 638 const char __user *buf, size_t count, loff_t *ppos) 639 { 640 char *kbuf; 641 ssize_t ret = count; 642 int err; 643 char *ctx_name; 644 645 kbuf = user_input_str(buf, count, ppos); 646 if (IS_ERR(kbuf)) 647 return PTR_ERR(kbuf); 648 ctx_name = kmalloc(count + 1, GFP_KERNEL); 649 if (!ctx_name) { 650 kfree(kbuf); 651 return -ENOMEM; 652 } 653 654 /* Trim white space */ 655 if (sscanf(kbuf, "%s", ctx_name) != 1) { 656 ret = -EINVAL; 657 goto out; 658 } 659 660 mutex_lock(&damon_dbgfs_lock); 661 err = dbgfs_rm_context(ctx_name); 662 if (err) 663 ret = err; 664 mutex_unlock(&damon_dbgfs_lock); 665 666 out: 667 kfree(kbuf); 668 kfree(ctx_name); 669 return ret; 670 } 671 672 static ssize_t dbgfs_monitor_on_read(struct file *file, 673 char __user *buf, size_t count, loff_t *ppos) 674 { 675 char monitor_on_buf[5]; 676 bool monitor_on = damon_nr_running_ctxs() != 0; 677 int len; 678 679 len = scnprintf(monitor_on_buf, 5, monitor_on ? "on\n" : "off\n"); 680 681 return simple_read_from_buffer(buf, count, ppos, monitor_on_buf, len); 682 } 683 684 static ssize_t dbgfs_monitor_on_write(struct file *file, 685 const char __user *buf, size_t count, loff_t *ppos) 686 { 687 ssize_t ret = count; 688 char *kbuf; 689 int err; 690 691 kbuf = user_input_str(buf, count, ppos); 692 if (IS_ERR(kbuf)) 693 return PTR_ERR(kbuf); 694 695 /* Remove white space */ 696 if (sscanf(kbuf, "%s", kbuf) != 1) { 697 kfree(kbuf); 698 return -EINVAL; 699 } 700 701 if (!strncmp(kbuf, "on", count)) 702 err = damon_start(dbgfs_ctxs, dbgfs_nr_ctxs); 703 else if (!strncmp(kbuf, "off", count)) 704 err = damon_stop(dbgfs_ctxs, dbgfs_nr_ctxs); 705 else 706 err = -EINVAL; 707 708 if (err) 709 ret = err; 710 kfree(kbuf); 711 return ret; 712 } 713 714 static const struct file_operations mk_contexts_fops = { 715 .write = dbgfs_mk_context_write, 716 }; 717 718 static const struct file_operations rm_contexts_fops = { 719 .write = dbgfs_rm_context_write, 720 }; 721 722 static const struct file_operations monitor_on_fops = { 723 .read = dbgfs_monitor_on_read, 724 .write = dbgfs_monitor_on_write, 725 }; 726 727 static int __init __damon_dbgfs_init(void) 728 { 729 struct dentry *dbgfs_root; 730 const char * const file_names[] = {"mk_contexts", "rm_contexts", 731 "monitor_on"}; 732 const struct file_operations *fops[] = {&mk_contexts_fops, 733 &rm_contexts_fops, &monitor_on_fops}; 734 int i; 735 736 dbgfs_root = debugfs_create_dir("damon", NULL); 737 738 for (i = 0; i < ARRAY_SIZE(file_names); i++) 739 debugfs_create_file(file_names[i], 0600, dbgfs_root, NULL, 740 fops[i]); 741 dbgfs_fill_ctx_dir(dbgfs_root, dbgfs_ctxs[0]); 742 743 dbgfs_dirs = kmalloc_array(1, sizeof(dbgfs_root), GFP_KERNEL); 744 if (!dbgfs_dirs) { 745 debugfs_remove(dbgfs_root); 746 return -ENOMEM; 747 } 748 dbgfs_dirs[0] = dbgfs_root; 749 750 return 0; 751 } 752 753 /* 754 * Functions for the initialization 755 */ 756 757 static int __init damon_dbgfs_init(void) 758 { 759 int rc; 760 761 dbgfs_ctxs = kmalloc(sizeof(*dbgfs_ctxs), GFP_KERNEL); 762 if (!dbgfs_ctxs) 763 return -ENOMEM; 764 dbgfs_ctxs[0] = dbgfs_new_ctx(); 765 if (!dbgfs_ctxs[0]) { 766 kfree(dbgfs_ctxs); 767 return -ENOMEM; 768 } 769 dbgfs_nr_ctxs = 1; 770 771 rc = __damon_dbgfs_init(); 772 if (rc) { 773 kfree(dbgfs_ctxs[0]); 774 kfree(dbgfs_ctxs); 775 pr_err("%s: dbgfs init failed\n", __func__); 776 } 777 778 return rc; 779 } 780 781 module_init(damon_dbgfs_init); 782 783 #include "dbgfs-test.h" 784