fuse-over-io-uring needs an implicit device clone, which is done per queue to avoid hanging "umount" when daemon side is already terminated. Reason is that fuse_dev_release() is not called when there are queued (waiting) io_uring commands. Solution is the implicit device clone and an exception in fuse_dev_release for uring devices to abort the connection when only uring device are left. Signed-off-by: Bernd Schubert <bschubert@xxxxxxx> --- fs/fuse/dev.c | 32 ++++++++++++++++++++++++++++++-- fs/fuse/dev_uring_i.h | 13 +++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 78c05516da7f..cd5dc6ae9272 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2257,6 +2257,8 @@ int fuse_dev_release(struct inode *inode, struct file *file) struct fuse_pqueue *fpq = &fud->pq; LIST_HEAD(to_end); unsigned int i; + int dev_cnt; + bool abort_conn = false; spin_lock(&fpq->lock); WARN_ON(!list_empty(&fpq->io)); @@ -2266,8 +2268,34 @@ int fuse_dev_release(struct inode *inode, struct file *file) fuse_dev_end_requests(&to_end); - /* Are we the last open device? */ - if (atomic_dec_and_test(&fc->dev_count)) { + /* Are we the last open device? */ + dev_cnt = atomic_dec_return(&fc->dev_count); + if (dev_cnt == 0) + abort_conn = true; + + /* + * Or is this with io_uring and only ring devices left? + * These devices will not receive a ->release() as long as + * there are io_uring_cmd's waiting and not completed + * with io_uring_cmd_done yet + */ + if (fuse_uring_configured(fc)) { + struct fuse_dev *list_dev; + bool all_uring = true; + + spin_lock(&fc->lock); + list_for_each_entry(list_dev, &fc->devices, entry) { + if (list_dev == fud) + continue; + if (!list_dev->uring_dev) + all_uring = false; + } + spin_unlock(&fc->lock); + if (all_uring) + abort_conn = true; + } + + if (abort_conn) { WARN_ON(fc->iq.fasync != NULL); fuse_abort_conn(fc); } diff --git a/fs/fuse/dev_uring_i.h b/fs/fuse/dev_uring_i.h index 7a2f540d3ea5..114e9c008013 100644 --- a/fs/fuse/dev_uring_i.h +++ b/fs/fuse/dev_uring_i.h @@ -261,6 +261,14 @@ fuse_uring_get_queue(struct fuse_ring *ring, int qid) return (struct fuse_ring_queue *)(ptr + qid * ring->queue_size); } +static inline bool fuse_uring_configured(struct fuse_conn *fc) +{ + if (READ_ONCE(fc->ring) != NULL && fc->ring->configured) + return true; + + return false; +} + #else /* CONFIG_FUSE_IO_URING */ struct fuse_ring; @@ -274,6 +282,11 @@ static inline void fuse_uring_conn_destruct(struct fuse_conn *fc) { } +static inline bool fuse_uring_configured(struct fuse_conn *fc) +{ + return false; +} + #endif /* CONFIG_FUSE_IO_URING */ #endif /* _FS_FUSE_DEV_URING_I_H */ -- 2.40.1