Already applied: 4dc73eb6adc3d fs/fuse: force offload of final fput in aio completion to workqueue
-- Best regards, Konstantin Khorenko, Virtuozzo Linux Kernel Team On 6/25/26 20:16, Eva Kurchatova wrote: > From: Alexey Kuznetsov <[email protected]> > > The patch is known as "fuse: queue work for aio_complete (v3)", > here is its simpler form. > > aio completion is executed in context of userspace worker thread. > Final fput might make lots of additional work like updating mtime, > releasing file, which could be routed to the same thread. > The problem is not specific to vstorage, all decent fuse fses > suffer of this. The code as is works only with low performance > fses based on libfuse. Also, current version of vstorage > is not supposed suffer if this problem because aio completions > are guaranteed to be done in threads different of threads > working on metadata. Yet, it can be configured, deliberately > or by mistake to route everything to one thread. > > Use workqueue supplied by vfs, all kernels in use (rh7,9,10) > offload final fput to workqueue when fput() is called from > interrupt or kthread context. So, we grab reference to file > before ki_complete() and release it afterwards surrounded > with local_bh_disable/local_bh_enable pair. It looks like > a good pragmatic solution with minimal impact on performance > and maintanance cost. > > Signed-off-by: Alexey Kuznetsov <[email protected]> > --- > fs/fuse/file.c | 15 +++++++++++++++ > 1 file changed, 15 insertions(+) > > diff --git a/fs/fuse/file.c b/fs/fuse/file.c > index 40cded85037f..c812420cc109 100644 > --- a/fs/fuse/file.c > +++ b/fs/fuse/file.c > @@ -18,6 +18,7 @@ > #include <linux/falloc.h> > #include <linux/uio.h> > #include <linux/fs.h> > +#include <linux/file.h> > #include <linux/filelock.h> > #include <linux/splice.h> > #include <linux/task_io_accounting_ops.h> > @@ -971,6 +972,7 @@ static void fuse_aio_complete(struct fuse_io_priv *io, > int err, ssize_t pos) > > if (!left && !io->blocking) { > ssize_t res = fuse_get_res_by_io(io); > + struct file *file = io->iocb->ki_filp; > > if (res >= 0) { > struct inode *inode = file_inode(io->iocb->ki_filp); > @@ -989,7 +991,20 @@ static void fuse_aio_complete(struct fuse_io_priv *io, > int err, ssize_t pos) > io->iocb->ki_flags, io->iocb->ki_pos); > } > > + /* We have to bump f_count here to avoid deadlock for > + * single-threaded fuse daemon: if the process that generated > + * AIO is already close(2) the file, fput() called from > + * aio_complete will be the last fput(); hence, it will send > + * flush_mtime (or release) request to userspace who is busy > + * now writing ACK for given AIO to in-kernel fuse > + */ > + get_file(file); > io->iocb->ki_complete(io->iocb, res); > + > + /* local_bh_disable() forces fput() to offload final release to > workqueue */ > + local_bh_disable(); > + fput(file); > + local_bh_enable(); > } > > kref_put(&io->refcnt, fuse_io_release); _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
