From nobody Fri Dec 26 17:40:51 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 173F62511D for ; Thu, 4 Jan 2024 16:46:32 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 82F05C433CB; Thu, 4 Jan 2024 16:46:32 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1rLQsc-00000000uJk-2dnw; Thu, 04 Jan 2024 11:47:38 -0500 Message-ID: <20240104164738.483305222@goodmis.org> User-Agent: quilt/0.67 Date: Thu, 04 Jan 2024 11:47:05 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Linus Torvalds , Ajay Kaher , Al Viro , Christian Brauner Subject: [for-next][PATCH 2/3] eventfs: Stop using dcache_readdir() for getdents() References: <20240104164703.808999991@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Steven Rostedt (Google)" The eventfs creates dynamically allocated dentries and inodes. Using the dcache_readdir() logic for its own directory lookups requires hiding the cursor of the dcache logic and playing games to allow the dcache_readdir() to still have access to the cursor while the eventfs saved what it created and what it needs to release. Instead, just have eventfs have its own iterate_shared callback function that will fill in the dent entries. This simplifies the code quite a bit. Link: https://lore.kernel.org/linux-trace-kernel/20240104015435.682218477@g= oodmis.org Cc: Masami Hiramatsu Cc: Mark Rutland Cc: Mathieu Desnoyers Cc: Linus Torvalds Cc: Ajay Kaher Cc: Al Viro Cc: Christian Brauner Signed-off-by: Steven Rostedt (Google) --- fs/tracefs/event_inode.c | 194 +++++++++++++-------------------------- 1 file changed, 64 insertions(+), 130 deletions(-) diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c index c360300fb866..41af56f44f0a 100644 --- a/fs/tracefs/event_inode.c +++ b/fs/tracefs/event_inode.c @@ -52,9 +52,7 @@ enum { static struct dentry *eventfs_root_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags); -static int dcache_dir_open_wrapper(struct inode *inode, struct file *file); -static int dcache_readdir_wrapper(struct file *file, struct dir_context *c= tx); -static int eventfs_release(struct inode *inode, struct file *file); +static int eventfs_iterate(struct file *file, struct dir_context *ctx); =20 static void update_attr(struct eventfs_attr *attr, struct iattr *iattr) { @@ -148,11 +146,9 @@ static const struct inode_operations eventfs_file_inod= e_operations =3D { }; =20 static const struct file_operations eventfs_file_operations =3D { - .open =3D dcache_dir_open_wrapper, .read =3D generic_read_dir, - .iterate_shared =3D dcache_readdir_wrapper, + .iterate_shared =3D eventfs_iterate, .llseek =3D generic_file_llseek, - .release =3D eventfs_release, }; =20 /* Return the evenfs_inode of the "events" directory */ @@ -643,128 +639,87 @@ static struct dentry *eventfs_root_lookup(struct ino= de *dir, return ret; } =20 -struct dentry_list { - void *cursor; - struct dentry **dentries; -}; - -/** - * eventfs_release - called to release eventfs file/dir - * @inode: inode to be released - * @file: file to be released (not used) - */ -static int eventfs_release(struct inode *inode, struct file *file) -{ - struct tracefs_inode *ti; - struct dentry_list *dlist =3D file->private_data; - void *cursor; - int i; - - ti =3D get_tracefs(inode); - if (!(ti->flags & TRACEFS_EVENT_INODE)) - return -EINVAL; - - if (WARN_ON_ONCE(!dlist)) - return -EINVAL; - - for (i =3D 0; dlist->dentries && dlist->dentries[i]; i++) { - dput(dlist->dentries[i]); - } - - cursor =3D dlist->cursor; - kfree(dlist->dentries); - kfree(dlist); - file->private_data =3D cursor; - return dcache_dir_close(inode, file); -} - -static int add_dentries(struct dentry ***dentries, struct dentry *d, int c= nt) -{ - struct dentry **tmp; - - tmp =3D krealloc(*dentries, sizeof(d) * (cnt + 2), GFP_NOFS); - if (!tmp) - return -1; - tmp[cnt] =3D d; - tmp[cnt + 1] =3D NULL; - *dentries =3D tmp; - return 0; -} - -/** - * dcache_dir_open_wrapper - eventfs open wrapper - * @inode: not used - * @file: dir to be opened (to create it's children) - * - * Used to dynamic create file/dir with-in @file, all the - * file/dir will be created. If already created then references - * will be increased +/* + * Walk the children of a eventfs_inode to fill in getdents(). */ -static int dcache_dir_open_wrapper(struct inode *inode, struct file *file) +static int eventfs_iterate(struct file *file, struct dir_context *ctx) { const struct file_operations *fops; + struct inode *f_inode =3D file_inode(file); const struct eventfs_entry *entry; struct eventfs_inode *ei_child; struct tracefs_inode *ti; struct eventfs_inode *ei; - struct dentry_list *dlist; - struct dentry **dentries =3D NULL; - struct dentry *parent =3D file_dentry(file); - struct dentry *d; - struct inode *f_inode =3D file_inode(file); - const char *name =3D parent->d_name.name; + struct dentry *ei_dentry =3D NULL; + struct dentry *dentry; + const char *name; umode_t mode; - void *data; - int cnt =3D 0; int idx; - int ret; - int i; - int r; + int ret =3D -EINVAL; + int ino; + int i, r, c; + + if (!dir_emit_dots(file, ctx)) + return 0; =20 ti =3D get_tracefs(f_inode); if (!(ti->flags & TRACEFS_EVENT_INODE)) return -EINVAL; =20 - if (WARN_ON_ONCE(file->private_data)) - return -EINVAL; + c =3D ctx->pos - 2; =20 idx =3D srcu_read_lock(&eventfs_srcu); =20 mutex_lock(&eventfs_mutex); ei =3D READ_ONCE(ti->private); + if (ei && !ei->is_freed) + ei_dentry =3D READ_ONCE(ei->dentry); mutex_unlock(&eventfs_mutex); =20 - if (!ei) { - srcu_read_unlock(&eventfs_srcu, idx); - return -EINVAL; - } - - - data =3D ei->data; + if (!ei || !ei_dentry) + goto out; =20 - dlist =3D kmalloc(sizeof(*dlist), GFP_KERNEL); - if (!dlist) { - srcu_read_unlock(&eventfs_srcu, idx); - return -ENOMEM; - } + ret =3D 0; =20 - inode_lock(parent->d_inode); + /* + * Need to create the dentries and inodes to have a consistent + * inode number. + */ list_for_each_entry_srcu(ei_child, &ei->children, list, srcu_read_lock_held(&eventfs_srcu)) { - d =3D create_dir_dentry(ei, ei_child, parent); - if (d) { - ret =3D add_dentries(&dentries, d, cnt); - dput(d); - if (ret < 0) - break; - cnt++; + + if (c > 0) { + c--; + continue; } + + if (ei_child->is_freed) + continue; + + name =3D ei_child->name; + + dentry =3D create_dir_dentry(ei, ei_child, ei_dentry); + if (!dentry) + goto out; + ino =3D dentry->d_inode->i_ino; + dput(dentry); + + if (!dir_emit(ctx, name, strlen(name), ino, DT_DIR)) + goto out; + ctx->pos++; } =20 for (i =3D 0; i < ei->nr_entries; i++) { - void *cdata =3D data; + void *cdata =3D ei->data; + + if (c > 0) { + c--; + continue; + } + entry =3D &ei->entries[i]; name =3D entry->name; + mutex_lock(&eventfs_mutex); /* If ei->is_freed, then the event itself may be too */ if (!ei->is_freed) @@ -774,42 +729,21 @@ static int dcache_dir_open_wrapper(struct inode *inod= e, struct file *file) mutex_unlock(&eventfs_mutex); if (r <=3D 0) continue; - d =3D create_file_dentry(ei, i, parent, name, mode, cdata, fops); - if (d) { - ret =3D add_dentries(&dentries, d, cnt); - dput(d); - if (ret < 0) - break; - cnt++; - } - } - inode_unlock(parent->d_inode); - srcu_read_unlock(&eventfs_srcu, idx); - ret =3D dcache_dir_open(inode, file); =20 - /* - * dcache_dir_open() sets file->private_data to a dentry cursor. - * Need to save that but also save all the dentries that were - * opened by this function. - */ - dlist->cursor =3D file->private_data; - dlist->dentries =3D dentries; - file->private_data =3D dlist; - return ret; -} + dentry =3D create_file_dentry(ei, i, ei_dentry, name, mode, cdata, fops); + if (!dentry) + goto out; + ino =3D dentry->d_inode->i_ino; + dput(dentry); =20 -/* - * This just sets the file->private_data back to the cursor and back. - */ -static int dcache_readdir_wrapper(struct file *file, struct dir_context *c= tx) -{ - struct dentry_list *dlist =3D file->private_data; - int ret; + if (!dir_emit(ctx, name, strlen(name), ino, DT_REG)) + goto out; + ctx->pos++; + } + ret =3D 1; + out: + srcu_read_unlock(&eventfs_srcu, idx); =20 - file->private_data =3D dlist->cursor; - ret =3D dcache_readdir(file, ctx); - dlist->cursor =3D file->private_data; - file->private_data =3D dlist; return ret; } =20 --=20 2.42.0