Message ID | 20230918150313.3845114-8-bschubert@ddn.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fuse direct write consolidation and parallel IO | expand |
Hi Bernd, kernel test robot noticed the following build warnings: [auto build test WARNING on mszeredi-fuse/for-next] [also build test WARNING on linus/master v6.6-rc2 next-20230918] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Bernd-Schubert/fuse-direct-IO-can-use-the-write-through-code-path/20230919-005745 base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next patch link: https://lore.kernel.org/r/20230918150313.3845114-8-bschubert%40ddn.com patch subject: [PATCH v4 07/10] fuse: Remove fuse_direct_write_iter code path / use IOCB_DIRECT config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20230919/202309190423.cEQ7h6ai-lkp@intel.com/config) compiler: m68k-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230919/202309190423.cEQ7h6ai-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202309190423.cEQ7h6ai-lkp@intel.com/ All warnings (new ones prefixed by >>): >> fs/fuse/file.c:1060: warning: Function parameter or member 'iocb' not described in 'fuse_write_flags' >> fs/fuse/file.c:1060: warning: expecting prototype for Note(). Prototype was for fuse_write_flags() instead vim +1060 fs/fuse/file.c 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1054 abb63dd79fa5c1 Bernd Schubert 2023-09-18 1055 /** abb63dd79fa5c1 Bernd Schubert 2023-09-18 1056 * Note: iocb->ki_flags & IOCB_DIRECT cannot be trusted here, abb63dd79fa5c1 Bernd Schubert 2023-09-18 1057 * it might be set when FOPEN_DIRECT_IO is used. abb63dd79fa5c1 Bernd Schubert 2023-09-18 1058 */ 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1059 static unsigned int fuse_write_flags(struct kiocb *iocb) 338f2e3f3341a9 Miklos Szeredi 2019-09-10 @1060 { 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1061 unsigned int flags = iocb->ki_filp->f_flags; 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1062 91b94c5d6ae55d Al Viro 2022-05-22 1063 if (iocb_is_dsync(iocb)) 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1064 flags |= O_DSYNC; 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1065 if (iocb->ki_flags & IOCB_SYNC) 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1066 flags |= O_SYNC; 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1067 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1068 return flags; 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1069 } 338f2e3f3341a9 Miklos Szeredi 2019-09-10 1070
On 9/18/23 22:13, kernel test robot wrote: > Hi Bernd, > > kernel test robot noticed the following build warnings: > > [auto build test WARNING on mszeredi-fuse/for-next] Thanks, updated patch: --- From: Bernd Schubert <bschubert@ddn.com> Subject: fuse: Remove fuse_direct_write_iter code path / use IOCB_DIRECT fuse_direct_write_iter is basically duplicating what is already in fuse_cache_write_iter/generic_file_direct_write. That can be avoided by setting IOCB_DIRECT in fuse_file_write_iter, after that fuse_cache_write_iter can be used for the FOPEN_DIRECT_IO code path and fuse_direct_write_iter can be removed. Before it was using for FOPEN_DIRECT_IO 1) async (!is_sync_kiocb(iocb)) && IOCB_DIRECT fuse_file_write_iter fuse_direct_write_iter fuse_direct_IO fuse_send_dio 2) sync (is_sync_kiocb(iocb)) or IOCB_DIRECT not being set fuse_file_write_iter fuse_direct_write_iter fuse_send_dio 3) FOPEN_DIRECT_IO not set Same as the consolidates path below The new consolidated code path is always fuse_file_write_iter fuse_cache_write_iter generic_file_write_iter __generic_file_write_iter generic_file_direct_write mapping->a_ops->direct_IO / fuse_direct_IO fuse_send_dio So in general for FOPEN_DIRECT_IO the code path gets longer. Additionally fuse_direct_IO does an allocation of struct fuse_io_priv - might be a bit slower in micro benchmarks. Also, the IOCB_DIRECT information gets lost (as we now set it outselves). But then IOCB_DIRECT is directly related to O_DIRECT set in struct file::f_flags. An additional change is for condition 2 above, which might will now do async IO on the condition ff->fm->fc->async_dio. Given that async IO for FOPEN_DIRECT_IO was especially introduced in commit 'commit 23c94e1cdcbf ("fuse: Switch to using async direct IO for FOPEN_DIRECT_IO")' it should not matter. Especially as fuse_direct_IO is blocking for is_sync_kiocb(), at worst it has another slight overhead. Advantage is the removal of code paths and conditions and it is now also possible to remove FOPEN_DIRECT_IO conditions in fuse_send_dio (in a later patch). Cc: Hao Xu <howeyxu@tencent.com> Cc: Miklos Szeredi <miklos@szeredi.hu> Cc: Dharmendra Singh <dsingh@ddn.com> Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Bernd Schubert <bschubert@ddn.com> --- fs/fuse/file.c | 60 +++++++++----------------------------------------- 1 file changed, 10 insertions(+), 50 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 24fa6cab836f..41e10e6f5aa4 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1061,6 +1061,12 @@ static unsigned int fuse_write_flags(struct kiocb *iocb) if (iocb->ki_flags & IOCB_SYNC) flags |= O_SYNC; + /* + * Note: If O_DIRECT should be ever added here, + * iocb->ki_flags & IOCB_DIRECT cannot be trusted when + * FOPEN_DIRECT_IO is set. + */ + return flags; } @@ -1631,52 +1637,6 @@ static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to) return res; } -static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) -{ - struct inode *inode = file_inode(iocb->ki_filp); - struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); - ssize_t res; - bool exclusive_lock = fuse_dio_wr_exclusive_lock(iocb, from, inode); - - /* - * Take exclusive lock if - * - Parallel direct writes are disabled - a user space decision - * - Parallel direct writes are enabled and i_size is being extended. - * This might not be needed at all, but needs further investigation. - */ - if (exclusive_lock) - inode_lock(inode); - else { - inode_lock_shared(inode); - - /* A race with truncate might have come up as the decision for - * the lock type was done without holding the lock, check again. - */ - if (fuse_io_past_eof(iocb, from)) { - inode_unlock_shared(inode); - inode_lock(inode); - exclusive_lock = true; - } - } - - res = generic_write_checks(iocb, from); - if (res > 0) { - if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) { - res = fuse_direct_IO(iocb, from); - } else { - res = fuse_send_dio(&io, from, &iocb->ki_pos, - FUSE_DIO_WRITE); - fuse_write_update_attr(inode, iocb->ki_pos, res); - } - } - if (exclusive_lock) - inode_unlock(inode); - else - inode_unlock_shared(inode); - - return res; -} - static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct file *file = iocb->ki_filp; @@ -1707,10 +1667,10 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (FUSE_IS_DAX(inode)) return fuse_dax_write_iter(iocb, from); - if (!(ff->open_flags & FOPEN_DIRECT_IO)) - return fuse_cache_write_iter(iocb, from); - else - return fuse_direct_write_iter(iocb, from); + if (ff->open_flags & FOPEN_DIRECT_IO) + iocb->ki_flags |= IOCB_DIRECT; + + return fuse_cache_write_iter(iocb, from); } static void fuse_writepage_free(struct fuse_writepage_args *wpa)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 24fa6cab836f..a5285a9e36e3 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1052,6 +1052,10 @@ static void fuse_write_args_fill(struct fuse_io_args *ia, struct fuse_file *ff, args->out_args[0].value = &ia->write.out; } +/** + * Note: iocb->ki_flags & IOCB_DIRECT cannot be trusted here, + * it might be set when FOPEN_DIRECT_IO is used. + */ static unsigned int fuse_write_flags(struct kiocb *iocb) { unsigned int flags = iocb->ki_filp->f_flags; @@ -1631,52 +1635,6 @@ static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to) return res; } -static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) -{ - struct inode *inode = file_inode(iocb->ki_filp); - struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); - ssize_t res; - bool exclusive_lock = fuse_dio_wr_exclusive_lock(iocb, from, inode); - - /* - * Take exclusive lock if - * - Parallel direct writes are disabled - a user space decision - * - Parallel direct writes are enabled and i_size is being extended. - * This might not be needed at all, but needs further investigation. - */ - if (exclusive_lock) - inode_lock(inode); - else { - inode_lock_shared(inode); - - /* A race with truncate might have come up as the decision for - * the lock type was done without holding the lock, check again. - */ - if (fuse_io_past_eof(iocb, from)) { - inode_unlock_shared(inode); - inode_lock(inode); - exclusive_lock = true; - } - } - - res = generic_write_checks(iocb, from); - if (res > 0) { - if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) { - res = fuse_direct_IO(iocb, from); - } else { - res = fuse_send_dio(&io, from, &iocb->ki_pos, - FUSE_DIO_WRITE); - fuse_write_update_attr(inode, iocb->ki_pos, res); - } - } - if (exclusive_lock) - inode_unlock(inode); - else - inode_unlock_shared(inode); - - return res; -} - static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct file *file = iocb->ki_filp; @@ -1707,10 +1665,10 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (FUSE_IS_DAX(inode)) return fuse_dax_write_iter(iocb, from); - if (!(ff->open_flags & FOPEN_DIRECT_IO)) - return fuse_cache_write_iter(iocb, from); - else - return fuse_direct_write_iter(iocb, from); + if (ff->open_flags & FOPEN_DIRECT_IO) + iocb->ki_flags |= IOCB_DIRECT; + + return fuse_cache_write_iter(iocb, from); } static void fuse_writepage_free(struct fuse_writepage_args *wpa)
fuse_direct_write_iter is basically duplicating what is already in fuse_cache_write_iter/generic_file_direct_write. That can be avoided by setting IOCB_DIRECT in fuse_file_write_iter, after that fuse_cache_write_iter can be used for the FOPEN_DIRECT_IO code path and fuse_direct_write_iter can be removed. Before it was using for FOPEN_DIRECT_IO 1) async (!is_sync_kiocb(iocb)) && IOCB_DIRECT fuse_file_write_iter fuse_direct_write_iter fuse_direct_IO fuse_send_dio 2) sync (is_sync_kiocb(iocb)) or IOCB_DIRECT not being set fuse_file_write_iter fuse_direct_write_iter fuse_send_dio 3) FOPEN_DIRECT_IO not set Same as the consolidates path below The new consolidated code path is always fuse_file_write_iter fuse_cache_write_iter generic_file_write_iter __generic_file_write_iter generic_file_direct_write mapping->a_ops->direct_IO / fuse_direct_IO fuse_send_dio So in general for FOPEN_DIRECT_IO the code path gets longer. Additionally fuse_direct_IO does an allocation of struct fuse_io_priv - might be a bit slower in micro benchmarks. Also, the IOCB_DIRECT information gets lost (as we now set it outselves). But then IOCB_DIRECT is directly related to O_DIRECT set in struct file::f_flags. An additional change is for condition 2 above, which might will now do async IO on the condition ff->fm->fc->async_dio. Given that async IO for FOPEN_DIRECT_IO was especially introduced in commit 'commit 23c94e1cdcbf ("fuse: Switch to using async direct IO for FOPEN_DIRECT_IO")' it should not matter. Especially as fuse_direct_IO is blocking for is_sync_kiocb(), at worst it has another slight overhead. Advantage is the removal of code paths and conditions and it is now also possible to remove FOPEN_DIRECT_IO conditions in fuse_send_dio (in a later patch). Cc: Hao Xu <howeyxu@tencent.com> Cc: Miklos Szeredi <miklos@szeredi.hu> Cc: Dharmendra Singh <dsingh@ddn.com> Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Bernd Schubert <bschubert@ddn.com> --- fs/fuse/file.c | 58 +++++++------------------------------------------- 1 file changed, 8 insertions(+), 50 deletions(-)