Dominique Martinet wrote on Fri, Apr 28, 2023 at 03:14:52PM +0900: > > AFAICT, the io_uring code wouldn't need to do much more other than > > punt to the work queue if it receives a -EAGAIN result. Otherwise > > the what the filesystem returns doesn't need to change, and I don't > > see that we need to change how the filldir callbacks work, either. > > We just keep filling the user buffer until we either run out of > > cached directory data or the user buffer is full. > > [...] I'd like to confirm what the uring > side needs to do before proceeding -- looking at the read/write path > there seems to be a polling mechanism in place to tell uring when to > look again, and I haven't looked at this part of the code yet to see > what happens if no such polling is in place (does uring just retry > periodically?) Ok so this part can work out as you said, I hadn't understood what you meant by "punt to the work queue" but that should work from my new understanding of the ring; we can just return EAGAIN if the non-blocking variant doesn't have immediate results and call the blocking variant when we're called again without IO_URING_F_NONBLOCK in flags. (So there's no need to try to add a form of polling, although that is possible if we ever become able to do that; I'll just forget about this and be happy this part is easy) That just leaves deciding if a filesystem handles the blocking variant or not; ideally if we can know early (prep time) we can even mark REQ_F_FORCE_ASYNC in flags to skip the non-blocking call for filesystems that don't handle that and we get the best of both worlds. I've had a second look and I still don't see anything obvious though; I'd rather avoid adding a new variant of iterate()/iterate_shared() -- we could use that as a chance to add a flag to struct file_operation instead? e.g., something like mmap_supported_flags: ----- diff --git a/include/linux/fs.h b/include/linux/fs.h index c85916e9f7db..2ebbf48ee18b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1761,7 +1761,7 @@ struct file_operations { int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *, unsigned int flags); int (*iterate) (struct file *, struct dir_context *); - int (*iterate_shared) (struct file *, struct dir_context *); + unsigned long iterate_supported_flags; __poll_t (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); @@ -1797,6 +1797,10 @@ struct file_operations { unsigned int poll_flags); } __randomize_layout; +/** iterate_supported_flags */ +#define ITERATE_SHARED 0x1 +#define ITERATE_NOWAIT 0x2 + struct inode_operations { struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); ----- and fix all usages of iterate_shared. I guess at this rate it might make sense to rename mmap_supported_flags to some more generic supported_flags instead?... It's a bit more than I have signed up for, but I guess it's still reasonable enough. I'll wait for feedback before doing it though; please say if this sounds good to you and I'll send a v2 with such a flag, as well as adding flags to dir_context as you had suggested. Thanks, -- Dominique Martinet | Asmadeus