This issue could be observed sometimes during libfuse xfstests, from
dmseg prints some like "kernel: WARNING: CPU: 4 PID: 0 at
fs/fuse/dev_uring.c:204 fuse_uring_destruct+0x1f5/0x200 [fuse]".
The cause is, if when fuse daemon just submitted
FUSE_IO_URING_CMD_REGISTER SQEs, then umount or fuse daemon quits at
this very early stage. After all uring queues stopped, might have one or
more unprocessed FUSE_IO_URING_CMD_REGISTER SQEs get processed then some
new ring entities are created and added to ent_avail_queue, and
immediately fuse_uring_cancel moves them to ent_in_userspace after SQEs
get canceled. These ring entities will not be moved to ent_released, and
will stay in ent_in_userspace when fuse_uring_destruct is called, needed
be freed by the function.
Fixes: b6236c8407cb ("fuse: {io-uring} Prevent mount point hang on
fuse-server termination")
Signed-off-by: Jian Huang Li <ali@xxxxxxx>
---
fs/fuse/dev_uring.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index 249b210becb1..eed0fc6c8b05 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -201,7 +201,20 @@ void fuse_uring_destruct(struct fuse_conn *fc)
WARN_ON(!list_empty(&queue->ent_avail_queue));
WARN_ON(!list_empty(&queue->ent_w_req_queue));
WARN_ON(!list_empty(&queue->ent_commit_queue));
- WARN_ON(!list_empty(&queue->ent_in_userspace));
+
+ /*
+ * ent_in_userspace might not be empty, because
+ * FUSE_IO_URING_CMD_REGISTER is not accounted yet
+ * in ring->queue_refs and fuse_uring_wait_stopped_queues()
+ * then passes too early. fuse_uring_cancel() adds these
+ * commands to queue->ent_in_userspace - they need
+ * to be freed here
+ */
+ list_for_each_entry_safe(ent, next, &queue->ent_in_userspace,
+ list) {
+ list_del_init(&ent->list);
+ kfree(ent);
+ }
list_for_each_entry_safe(ent, next, &queue->ent_released,
list) {
--
2.47.1