two requirements: no file creations in IS_DEADDIR and no cross-directory renames whatsoever.
Unified · Split
| @@ -332,7 +332,10 @@ static struct dentry *start_creating(const char *name, struct dentry *parent) · 331 unmodified lines | |||
| 332 | parent = debugfs_mount->mnt_root; | 332 | parent = debugfs_mount->mnt_root; |
| 333 | 333 | ||
| 334 | inode_lock(d_inode(parent)); | 334 | inode_lock(d_inode(parent)); |
| 335 | dentry = lookup_one_len(name, parent, strlen(name)); | 335 | if (unlikely(IS_DEADDIR(d_inode(parent)))) |
| 336 | dentry = ERR_PTR(-ENOENT); | ||
| 337 | else | ||
| 338 | dentry = lookup_one_len(name, parent, strlen(name)); | ||
| 336 | if (!IS_ERR(dentry) && d_really_is_positive(dentry)) { | 339 | if (!IS_ERR(dentry) && d_really_is_positive(dentry)) { |
| 337 | if (d_is_dir(dentry)) | 340 | if (d_is_dir(dentry)) |
| 338 | pr_err("Directory '%s' with parent '%s' already present!\n", | 341 | pr_err("Directory '%s' with parent '%s' already present!\n", |
| @@ -681,62 +684,15 @@ static void __debugfs_file_removed(struct dentry *dentry) · 342 unmodified lines | |||
| 681 | wait_for_completion(&fsd->active_users_drained); | 684 | wait_for_completion(&fsd->active_users_drained); |
| 682 | } | 685 | } |
| 683 | 686 | ||
| 684 | static int __debugfs_remove(struct dentry *dentry, struct dentry *parent) | 687 | static void remove_one(struct dentry *victim) |
| 685 | { | ||
| 686 | int ret = 0; | ||
| 687 | |||
| 688 | if (simple_positive(dentry)) { | ||
| 689 | dget(dentry); | ||
| 690 | if (d_is_dir(dentry)) { | ||
| 691 | ret = simple_rmdir(d_inode(parent), dentry); | ||
| 692 | if (!ret) | ||
| 693 | fsnotify_rmdir(d_inode(parent), dentry); | ||
| 694 | } else { | ||
| 695 | simple_unlink(d_inode(parent), dentry); | ||
| 696 | fsnotify_unlink(d_inode(parent), dentry); | ||
| 697 | } | ||
| 698 | if (!ret) | ||
| 699 | d_delete(dentry); | ||
| 700 | if (d_is_reg(dentry)) | ||
| 701 | __debugfs_file_removed(dentry); | ||
| 702 | dput(dentry); | ||
| 703 | } | ||
| 704 | return ret; | ||
| 705 | } | ||
| 706 | |||
| 707 | /** | ||
| 708 | * debugfs_remove - removes a file or directory from the debugfs filesystem | ||
| 709 | * @dentry: a pointer to a the dentry of the file or directory to be | ||
| 710 | * removed. If this parameter is NULL or an error value, nothing | ||
| 711 | * will be done. | ||
| 712 | * | ||
| 713 | * This function removes a file or directory in debugfs that was previously | ||
| 714 | * created with a call to another debugfs function (like | ||
| 715 | * debugfs_create_file() or variants thereof.) | ||
| 716 | * | ||
| 717 | * This function is required to be called in order for the file to be | ||
| 718 | * removed, no automatic cleanup of files will happen when a module is | ||
| 719 | * removed, you are responsible here. | ||
| 720 | */ | ||
| 721 | void debugfs_remove(struct dentry *dentry) | ||
| 722 | { | 688 | { |
| 723 | struct dentry *parent; | 689 | if (d_is_reg(victim)) |
| 724 | int ret; | 690 | __debugfs_file_removed(victim); |
| 725 | 691 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | |
| 726 | if (IS_ERR_OR_NULL(dentry)) | ||
| 727 | return; | ||
| 728 | |||
| 729 | parent = dentry->d_parent; | ||
| 730 | inode_lock(d_inode(parent)); | ||
| 731 | ret = __debugfs_remove(dentry, parent); | ||
| 732 | inode_unlock(d_inode(parent)); | ||
| 733 | if (!ret) | ||
| 734 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
| 735 | } | 692 | } |
| 736 | EXPORT_SYMBOL_GPL(debugfs_remove); | ||
| 737 | 693 | ||
| 738 | /** | 694 | /** |
| 739 | * debugfs_remove_recursive - recursively removes a directory | 695 | * debugfs_remove - recursively removes a directory |
| 740 | * @dentry: a pointer to a the dentry of the directory to be removed. If this | 696 | * @dentry: a pointer to a the dentry of the directory to be removed. If this |
| 741 | * parameter is NULL or an error value, nothing will be done. | 697 | * parameter is NULL or an error value, nothing will be done. |
| 742 | * | 698 | * |
| @@ -748,65 +704,16 @@ EXPORT_SYMBOL_GPL(debugfs_remove); · 5 unmodified lines | |||
| 748 | * removed, no automatic cleanup of files will happen when a module is | 704 | * removed, no automatic cleanup of files will happen when a module is |
| 749 | * removed, you are responsible here. | 705 | * removed, you are responsible here. |
| 750 | */ | 706 | */ |
| 751 | void debugfs_remove_recursive(struct dentry *dentry) | 707 | void debugfs_remove(struct dentry *dentry) |
| 752 | { | 708 | { |
| 753 | struct dentry *child, *parent; | ||
| 754 | |||
| 755 | if (IS_ERR_OR_NULL(dentry)) | 709 | if (IS_ERR_OR_NULL(dentry)) |
| 756 | return; | 710 | return; |
| 757 | 711 | ||
| 758 | parent = dentry; | 712 | simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count); |
| 759 | down: | 713 | simple_recursive_removal(dentry, remove_one); |
| 760 | inode_lock(d_inode(parent)); | 714 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); |
| 761 | loop: | ||
| 762 | /* | ||
| 763 | * The parent->d_subdirs is protected by the d_lock. Outside that | ||
| 764 | * lock, the child can be unlinked and set to be freed which can | ||
| 765 | * use the d_u.d_child as the rcu head and corrupt this list. | ||
| 766 | */ | ||
| 767 | spin_lock(&parent->d_lock); | ||
| 768 | list_for_each_entry(child, &parent->d_subdirs, d_child) { | ||
| 769 | if (!simple_positive(child)) | ||
| 770 | continue; | ||
| 771 | |||
| 772 | /* perhaps simple_empty(child) makes more sense */ | ||
| 773 | if (!list_empty(&child->d_subdirs)) { | ||
| 774 | spin_unlock(&parent->d_lock); | ||
| 775 | inode_unlock(d_inode(parent)); | ||
| 776 | parent = child; | ||
| 777 | goto down; | ||
| 778 | } | ||
| 779 | |||
| 780 | spin_unlock(&parent->d_lock); | ||
| 781 | |||
| 782 | if (!__debugfs_remove(child, parent)) | ||
| 783 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
| 784 | |||
| 785 | /* | ||
| 786 | * The parent->d_lock protects agaist child from unlinking | ||
| 787 | * from d_subdirs. When releasing the parent->d_lock we can | ||
| 788 | * no longer trust that the next pointer is valid. | ||
| 789 | * Restart the loop. We'll skip this one with the | ||
| 790 | * simple_positive() check. | ||
| 791 | */ | ||
| 792 | goto loop; | ||
| 793 | } | ||
| 794 | spin_unlock(&parent->d_lock); | ||
| 795 | |||
| 796 | inode_unlock(d_inode(parent)); | ||
| 797 | child = parent; | ||
| 798 | parent = parent->d_parent; | ||
| 799 | inode_lock(d_inode(parent)); | ||
| 800 | |||
| 801 | if (child != dentry) | ||
| 802 | /* go up */ | ||
| 803 | goto loop; | ||
| 804 | |||
| 805 | if (!__debugfs_remove(child, parent)) | ||
| 806 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
| 807 | inode_unlock(d_inode(parent)); | ||
| 808 | } | 715 | } |
| 809 | EXPORT_SYMBOL_GPL(debugfs_remove_recursive); | 716 | EXPORT_SYMBOL_GPL(debugfs_remove); |
| 810 | 717 | ||
| 811 | /** | 718 | /** |
| 812 | * debugfs_rename - rename a file/directory in the debugfs filesystem | 719 | * debugfs_rename - rename a file/directory in the debugfs filesystem |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include <linux/buffer_head.h> /* sync_mapping_buffers */ | 19 | #include <linux/buffer_head.h> /* sync_mapping_buffers */ |
| 20 | #include <linux/fs_context.h> | 20 | #include <linux/fs_context.h> |
| 21 | #include <linux/pseudo_fs.h> | 21 | #include <linux/pseudo_fs.h> |
| 22 | #include <linux/fsnotify.h> | ||
| 22 | 23 | ||
| 23 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
| 24 | 25 | ||
| @@ -239,6 +240,75 @@ const struct inode_operations simple_dir_inode_operations = { · 214 unmodified lines | |||
| 239 | }; | 240 | }; |
| 240 | EXPORT_SYMBOL(simple_dir_inode_operations); | 241 | EXPORT_SYMBOL(simple_dir_inode_operations); |
| 241 | 242 | ||
| 243 | static struct dentry *find_next_child(struct dentry *parent, struct dentry *prev) | ||
| 244 | { | ||
| 245 | struct dentry *child = NULL; | ||
| 246 | struct list_head *p = prev ? &prev->d_child : &parent->d_subdirs; | ||
| 247 | |||
| 248 | spin_lock(&parent->d_lock); | ||
| 249 | while ((p = p->next) != &parent->d_subdirs) { | ||
| 250 | struct dentry *d = container_of(p, struct dentry, d_child); | ||
| 251 | if (simple_positive(d)) { | ||
| 252 | spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); | ||
| 253 | if (simple_positive(d)) | ||
| 254 | child = dget_dlock(d); | ||
| 255 | spin_unlock(&d->d_lock); | ||
| 256 | if (likely(child)) | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | spin_unlock(&parent->d_lock); | ||
| 261 | dput(prev); | ||
| 262 | return child; | ||
| 263 | } | ||
| 264 | |||
| 265 | void simple_recursive_removal(struct dentry *dentry, | ||
| 266 | void (*callback)(struct dentry *)) | ||
| 267 | { | ||
| 268 | struct dentry *this = dget(dentry); | ||
| 269 | while (true) { | ||
| 270 | struct dentry *victim = NULL, *child; | ||
| 271 | struct inode *inode = this->d_inode; | ||
| 272 | |||
| 273 | inode_lock(inode); | ||
| 274 | if (d_is_dir(this)) | ||
| 275 | inode->i_flags |= S_DEAD; | ||
| 276 | while ((child = find_next_child(this, victim)) == NULL) { | ||
| 277 | // kill and ascend | ||
| 278 | // update metadata while it's still locked | ||
| 279 | inode->i_ctime = current_time(inode); | ||
| 280 | clear_nlink(inode); | ||
| 281 | inode_unlock(inode); | ||
| 282 | victim = this; | ||
| 283 | this = this->d_parent; | ||
| 284 | inode = this->d_inode; | ||
| 285 | inode_lock(inode); | ||
| 286 | if (simple_positive(victim)) { | ||
| 287 | d_invalidate(victim); // avoid lost mounts | ||
| 288 | if (d_is_dir(victim)) | ||
| 289 | fsnotify_rmdir(inode, victim); | ||
| 290 | else | ||
| 291 | fsnotify_unlink(inode, victim); | ||
| 292 | if (callback) | ||
| 293 | callback(victim); | ||
| 294 | dput(victim); // unpin it | ||
| 295 | } | ||
| 296 | if (victim == dentry) { | ||
| 297 | inode->i_ctime = inode->i_mtime = | ||
| 298 | current_time(inode); | ||
| 299 | if (d_is_dir(dentry)) | ||
| 300 | drop_nlink(inode); | ||
| 301 | inode_unlock(inode); | ||
| 302 | dput(dentry); | ||
| 303 | return; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | inode_unlock(inode); | ||
| 307 | this = child; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | EXPORT_SYMBOL(simple_recursive_removal); | ||
| 311 | |||
| 242 | static const struct super_operations simple_super_operations = { | 312 | static const struct super_operations simple_super_operations = { |
| 243 | .statfs = simple_statfs, | 313 | .statfs = simple_statfs, |
| 244 | }; | 314 | }; |
| @@ -330,7 +330,10 @@ static struct dentry *start_creating(const char *name, struct dentry *parent) · 329 unmodified lines | |||
| 330 | parent = tracefs_mount->mnt_root; | 330 | parent = tracefs_mount->mnt_root; |
| 331 | 331 | ||
| 332 | inode_lock(parent->d_inode); | 332 | inode_lock(parent->d_inode); |
| 333 | dentry = lookup_one_len(name, parent, strlen(name)); | 333 | if (unlikely(IS_DEADDIR(parent->d_inode))) |
| 334 | dentry = ERR_PTR(-ENOENT); | ||
| 335 | else | ||
| 336 | dentry = lookup_one_len(name, parent, strlen(name)); | ||
| 334 | if (!IS_ERR(dentry) && dentry->d_inode) { | 337 | if (!IS_ERR(dentry) && dentry->d_inode) { |
| 335 | dput(dentry); | 338 | dput(dentry); |
| 336 | dentry = ERR_PTR(-EEXIST); | 339 | dentry = ERR_PTR(-EEXIST); |
| @@ -499,122 +502,27 @@ __init struct dentry *tracefs_create_instance_dir(const char *name, · 162 unmodified lines | |||
| 499 | return dentry; | 502 | return dentry; |
| 500 | } | 503 | } |
| 501 | 504 | ||
| 502 | static int __tracefs_remove(struct dentry *dentry, struct dentry *parent) | 505 | static void remove_one(struct dentry *victim) |
| 503 | { | 506 | { |
| 504 | int ret = 0; | 507 | simple_release_fs(&tracefs_mount, &tracefs_mount_count); |
| 505 | |||
| 506 | if (simple_positive(dentry)) { | ||
| 507 | if (dentry->d_inode) { | ||
| 508 | dget(dentry); | ||
| 509 | switch (dentry->d_inode->i_mode & S_IFMT) { | ||
| 510 | case S_IFDIR: | ||
| 511 | ret = simple_rmdir(parent->d_inode, dentry); | ||
| 512 | if (!ret) | ||
| 513 | fsnotify_rmdir(parent->d_inode, dentry); | ||
| 514 | break; | ||
| 515 | default: | ||
| 516 | simple_unlink(parent->d_inode, dentry); | ||
| 517 | fsnotify_unlink(parent->d_inode, dentry); | ||
| 518 | break; | ||
| 519 | } | ||
| 520 | if (!ret) | ||
| 521 | d_delete(dentry); | ||
| 522 | dput(dentry); | ||
| 523 | } | ||
| 524 | } | ||
| 525 | return ret; | ||
| 526 | } | ||
| 527 | |||
| 528 | /** | ||
| 529 | * tracefs_remove - removes a file or directory from the tracefs filesystem | ||
| 530 | * @dentry: a pointer to a the dentry of the file or directory to be | ||
| 531 | * removed. | ||
| 532 | * | ||
| 533 | * This function removes a file or directory in tracefs that was previously | ||
| 534 | * created with a call to another tracefs function (like | ||
| 535 | * tracefs_create_file() or variants thereof.) | ||
| 536 | */ | ||
| 537 | void tracefs_remove(struct dentry *dentry) | ||
| 538 | { | ||
| 539 | struct dentry *parent; | ||
| 540 | int ret; | ||
| 541 | |||
| 542 | if (IS_ERR_OR_NULL(dentry)) | ||
| 543 | return; | ||
| 544 | |||
| 545 | parent = dentry->d_parent; | ||
| 546 | inode_lock(parent->d_inode); | ||
| 547 | ret = __tracefs_remove(dentry, parent); | ||
| 548 | inode_unlock(parent->d_inode); | ||
| 549 | if (!ret) | ||
| 550 | simple_release_fs(&tracefs_mount, &tracefs_mount_count); | ||
| 551 | } | 508 | } |
| 552 | 509 | ||
| 553 | /** | 510 | /** |
| 554 | * tracefs_remove_recursive - recursively removes a directory | 511 | * tracefs_remove - recursively removes a directory |
| 555 | * @dentry: a pointer to a the dentry of the directory to be removed. | 512 | * @dentry: a pointer to a the dentry of the directory to be removed. |
| 556 | * | 513 | * |
| 557 | * This function recursively removes a directory tree in tracefs that | 514 | * This function recursively removes a directory tree in tracefs that |
| 558 | * was previously created with a call to another tracefs function | 515 | * was previously created with a call to another tracefs function |
| 559 | * (like tracefs_create_file() or variants thereof.) | 516 | * (like tracefs_create_file() or variants thereof.) |
| 560 | */ | 517 | */ |
| 561 | void tracefs_remove_recursive(struct dentry *dentry) | 518 | void tracefs_remove(struct dentry *dentry) |
| 562 | { | 519 | { |
| 563 | struct dentry *child, *parent; | ||
| 564 | |||
| 565 | if (IS_ERR_OR_NULL(dentry)) | 520 | if (IS_ERR_OR_NULL(dentry)) |
| 566 | return; | 521 | return; |
| 567 | 522 | ||
| 568 | parent = dentry; | 523 | simple_pin_fs(&trace_fs_type, &tracefs_mount, &tracefs_mount_count); |
| 569 | down: | 524 | simple_recursive_removal(dentry, remove_one); |
| 570 | inode_lock(parent->d_inode); | 525 | simple_release_fs(&tracefs_mount, &tracefs_mount_count); |
| 571 | loop: | ||
| 572 | /* | ||
| 573 | * The parent->d_subdirs is protected by the d_lock. Outside that | ||
| 574 | * lock, the child can be unlinked and set to be freed which can | ||
| 575 | * use the d_u.d_child as the rcu head and corrupt this list. | ||
| 576 | */ | ||
| 577 | spin_lock(&parent->d_lock); | ||
| 578 | list_for_each_entry(child, &parent->d_subdirs, d_child) { | ||
| 579 | if (!simple_positive(child)) | ||
| 580 | continue; | ||
| 581 | |||
| 582 | /* perhaps simple_empty(child) makes more sense */ | ||
| 583 | if (!list_empty(&child->d_subdirs)) { | ||
| 584 | spin_unlock(&parent->d_lock); | ||
| 585 | inode_unlock(parent->d_inode); | ||
| 586 | parent = child; | ||
| 587 | goto down; | ||
| 588 | } | ||
| 589 | |||
| 590 | spin_unlock(&parent->d_lock); | ||
| 591 | |||
| 592 | if (!__tracefs_remove(child, parent)) | ||
| 593 | simple_release_fs(&tracefs_mount, &tracefs_mount_count); | ||
| 594 | |||
| 595 | /* | ||
| 596 | * The parent->d_lock protects agaist child from unlinking | ||
| 597 | * from d_subdirs. When releasing the parent->d_lock we can | ||
| 598 | * no longer trust that the next pointer is valid. | ||
| 599 | * Restart the loop. We'll skip this one with the | ||
| 600 | * simple_positive() check. | ||
| 601 | */ | ||
| 602 | goto loop; | ||
| 603 | } | ||
| 604 | spin_unlock(&parent->d_lock); | ||
| 605 | |||
| 606 | inode_unlock(parent->d_inode); | ||
| 607 | child = parent; | ||
| 608 | parent = parent->d_parent; | ||
| 609 | inode_lock(parent->d_inode); | ||
| 610 | |||
| 611 | if (child != dentry) | ||
| 612 | /* go up */ | ||
| 613 | goto loop; | ||
| 614 | |||
| 615 | if (!__tracefs_remove(child, parent)) | ||
| 616 | simple_release_fs(&tracefs_mount, &tracefs_mount_count); | ||
| 617 | inode_unlock(parent->d_inode); | ||
| 618 | } | 526 | } |
| 619 | 527 | ||
| 620 | /** | 528 | /** |
| @@ -83,7 +83,7 @@ struct dentry *debugfs_create_automount(const char *name, · 82 unmodified lines | |||
| 83 | void *data); | 83 | void *data); |
| 84 | 84 | ||
| 85 | void debugfs_remove(struct dentry *dentry); | 85 | void debugfs_remove(struct dentry *dentry); |
| 86 | void debugfs_remove_recursive(struct dentry *dentry); | 86 | #define debugfs_remove_recursive debugfs_remove |
| 87 | 87 | ||
| 88 | const struct file_operations *debugfs_real_fops(const struct file *filp); | 88 | const struct file_operations *debugfs_real_fops(const struct file *filp); |
| 89 | 89 | ||
| @@ -3303,6 +3303,8 @@ extern int simple_unlink(struct inode *, struct dentry *); · 3302 unmodified lines | |||
| 3303 | extern int simple_rmdir(struct inode *, struct dentry *); | 3303 | extern int simple_rmdir(struct inode *, struct dentry *); |
| 3304 | extern int simple_rename(struct inode *, struct dentry *, | 3304 | extern int simple_rename(struct inode *, struct dentry *, |
| 3305 | struct inode *, struct dentry *, unsigned int); | 3305 | struct inode *, struct dentry *, unsigned int); |
| 3306 | extern void simple_recursive_removal(struct dentry *, | ||
| 3307 | void (*callback)(struct dentry *)); | ||
| 3306 | extern int noop_fsync(struct file *, loff_t, loff_t, int); | 3308 | extern int noop_fsync(struct file *, loff_t, loff_t, int); |
| 3307 | extern int noop_set_page_dirty(struct page *page); | 3309 | extern int noop_set_page_dirty(struct page *page); |
| 3308 | extern void noop_invalidatepage(struct page *page, unsigned int offset, | 3310 | extern void noop_invalidatepage(struct page *page, unsigned int offset, |
| @@ -28,7 +28,6 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode, · 27 unmodified lines | |||
| 28 | struct dentry *tracefs_create_dir(const char *name, struct dentry *parent); | 28 | struct dentry *tracefs_create_dir(const char *name, struct dentry *parent); |
| 29 | 29 | ||
| 30 | void tracefs_remove(struct dentry *dentry); | 30 | void tracefs_remove(struct dentry *dentry); |
| 31 | void tracefs_remove_recursive(struct dentry *dentry); | ||
| 32 | 31 | ||
| 33 | struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent, | 32 | struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent, |
| 34 | int (*mkdir)(const char *name), | 33 | int (*mkdir)(const char *name), |
| @@ -8496,7 +8496,7 @@ static struct trace_array *trace_array_create(const char *name) · 8495 unmodified lines | |||
| 8496 | 8496 | ||
| 8497 | ret = event_trace_add_tracer(tr->dir, tr); | 8497 | ret = event_trace_add_tracer(tr->dir, tr); |
| 8498 | if (ret) { | 8498 | if (ret) { |
| 8499 | tracefs_remove_recursive(tr->dir); | 8499 | tracefs_remove(tr->dir); |
| 8500 | goto out_free_tr; | 8500 | goto out_free_tr; |
| 8501 | } | 8501 | } |
| 8502 | 8502 | ||
| @@ -8605,7 +8605,7 @@ static int __remove_instance(struct trace_array *tr) · 102 unmodified lines | |||
| 8605 | event_trace_del_tracer(tr); | 8605 | event_trace_del_tracer(tr); |
| 8606 | ftrace_clear_pids(tr); | 8606 | ftrace_clear_pids(tr); |
| 8607 | ftrace_destroy_function_files(tr); | 8607 | ftrace_destroy_function_files(tr); |
| 8608 | tracefs_remove_recursive(tr->dir); | 8608 | tracefs_remove(tr->dir); |
| 8609 | free_trace_buffers(tr); | 8609 | free_trace_buffers(tr); |
| 8610 | 8610 | ||
| 8611 | for (i = 0; i < tr->nr_topts; i++) { | 8611 | for (i = 0; i < tr->nr_topts; i++) { |
| @@ -697,7 +697,7 @@ static void remove_subsystem(struct trace_subsystem_dir *dir) · 696 unmodified lines | |||
| 697 | return; | 697 | return; |
| 698 | 698 | ||
| 699 | if (!--dir->nr_events) { | 699 | if (!--dir->nr_events) { |
| 700 | tracefs_remove_recursive(dir->entry); | 700 | tracefs_remove(dir->entry); |
| 701 | list_del(&dir->list); | 701 | list_del(&dir->list); |
| 702 | __put_system_dir(dir); | 702 | __put_system_dir(dir); |
| 703 | } | 703 | } |
| @@ -716,7 +716,7 @@ static void remove_event_file_dir(struct trace_event_file *file) · 12 unmodified lines | |||
| 716 | } | 716 | } |
| 717 | spin_unlock(&dir->d_lock); | 717 | spin_unlock(&dir->d_lock); |
| 718 | 718 | ||
| 719 | tracefs_remove_recursive(dir); | 719 | tracefs_remove(dir); |
| 720 | } | 720 | } |
| 721 | 721 | ||
| 722 | list_del(&file->list); | 722 | list_del(&file->list); |
| @@ -3064,7 +3064,7 @@ int event_trace_del_tracer(struct trace_array *tr) · 2341 unmodified lines | |||
| 3064 | 3064 | ||
| 3065 | down_write(&trace_event_sem); | 3065 | down_write(&trace_event_sem); |
| 3066 | __trace_remove_event_dirs(tr); | 3066 | __trace_remove_event_dirs(tr); |
| 3067 | tracefs_remove_recursive(tr->event_dir); | 3067 | tracefs_remove(tr->event_dir); |
| 3068 | up_write(&trace_event_sem); | 3068 | up_write(&trace_event_sem); |
| 3069 | 3069 | ||
| 3070 | tr->event_dir = NULL; | 3070 | tr->event_dir = NULL; |
| @@ -556,7 +556,7 @@ static int init_tracefs(void) · 555 unmodified lines | |||
| 556 | return 0; | 556 | return 0; |
| 557 | 557 | ||
| 558 | err: | 558 | err: |
| 559 | tracefs_remove_recursive(top_dir); | 559 | tracefs_remove(top_dir); |
| 560 | return -ENOMEM; | 560 | return -ENOMEM; |
| 561 | } | 561 | } |
| 562 | 562 | ||