]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
fuse: block request allocation until io-uring init is complete
authorBernd Schubert <bernd@bsbernd.com>
Mon, 20 Jan 2025 01:29:09 +0000 (02:29 +0100)
committerMiklos Szeredi <mszeredi@redhat.com>
Mon, 27 Jan 2025 17:02:23 +0000 (18:02 +0100)
Avoid races and block request allocation until io-uring
queues are ready.

This is a especially important for background requests,
as bg request completion might cause lock order inversion
of the typical queue->lock and then fc->bg_lock

    fuse_request_end
       spin_lock(&fc->bg_lock);
       flush_bg_queue
         fuse_send_one
           fuse_uring_queue_fuse_req
           spin_lock(&queue->lock);

Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
Reviewed-by: Luis Henriques <luis@igalia.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dev.c
fs/fuse/dev_uring.c
fs/fuse/fuse_i.h
fs/fuse/inode.c

index 1b593b23f7b8c319ec38c7e726dabf516965500e..f002e8a096f97ba8b6e039309292942995c901c5 100644 (file)
@@ -76,7 +76,8 @@ void fuse_set_initialized(struct fuse_conn *fc)
 
 static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
 {
-       return !fc->initialized || (for_background && fc->blocked);
+       return !fc->initialized || (for_background && fc->blocked) ||
+              (fc->io_uring && !fuse_uring_ready(fc));
 }
 
 static void fuse_drop_waiting(struct fuse_conn *fc)
index fa0451176385ea52e87b378efad2515be30a8415..ea197ccd4c51ffcfa7bb6b0b5b31297dea5bb524 100644 (file)
@@ -957,6 +957,7 @@ static void fuse_uring_do_register(struct fuse_ring_ent *ent,
                if (ready) {
                        WRITE_ONCE(fiq->ops, &fuse_io_uring_ops);
                        WRITE_ONCE(ring->ready, true);
+                       wake_up_all(&fc->blocked_waitq);
                }
        }
 }
@@ -1130,6 +1131,8 @@ int __maybe_unused fuse_uring_cmd(struct io_uring_cmd *cmd,
                if (err) {
                        pr_info_once("FUSE_IO_URING_CMD_REGISTER failed err=%d\n",
                                     err);
+                       fc->io_uring = 0;
+                       wake_up_all(&fc->blocked_waitq);
                        return err;
                }
                break;
index ba6901c1bc2d0ac102f762f3d37e8b8a2d5ae2a4..fee96fe7887b30cd57b8a6bbda11447a228cf446 100644 (file)
@@ -867,6 +867,9 @@ struct fuse_conn {
        /* Use pages instead of pointer for kernel I/O */
        unsigned int use_pages_for_kvec_io:1;
 
+       /* Use io_uring for communication */
+       unsigned int io_uring;
+
        /** Maximum stack depth for passthrough backing files */
        int max_stack_depth;
 
index 328797b9aac9a816a4ad2c69b6880dc6ef6222b0..e9db2cb8c150878634728685af0fa15e7ade628f 100644 (file)
@@ -1390,6 +1390,8 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
                                else
                                        ok = false;
                        }
+                       if (flags & FUSE_OVER_IO_URING && fuse_uring_enabled())
+                               fc->io_uring = 1;
                } else {
                        ra_pages = fc->max_read / PAGE_SIZE;
                        fc->no_lock = 1;