The current iterate_dir() infrastructure is somewhat cumbersome to use from within the kernel. Introduce a lighter weight simple_iterate_dir() function that directly iterates the directory and executes a callback for each positive dentry. Signed-off-by: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> --- fs/libfs.c | 33 +++++++++++++++++++++++++++++++++ include/linux/fs.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/fs/libfs.c b/fs/libfs.c index 816bfe6c0430..37da5fe25242 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -214,6 +214,39 @@ static void internal_readdir(struct dentry *dentry, struct dentry *cursor, dput(next); } +/** + * generic_iterate_call - iterate all entries executing @callback + * + * @dir: directory to iterate over + * @data: data passed to callback + * @callback: callback to call + * + * Iterates over all positive dentries that are direct children of + * @dir (so doesn't include . and ..) and executes the callback for + * each of them. Note that because there's no struct *mnt, the caller + * is responsible for pinning the filesystem. + * + * If the @callback returns true, the iteration will continue and if + * it returns @false, it will stop (note that since the cursor is + * destroyed the next invocation will go back to the beginning again). + * + */ +int simple_iterate_call(struct dentry *dir, void *data, + bool (*callback)(void *, struct dentry *)) +{ + struct dentry *cursor = d_alloc_cursor(dir); + + if (!cursor) + return -ENOMEM; + + internal_readdir(dir, cursor, data, true, callback); + + dput(cursor); + + return 0; +} +EXPORT_SYMBOL(simple_iterate_call); + static bool dcache_readdir_callback(void *data, struct dentry *entry) { struct dir_context *ctx = data; diff --git a/include/linux/fs.h b/include/linux/fs.h index 2788df98080f..a84896f0b2d1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3531,6 +3531,8 @@ extern int simple_rename(struct mnt_idmap *, struct inode *, unsigned int); extern void simple_recursive_removal(struct dentry *, void (*callback)(struct dentry *)); +extern int simple_iterate_call(struct dentry *dir, void *data, + bool (*callback)(void *, struct dentry *)); extern int noop_fsync(struct file *, loff_t, loff_t, int); extern ssize_t noop_direct_IO(struct kiocb *iocb, struct iov_iter *iter); extern int simple_empty(struct dentry *); -- 2.43.0