On Thu, Oct 03, 2024 at 01:45:55PM +0200, Jan Kara wrote:
> /* Find next inode on the inode list eligible for processing */
> #define sb_inode_iter_next(sb, inode, old_inode, inode_eligible)      \
> ({                                                                    \
>       struct inode *ret = NULL;                                       \

<snip>

>       ret;                                                            \
> })

How is this going to interact with calling into the file system
to do the interaction, which is kinda the point of this series?

Sure, you could have a get_next_inode-style method, but it would need
a fair amount of entirely file system specific state that needs
to be stashed away somewhere, and all options for that looks pretty
ugly.

Also even with your pre-iget callback we'd at best halve the number
of indirect calls for something that isn't exactly performance
critical.  So while it could be done that way, it feels like a
more complex and much harder to reason about version for no real
benefit.

> #define for_each_sb_inode(sb, inode, inode_eligible)                  \
>       for (DEFINE_FREE(old_inode, struct inode *, if (_T) iput(_T)),  \
>            inode = NULL;                                              \
>            inode = sb_inode_iter_next((sb), inode, &old_inode,        \
>                                        inode_eligible);               \
>           )

And while I liked:

        obj = NULL;

        while ((obj = get_next_object(foo, obj))) {
        }

style iterators, magic for_each macros that do magic cleanup are just
a nightmare to read.  Keep it simple and optimize for someone actually
having to read and understand the code, and not for saving a few lines
of code.


Reply via email to