Hi James, Thanks for persisting with this. On Tue, 18 Mar 2025 at 20:44, James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> wrote: > > No functional change. Preparatory to using the internal function to > iterate a directory with just a dentry not a file. > > Signed-off-by: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> > --- > fs/libfs.c | 41 +++++++++++++++++++++++++++++------------ > 1 file changed, 29 insertions(+), 12 deletions(-) > > diff --git a/fs/libfs.c b/fs/libfs.c > index 8444f5cc4064..816bfe6c0430 100644 > --- a/fs/libfs.c > +++ b/fs/libfs.c > @@ -189,28 +189,21 @@ EXPORT_SYMBOL(dcache_dir_lseek); > * for ramfs-type trees they can't go away without unlink() or rmdir(), > * both impossible due to the lock on directory. > */ > - > -int dcache_readdir(struct file *file, struct dir_context *ctx) > +static void internal_readdir(struct dentry *dentry, struct dentry *cursor, It might make sense to make this __always_inline, so that the callback argument is guaranteed to become a compile time constant when the caller is dcache_readdir(). Otherwise, the indirect call overhead might impact its performance. > + void *data, bool start, > + bool (*callback)(void *, struct dentry *)) > { > - struct dentry *dentry = file->f_path.dentry; > - struct dentry *cursor = file->private_data; > struct dentry *next = NULL; > struct hlist_node **p; > > - if (!dir_emit_dots(file, ctx)) > - return 0; > - > - if (ctx->pos == 2) > + if (start) > p = &dentry->d_children.first; > else > p = &cursor->d_sib.next; > > while ((next = scan_positives(cursor, p, 1, next)) != NULL) { > - if (!dir_emit(ctx, next->d_name.name, next->d_name.len, > - d_inode(next)->i_ino, > - fs_umode_to_dtype(d_inode(next)->i_mode))) > + if (!callback(data, next)) > break; > - ctx->pos++; > p = &next->d_sib.next; > } > spin_lock(&dentry->d_lock); > @@ -219,6 +212,30 @@ int dcache_readdir(struct file *file, struct dir_context *ctx) > hlist_add_before(&cursor->d_sib, &next->d_sib); > spin_unlock(&dentry->d_lock); > dput(next); > +} > + > +static bool dcache_readdir_callback(void *data, struct dentry *entry) > +{ > + struct dir_context *ctx = data; > + > + if (!dir_emit(ctx, entry->d_name.name, entry->d_name.len, > + d_inode(entry)->i_ino, > + fs_umode_to_dtype(d_inode(entry)->i_mode))) > + return false; > + ctx->pos++; > + return true; > +} > + > +int dcache_readdir(struct file *file, struct dir_context *ctx) > +{ > + struct dentry *dentry = file->f_path.dentry; > + struct dentry *cursor = file->private_data; > + > + if (!dir_emit_dots(file, ctx)) > + return 0; > + > + internal_readdir(dentry, cursor, ctx, ctx->pos == 2, > + dcache_readdir_callback); > > return 0; > } > -- > 2.43.0 >