Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'tracefs-v7.1-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull tracefs updates from Steven Rostedt:

- Simplify error handling with guards()

Use guards() to simplify the handling of releasing locks in exit
paths.

- Use dentry name snapshots instead of allocation

Instead of allocating a temp buffer to store the dentry name to use
in mkdir() and rmdir() use take_dentry_name_snapshot().

- Fix default permissions not being applied at boot

The default permissions for tracefs was 0700 to only allow root
having access. But after a change to fix other mount options the
update to permissions ignored the defined default and used the system
default of 0755. This is a regression and is fixed.

* tag 'tracefs-v7.1-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
tracefs: Removed unused 'ret' variable in eventfs_iterate()
tracefs: Fix default permissions not being applied on initial mount
tracefs: Use dentry name snapshots instead of heap allocation
eventfs: Simplify code using guard()s

+45 -93
+36 -62
fs/tracefs/event_inode.c
··· 180 180 const char *name; 181 181 int ret; 182 182 183 - mutex_lock(&eventfs_mutex); 183 + guard(mutex)(&eventfs_mutex); 184 184 ei = dentry->d_fsdata; 185 - if (ei->is_freed) { 186 - /* Do not allow changes if the event is about to be removed. */ 187 - mutex_unlock(&eventfs_mutex); 185 + /* Do not allow changes if the event is about to be removed. */ 186 + if (ei->is_freed) 188 187 return -ENODEV; 189 - } 190 188 191 189 /* Preallocate the children mode array if necessary */ 192 190 if (!(dentry->d_inode->i_mode & S_IFDIR)) { 193 191 if (!ei->entry_attrs) { 194 192 ei->entry_attrs = kzalloc_objs(*ei->entry_attrs, 195 193 ei->nr_entries, GFP_NOFS); 196 - if (!ei->entry_attrs) { 197 - ret = -ENOMEM; 198 - goto out; 199 - } 194 + if (!ei->entry_attrs) 195 + return -ENOMEM; 200 196 } 201 197 } 202 198 203 199 ret = simple_setattr(idmap, dentry, iattr); 204 200 if (ret < 0) 205 - goto out; 201 + return ret; 206 202 207 203 /* 208 204 * If this is a dir, then update the ei cache, only the file ··· 221 225 } 222 226 } 223 227 } 224 - out: 225 - mutex_unlock(&eventfs_mutex); 226 228 return ret; 227 229 } 228 230 ··· 522 528 struct tracefs_inode *ti; 523 529 struct eventfs_inode *ei; 524 530 const char *name = dentry->d_name.name; 525 - struct dentry *result = NULL; 526 531 527 532 ti = get_tracefs(dir); 528 533 if (WARN_ON_ONCE(!(ti->flags & TRACEFS_EVENT_INODE))) 529 534 return ERR_PTR(-EIO); 530 535 531 - mutex_lock(&eventfs_mutex); 536 + guard(mutex)(&eventfs_mutex); 532 537 533 538 ei = ti->private; 534 539 if (!ei || ei->is_freed) 535 - goto out; 540 + return NULL; 536 541 537 542 list_for_each_entry(ei_child, &ei->children, list) { 538 543 if (strcmp(ei_child->name, name) != 0) 539 544 continue; 540 545 /* A child is freed and removed from the list at the same time */ 541 546 if (WARN_ON_ONCE(ei_child->is_freed)) 542 - goto out; 543 - result = lookup_dir_entry(dentry, ei, ei_child); 544 - goto out; 547 + return NULL; 548 + return lookup_dir_entry(dentry, ei, ei_child); 545 549 } 546 550 547 551 for (int i = 0; i < ei->nr_entries; i++) { ··· 553 561 554 562 data = ei->data; 555 563 if (entry->callback(name, &mode, &data, &fops) <= 0) 556 - goto out; 564 + return NULL; 557 565 558 - result = lookup_file_dentry(dentry, ei, i, mode, data, fops); 559 - goto out; 566 + return lookup_file_dentry(dentry, ei, i, mode, data, fops); 567 + 560 568 } 561 - out: 562 - mutex_unlock(&eventfs_mutex); 563 - return result; 569 + return NULL; 564 570 } 565 571 566 572 /* ··· 574 584 struct eventfs_inode *ei; 575 585 const char *name; 576 586 umode_t mode; 577 - int idx; 578 - int ret = -EINVAL; 579 587 int ino; 580 588 int i, r, c; 581 589 ··· 586 598 587 599 c = ctx->pos - 2; 588 600 589 - idx = srcu_read_lock(&eventfs_srcu); 601 + guard(srcu)(&eventfs_srcu); 590 602 591 - mutex_lock(&eventfs_mutex); 592 - ei = READ_ONCE(ti->private); 593 - if (ei && ei->is_freed) 594 - ei = NULL; 595 - mutex_unlock(&eventfs_mutex); 596 - 597 - if (!ei) 598 - goto out; 603 + scoped_guard(mutex, &eventfs_mutex) { 604 + ei = READ_ONCE(ti->private); 605 + if (!ei || ei->is_freed) 606 + return -EINVAL; 607 + } 599 608 600 609 /* 601 610 * Need to create the dentries and inodes to have a consistent 602 611 * inode number. 603 612 */ 604 - ret = 0; 605 613 606 614 /* Start at 'c' to jump over already read entries */ 607 615 for (i = c; i < ei->nr_entries; i++, ctx->pos++) { ··· 606 622 entry = &ei->entries[i]; 607 623 name = entry->name; 608 624 609 - mutex_lock(&eventfs_mutex); 610 625 /* If ei->is_freed then just bail here, nothing more to do */ 611 - if (ei->is_freed) { 612 - mutex_unlock(&eventfs_mutex); 613 - goto out; 626 + scoped_guard(mutex, &eventfs_mutex) { 627 + if (ei->is_freed) 628 + return -EINVAL; 629 + r = entry->callback(name, &mode, &cdata, &fops); 614 630 } 615 - r = entry->callback(name, &mode, &cdata, &fops); 616 - mutex_unlock(&eventfs_mutex); 617 631 if (r <= 0) 618 632 continue; 619 633 620 634 ino = EVENTFS_FILE_INODE_INO; 621 635 622 636 if (!dir_emit(ctx, name, strlen(name), ino, DT_REG)) 623 - goto out; 637 + return -EINVAL; 624 638 } 625 639 626 640 /* Subtract the skipped entries above */ ··· 641 659 642 660 ino = eventfs_dir_ino(ei_child); 643 661 644 - if (!dir_emit(ctx, name, strlen(name), ino, DT_DIR)) 645 - goto out_dec; 662 + if (!dir_emit(ctx, name, strlen(name), ino, DT_DIR)) { 663 + /* Incremented ctx->pos without adding something, reset it */ 664 + ctx->pos--; 665 + return -EINVAL; 666 + } 646 667 } 647 - ret = 1; 648 - out: 649 - srcu_read_unlock(&eventfs_srcu, idx); 650 - 651 - return ret; 652 - 653 - out_dec: 654 - /* Incremented ctx->pos without adding something, reset it */ 655 - ctx->pos--; 656 - goto out; 668 + return 1; 657 669 } 658 670 659 671 /** ··· 704 728 INIT_LIST_HEAD(&ei->children); 705 729 INIT_LIST_HEAD(&ei->list); 706 730 707 - mutex_lock(&eventfs_mutex); 708 - if (!parent->is_freed) 709 - list_add_tail(&ei->list, &parent->children); 710 - mutex_unlock(&eventfs_mutex); 711 - 731 + scoped_guard(mutex, &eventfs_mutex) { 732 + if (!parent->is_freed) 733 + list_add_tail(&ei->list, &parent->children); 734 + } 712 735 /* Was the parent freed? */ 713 736 if (list_empty(&ei->list)) { 714 737 cleanup_ei(ei); ··· 853 878 if (!ei) 854 879 return; 855 880 856 - mutex_lock(&eventfs_mutex); 881 + guard(mutex)(&eventfs_mutex); 857 882 eventfs_remove_rec(ei, 0); 858 - mutex_unlock(&eventfs_mutex); 859 883 } 860 884 861 885 /**
+9 -31
fs/tracefs/inode.c
··· 94 94 int (*rmdir)(const char *name); 95 95 } tracefs_ops __ro_after_init; 96 96 97 - static char *get_dname(struct dentry *dentry) 98 - { 99 - const char *dname; 100 - char *name; 101 - int len = dentry->d_name.len; 102 - 103 - dname = dentry->d_name.name; 104 - name = kmalloc(len + 1, GFP_KERNEL); 105 - if (!name) 106 - return NULL; 107 - memcpy(name, dname, len); 108 - name[len] = 0; 109 - return name; 110 - } 111 - 112 97 static struct dentry *tracefs_syscall_mkdir(struct mnt_idmap *idmap, 113 98 struct inode *inode, struct dentry *dentry, 114 99 umode_t mode) 115 100 { 116 101 struct tracefs_inode *ti; 117 - char *name; 102 + struct name_snapshot name; 118 103 int ret; 119 - 120 - name = get_dname(dentry); 121 - if (!name) 122 - return ERR_PTR(-ENOMEM); 123 104 124 105 /* 125 106 * This is a new directory that does not take the default of ··· 116 135 * the files within the tracefs system. It is up to the individual 117 136 * mkdir routine to handle races. 118 137 */ 138 + take_dentry_name_snapshot(&name, dentry); 119 139 inode_unlock(inode); 120 - ret = tracefs_ops.mkdir(name); 140 + ret = tracefs_ops.mkdir(name.name.name); 121 141 inode_lock(inode); 122 - 123 - kfree(name); 142 + release_dentry_name_snapshot(&name); 124 143 125 144 return ERR_PTR(ret); 126 145 } 127 146 128 147 static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry) 129 148 { 130 - char *name; 149 + struct name_snapshot name; 131 150 int ret; 132 - 133 - name = get_dname(dentry); 134 - if (!name) 135 - return -ENOMEM; 136 151 137 152 /* 138 153 * The rmdir call can call the generic functions that create ··· 137 160 * This time we need to unlock not only the parent (inode) but 138 161 * also the directory that is being deleted. 139 162 */ 163 + take_dentry_name_snapshot(&name, dentry); 140 164 inode_unlock(inode); 141 165 inode_unlock(d_inode(dentry)); 142 166 143 - ret = tracefs_ops.rmdir(name); 167 + ret = tracefs_ops.rmdir(name.name.name); 144 168 145 169 inode_lock_nested(inode, I_MUTEX_PARENT); 146 170 inode_lock(d_inode(dentry)); 147 - 148 - kfree(name); 171 + release_dentry_name_snapshot(&name); 149 172 150 173 return ret; 151 174 } ··· 468 491 return err; 469 492 470 493 sb->s_op = &tracefs_super_operations; 494 + tracefs_apply_options(sb, false); 471 495 set_default_d_op(sb, &tracefs_dentry_operations); 472 496 473 497 return 0;