Skip to content

Commit 493ec81

Browse files
committed
eventfs: Stop using dcache_readdir() for getdents()
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@goodmis.org Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Ajay Kaher <akaher@vmware.com> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Christian Brauner <brauner@kernel.org> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent b0f7e2d commit 493ec81

1 file changed

Lines changed: 64 additions & 130 deletions

File tree

fs/tracefs/event_inode.c

Lines changed: 64 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@ enum {
5252
static struct dentry *eventfs_root_lookup(struct inode *dir,
5353
struct dentry *dentry,
5454
unsigned int flags);
55-
static int dcache_dir_open_wrapper(struct inode *inode, struct file *file);
56-
static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx);
57-
static int eventfs_release(struct inode *inode, struct file *file);
55+
static int eventfs_iterate(struct file *file, struct dir_context *ctx);
5856

5957
static void update_attr(struct eventfs_attr *attr, struct iattr *iattr)
6058
{
@@ -148,11 +146,9 @@ static const struct inode_operations eventfs_file_inode_operations = {
148146
};
149147

150148
static const struct file_operations eventfs_file_operations = {
151-
.open = dcache_dir_open_wrapper,
152149
.read = generic_read_dir,
153-
.iterate_shared = dcache_readdir_wrapper,
150+
.iterate_shared = eventfs_iterate,
154151
.llseek = generic_file_llseek,
155-
.release = eventfs_release,
156152
};
157153

158154
/* Return the evenfs_inode of the "events" directory */
@@ -643,128 +639,87 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
643639
return ret;
644640
}
645641

646-
struct dentry_list {
647-
void *cursor;
648-
struct dentry **dentries;
649-
};
650-
651-
/**
652-
* eventfs_release - called to release eventfs file/dir
653-
* @inode: inode to be released
654-
* @file: file to be released (not used)
655-
*/
656-
static int eventfs_release(struct inode *inode, struct file *file)
657-
{
658-
struct tracefs_inode *ti;
659-
struct dentry_list *dlist = file->private_data;
660-
void *cursor;
661-
int i;
662-
663-
ti = get_tracefs(inode);
664-
if (!(ti->flags & TRACEFS_EVENT_INODE))
665-
return -EINVAL;
666-
667-
if (WARN_ON_ONCE(!dlist))
668-
return -EINVAL;
669-
670-
for (i = 0; dlist->dentries && dlist->dentries[i]; i++) {
671-
dput(dlist->dentries[i]);
672-
}
673-
674-
cursor = dlist->cursor;
675-
kfree(dlist->dentries);
676-
kfree(dlist);
677-
file->private_data = cursor;
678-
return dcache_dir_close(inode, file);
679-
}
680-
681-
static int add_dentries(struct dentry ***dentries, struct dentry *d, int cnt)
682-
{
683-
struct dentry **tmp;
684-
685-
tmp = krealloc(*dentries, sizeof(d) * (cnt + 2), GFP_NOFS);
686-
if (!tmp)
687-
return -1;
688-
tmp[cnt] = d;
689-
tmp[cnt + 1] = NULL;
690-
*dentries = tmp;
691-
return 0;
692-
}
693-
694-
/**
695-
* dcache_dir_open_wrapper - eventfs open wrapper
696-
* @inode: not used
697-
* @file: dir to be opened (to create it's children)
698-
*
699-
* Used to dynamic create file/dir with-in @file, all the
700-
* file/dir will be created. If already created then references
701-
* will be increased
642+
/*
643+
* Walk the children of a eventfs_inode to fill in getdents().
702644
*/
703-
static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
645+
static int eventfs_iterate(struct file *file, struct dir_context *ctx)
704646
{
705647
const struct file_operations *fops;
648+
struct inode *f_inode = file_inode(file);
706649
const struct eventfs_entry *entry;
707650
struct eventfs_inode *ei_child;
708651
struct tracefs_inode *ti;
709652
struct eventfs_inode *ei;
710-
struct dentry_list *dlist;
711-
struct dentry **dentries = NULL;
712-
struct dentry *parent = file_dentry(file);
713-
struct dentry *d;
714-
struct inode *f_inode = file_inode(file);
715-
const char *name = parent->d_name.name;
653+
struct dentry *ei_dentry = NULL;
654+
struct dentry *dentry;
655+
const char *name;
716656
umode_t mode;
717-
void *data;
718-
int cnt = 0;
719657
int idx;
720-
int ret;
721-
int i;
722-
int r;
658+
int ret = -EINVAL;
659+
int ino;
660+
int i, r, c;
661+
662+
if (!dir_emit_dots(file, ctx))
663+
return 0;
723664

724665
ti = get_tracefs(f_inode);
725666
if (!(ti->flags & TRACEFS_EVENT_INODE))
726667
return -EINVAL;
727668

728-
if (WARN_ON_ONCE(file->private_data))
729-
return -EINVAL;
669+
c = ctx->pos - 2;
730670

731671
idx = srcu_read_lock(&eventfs_srcu);
732672

733673
mutex_lock(&eventfs_mutex);
734674
ei = READ_ONCE(ti->private);
675+
if (ei && !ei->is_freed)
676+
ei_dentry = READ_ONCE(ei->dentry);
735677
mutex_unlock(&eventfs_mutex);
736678

737-
if (!ei) {
738-
srcu_read_unlock(&eventfs_srcu, idx);
739-
return -EINVAL;
740-
}
741-
742-
743-
data = ei->data;
679+
if (!ei || !ei_dentry)
680+
goto out;
744681

745-
dlist = kmalloc(sizeof(*dlist), GFP_KERNEL);
746-
if (!dlist) {
747-
srcu_read_unlock(&eventfs_srcu, idx);
748-
return -ENOMEM;
749-
}
682+
ret = 0;
750683

751-
inode_lock(parent->d_inode);
684+
/*
685+
* Need to create the dentries and inodes to have a consistent
686+
* inode number.
687+
*/
752688
list_for_each_entry_srcu(ei_child, &ei->children, list,
753689
srcu_read_lock_held(&eventfs_srcu)) {
754-
d = create_dir_dentry(ei, ei_child, parent);
755-
if (d) {
756-
ret = add_dentries(&dentries, d, cnt);
757-
dput(d);
758-
if (ret < 0)
759-
break;
760-
cnt++;
690+
691+
if (c > 0) {
692+
c--;
693+
continue;
761694
}
695+
696+
if (ei_child->is_freed)
697+
continue;
698+
699+
name = ei_child->name;
700+
701+
dentry = create_dir_dentry(ei, ei_child, ei_dentry);
702+
if (!dentry)
703+
goto out;
704+
ino = dentry->d_inode->i_ino;
705+
dput(dentry);
706+
707+
if (!dir_emit(ctx, name, strlen(name), ino, DT_DIR))
708+
goto out;
709+
ctx->pos++;
762710
}
763711

764712
for (i = 0; i < ei->nr_entries; i++) {
765-
void *cdata = data;
713+
void *cdata = ei->data;
714+
715+
if (c > 0) {
716+
c--;
717+
continue;
718+
}
719+
766720
entry = &ei->entries[i];
767721
name = entry->name;
722+
768723
mutex_lock(&eventfs_mutex);
769724
/* If ei->is_freed, then the event itself may be too */
770725
if (!ei->is_freed)
@@ -774,42 +729,21 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
774729
mutex_unlock(&eventfs_mutex);
775730
if (r <= 0)
776731
continue;
777-
d = create_file_dentry(ei, i, parent, name, mode, cdata, fops);
778-
if (d) {
779-
ret = add_dentries(&dentries, d, cnt);
780-
dput(d);
781-
if (ret < 0)
782-
break;
783-
cnt++;
784-
}
785-
}
786-
inode_unlock(parent->d_inode);
787-
srcu_read_unlock(&eventfs_srcu, idx);
788-
ret = dcache_dir_open(inode, file);
789732

790-
/*
791-
* dcache_dir_open() sets file->private_data to a dentry cursor.
792-
* Need to save that but also save all the dentries that were
793-
* opened by this function.
794-
*/
795-
dlist->cursor = file->private_data;
796-
dlist->dentries = dentries;
797-
file->private_data = dlist;
798-
return ret;
799-
}
733+
dentry = create_file_dentry(ei, i, ei_dentry, name, mode, cdata, fops);
734+
if (!dentry)
735+
goto out;
736+
ino = dentry->d_inode->i_ino;
737+
dput(dentry);
800738

801-
/*
802-
* This just sets the file->private_data back to the cursor and back.
803-
*/
804-
static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx)
805-
{
806-
struct dentry_list *dlist = file->private_data;
807-
int ret;
739+
if (!dir_emit(ctx, name, strlen(name), ino, DT_REG))
740+
goto out;
741+
ctx->pos++;
742+
}
743+
ret = 1;
744+
out:
745+
srcu_read_unlock(&eventfs_srcu, idx);
808746

809-
file->private_data = dlist->cursor;
810-
ret = dcache_readdir(file, ctx);
811-
dlist->cursor = file->private_data;
812-
file->private_data = dlist;
813747
return ret;
814748
}
815749

0 commit comments

Comments
 (0)