On Tue, 30 Jan 2024 11:54:56 -0800 Linus Torvalds <torva...@linux-foundation.org> wrote:
> If you do run the full tracefs tests on the whole series, and there > are no other major problems, I'll happily take it all for 6.8. And > yes, even mark it for stable. I think the other bugs are much harder > to hit, but I do think they exist. And code deletion is always good. > > So give it the full test attention, and *if* it all still looks good > and there are no new subtle issues that crop up, let's just put this > saga behind us asap. BTW, I ran my full test suite on your patches with the below updates and it all passed. Note, I did not run the "bisectable" portion of my test. That is, the part that runs tests on each patch in the series. Because I know that fails. I just ran the tests on the last applied patch. I can break up and clean up the patches so that they are bisectable, and if that passes the bisectable portion of my tests, I can still send them to you for 6.8. I think this does fix a lot of hidden bugs, and would like all this to go back to 6.6 when the eventfs was first introduced. -- Steve diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c index acdc797bd9c0..31cbe38739fa 100644 --- a/fs/tracefs/event_inode.c +++ b/fs/tracefs/event_inode.c @@ -74,7 +74,8 @@ static void release_ei(struct kref *ref) { struct eventfs_inode *ei = container_of(ref, struct eventfs_inode, kref); kfree(ei->entry_attrs); - kfree(ei); + kfree_const(ei->name); + kfree_rcu(ei, rcu); } static inline void put_ei(struct eventfs_inode *ei) @@ -348,8 +349,7 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei, inode->i_ino = EVENTFS_FILE_INODE_INO; ti = get_tracefs(inode); - ti->flags = TRACEFS_EVENT_INODE; - ti->private = NULL; // Directories have 'ei', files not + ti->flags |= TRACEFS_EVENT_INODE; // Files have their parent's ei as their fsdata dentry->d_fsdata = get_ei(parent_ei); @@ -388,7 +388,8 @@ static struct dentry *lookup_dir_entry(struct dentry *dentry, inode->i_ino = eventfs_dir_ino(ei); ti = get_tracefs(inode); - ti->flags = TRACEFS_EVENT_INODE; + ti->flags |= TRACEFS_EVENT_INODE; + /* Only directories have ti->private set to an ei, not files */ ti->private = ei; dentry->d_fsdata = get_ei(ei); @@ -402,17 +403,20 @@ static struct dentry *lookup_dir_entry(struct dentry *dentry, static inline struct eventfs_inode *alloc_ei(const char *name) { - int namesize = strlen(name) + 1; - struct eventfs_inode *ei = kzalloc(sizeof(*ei) + namesize, GFP_KERNEL); + struct eventfs_inode *ei = kzalloc(sizeof(*ei), GFP_KERNEL); - if (ei) { - memcpy((char *)ei->name, name, namesize); - kref_init(&ei->kref); + if (!ei) + return NULL; + + ei->name = kstrdup_const(name, GFP_KERNEL); + if (!ei->name) { + kfree(ei); + return NULL; } + kref_init(&ei->kref); return ei; } - /** * eventfs_d_release - dentry is going away * @dentry: dentry which has the reference to remove. @@ -750,7 +754,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry INIT_LIST_HEAD(&ei->list); ti = get_tracefs(inode); - ti->flags = TRACEFS_EVENT_INODE | TRACEFS_EVENT_TOP_INODE; + ti->flags |= TRACEFS_EVENT_INODE | TRACEFS_EVENT_TOP_INODE; ti->private = ei; inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; @@ -847,5 +851,6 @@ void eventfs_remove_events_dir(struct eventfs_inode *ei) * sticks around while the other ei->dentry are created * and destroyed dynamically. */ + d_invalidate(dentry); dput(dentry); } diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c index 64122787e5d0..cf90ea86baf8 100644 --- a/fs/tracefs/inode.c +++ b/fs/tracefs/inode.c @@ -38,8 +38,6 @@ static struct inode *tracefs_alloc_inode(struct super_block *sb) if (!ti) return NULL; - ti->flags = 0; - return &ti->vfs_inode; } @@ -506,75 +504,6 @@ struct dentry *tracefs_end_creating(struct dentry *dentry) return dentry; } -/** - * eventfs_start_creating - start the process of creating a dentry - * @name: Name of the file created for the dentry - * @parent: The parent dentry where this dentry will be created - * - * This is a simple helper function for the dynamically created eventfs - * files. When the directory of the eventfs files are accessed, their - * dentries are created on the fly. This function is used to start that - * process. - */ -struct dentry *eventfs_start_creating(const char *name, struct dentry *parent) -{ - struct dentry *dentry; - int error; - - /* Must always have a parent. */ - if (WARN_ON_ONCE(!parent)) - return ERR_PTR(-EINVAL); - - error = simple_pin_fs(&trace_fs_type, &tracefs_mount, - &tracefs_mount_count); - if (error) - return ERR_PTR(error); - - if (unlikely(IS_DEADDIR(parent->d_inode))) - dentry = ERR_PTR(-ENOENT); - else - dentry = lookup_one_len(name, parent, strlen(name)); - - if (!IS_ERR(dentry) && dentry->d_inode) { - dput(dentry); - dentry = ERR_PTR(-EEXIST); - } - - if (IS_ERR(dentry)) - simple_release_fs(&tracefs_mount, &tracefs_mount_count); - - return dentry; -} - -/** - * eventfs_failed_creating - clean up a failed eventfs dentry creation - * @dentry: The dentry to clean up - * - * If after calling eventfs_start_creating(), a failure is detected, the - * resources created by eventfs_start_creating() needs to be cleaned up. In - * that case, this function should be called to perform that clean up. - */ -struct dentry *eventfs_failed_creating(struct dentry *dentry) -{ - dput(dentry); - simple_release_fs(&tracefs_mount, &tracefs_mount_count); - return NULL; -} - -/** - * eventfs_end_creating - Finish the process of creating a eventfs dentry - * @dentry: The dentry that has successfully been created. - * - * This function is currently just a place holder to match - * eventfs_start_creating(). In case any synchronization needs to be added, - * this function will be used to implement that without having to modify - * the callers of eventfs_start_creating(). - */ -struct dentry *eventfs_end_creating(struct dentry *dentry) -{ - return dentry; -} - /* Find the inode that this will use for default */ static struct inode *instance_inode(struct dentry *parent, struct inode *inode) { @@ -788,6 +717,7 @@ static void init_once(void *foo) { struct tracefs_inode *ti = (struct tracefs_inode *) foo; + memset(ti, 0, sizeof(*ti)); inode_init_once(&ti->vfs_inode); } diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h index d4194466b643..ca1ccc86986f 100644 --- a/fs/tracefs/internal.h +++ b/fs/tracefs/internal.h @@ -46,6 +46,7 @@ struct eventfs_inode { struct kref kref; struct list_head list; const struct eventfs_entry *entries; + const char *name; struct list_head children; struct dentry *events_dir; struct eventfs_attr *entry_attrs; @@ -64,7 +65,6 @@ struct eventfs_inode { struct llist_node llist; struct rcu_head rcu; }; - const char name[]; }; static inline struct tracefs_inode *get_tracefs(const struct inode *inode) @@ -76,9 +76,6 @@ struct dentry *tracefs_start_creating(const char *name, struct dentry *parent); struct dentry *tracefs_end_creating(struct dentry *dentry); struct dentry *tracefs_failed_creating(struct dentry *dentry); struct inode *tracefs_get_inode(struct super_block *sb); -struct dentry *eventfs_start_creating(const char *name, struct dentry *parent); -struct dentry *eventfs_failed_creating(struct dentry *dentry); -struct dentry *eventfs_end_creating(struct dentry *dentry); void eventfs_d_release(struct dentry *dentry);