Merged to rh10-6.12.0-211.16.1.12.7.vz10. On 6/22/26 18:22, Alexey Kuznetsov wrote: > 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 | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > > diff --git a/fs/fuse/file.c b/fs/fuse/file.c > index 40cded8..95a3352 100644 > --- a/fs/fuse/file.c > +++ b/fs/fuse/file.c > @@ -971,6 +971,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 +990,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);
-- Best regards, Pavel Tikhomirov Senior Software Developer, Virtuozzo. _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
