]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fuse: split off fch->lock from fc->lock
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 17 Mar 2026 15:32:37 +0000 (16:32 +0100)
committerMiklos Szeredi <mszeredi@redhat.com>
Mon, 15 Jun 2026 12:06:16 +0000 (14:06 +0200)
And document which members they protect.

end_polls() is called with both, outer fch->lock is probably unnecessary,
but doesn't hurt for now.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dev.c
fs/fuse/dev_uring.c
fs/fuse/fuse_dev_i.h
fs/fuse/fuse_i.h
fs/fuse/req_timeout.c

index 27357ee01fe5696a937478faf0658766e30fdf1d..52f46efd85ba7a7a8969b46f8a1b583cb492d4ae 100644 (file)
@@ -354,6 +354,7 @@ struct fuse_chan *fuse_chan_new(void)
        if (!fch)
                return NULL;
 
+       spin_lock_init(&fch->lock);
        INIT_LIST_HEAD(&fch->devices);
        spin_lock_init(&fch->bg_lock);
        INIT_LIST_HEAD(&fch->bg_queue);
@@ -418,7 +419,7 @@ void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc)
 {
        struct fuse_conn *old_fc;
 
-       spin_lock(&fc->lock);
+       spin_lock(&fc->chan->lock);
        /*
         * Pairs with:
         *  - xchg() in fuse_dev_release()
@@ -436,7 +437,7 @@ void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc)
                list_add_tail(&fud->entry, &fc->chan->devices);
                fuse_conn_get(fc);
        }
-       spin_unlock(&fc->lock);
+       spin_unlock(&fc->chan->lock);
 }
 EXPORT_SYMBOL_GPL(fuse_dev_install);
 
@@ -463,9 +464,9 @@ void fuse_dev_put(struct fuse_dev *fud)
        fc = fuse_dev_fc_get(fud);
        if (fc && fc != FUSE_DEV_FC_DISCONNECTED) {
                /* This is the virtiofs case (fuse_dev_release() not called) */
-               spin_lock(&fc->lock);
+               spin_lock(&fc->chan->lock);
                list_del(&fud->entry);
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
 
                fuse_conn_put(fc);
        }
@@ -2060,9 +2061,9 @@ static void fuse_resend(struct fuse_conn *fc)
        LIST_HEAD(to_queue);
        unsigned int i;
 
-       spin_lock(&fc->lock);
+       spin_lock(&fc->chan->lock);
        if (!fc->chan->connected) {
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
                return;
        }
 
@@ -2074,7 +2075,7 @@ static void fuse_resend(struct fuse_conn *fc)
                        list_splice_tail_init(&fpq->processing[i], &to_queue);
                spin_unlock(&fpq->lock);
        }
-       spin_unlock(&fc->lock);
+       spin_unlock(&fc->chan->lock);
 
        list_for_each_entry_safe(req, next, &to_queue, list) {
                set_bit(FR_PENDING, &req->flags);
@@ -2498,6 +2499,7 @@ static void end_polls(struct fuse_conn *fc)
 {
        struct rb_node *p;
 
+       spin_lock(&fc->lock);
        p = rb_first(&fc->polled_files);
 
        while (p) {
@@ -2507,6 +2509,7 @@ static void end_polls(struct fuse_conn *fc)
 
                p = rb_next(p);
        }
+       spin_unlock(&fc->lock);
 }
 
 /*
@@ -2531,7 +2534,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
 {
        struct fuse_iqueue *fiq = &fc->chan->iq;
 
-       spin_lock(&fc->lock);
+       spin_lock(&fc->chan->lock);
        if (fc->chan->connected) {
                struct fuse_dev *fud;
                struct fuse_req *req, *next;
@@ -2586,17 +2589,17 @@ void fuse_abort_conn(struct fuse_conn *fc)
                kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
                end_polls(fc);
                wake_up_all(&fc->chan->blocked_waitq);
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
 
                fuse_dev_end_requests(&to_end);
 
                /*
-                * fc->lock must not be taken to avoid conflicts with io-uring
+                * fc->chan->lock must not be taken to avoid conflicts with io-uring
                 * locks
                 */
                fuse_uring_abort(fc);
        } else {
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
        }
 }
 EXPORT_SYMBOL_GPL(fuse_abort_conn);
@@ -2630,11 +2633,11 @@ int fuse_dev_release(struct inode *inode, struct file *file)
 
                fuse_dev_end_requests(&to_end);
 
-               spin_lock(&fc->lock);
+               spin_lock(&fc->chan->lock);
                list_del(&fud->entry);
                /* Are we the last open device? */
                last = list_empty(&fc->chan->devices);
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
 
                if (last) {
                        WARN_ON(fc->chan->iq.fasync != NULL);
index eef7f7eac7957a74a8ea093a5136e80c9740d30a..53bd5ae4b68603d581c222d796eaf5389d3baeec 100644 (file)
@@ -243,14 +243,14 @@ static struct fuse_ring *fuse_uring_create(struct fuse_conn *fc)
        max_payload_size = max(FUSE_MIN_READ_BUFFER, fc->max_write);
        max_payload_size = max(max_payload_size, fc->max_pages * PAGE_SIZE);
 
-       spin_lock(&fc->lock);
+       spin_lock(&fc->chan->lock);
        if (!fc->chan->connected) {
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
                goto out_err;
        }
        if (fc->chan->ring) {
                /* race, another thread created the ring in the meantime */
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
                res = fc->chan->ring;
                goto out_err;
        }
@@ -262,7 +262,7 @@ static struct fuse_ring *fuse_uring_create(struct fuse_conn *fc)
        ring->max_payload_sz = max_payload_size;
        smp_store_release(&fc->chan->ring, ring);
 
-       spin_unlock(&fc->lock);
+       spin_unlock(&fc->chan->lock);
        return ring;
 
 out_err:
@@ -302,9 +302,9 @@ static struct fuse_ring_queue *fuse_uring_create_queue(struct fuse_ring *ring,
        queue->fpq.processing = pq;
        fuse_pqueue_init(&queue->fpq);
 
-       spin_lock(&fc->lock);
+       spin_lock(&fc->chan->lock);
        if (ring->queues[qid]) {
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
                kfree(queue->fpq.processing);
                kfree(queue);
                return ring->queues[qid];
@@ -314,7 +314,7 @@ static struct fuse_ring_queue *fuse_uring_create_queue(struct fuse_ring *ring,
         * write_once and lock as the caller mostly doesn't take the lock at all
         */
        WRITE_ONCE(ring->queues[qid], queue);
-       spin_unlock(&fc->lock);
+       spin_unlock(&fc->chan->lock);
 
        return queue;
 }
@@ -1008,16 +1008,16 @@ static int fuse_uring_do_register(struct fuse_ring_ent *ent,
        struct fuse_conn *fc = ring->fc;
        struct fuse_iqueue *fiq = &fc->chan->iq;
 
-       spin_lock(&fc->lock);
+       spin_lock(&fc->chan->lock);
        /* abort teardown path is running or has run */
        if (!fc->chan->connected) {
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
                if (atomic_dec_and_test(&ring->queue_refs))
                        wake_up_all(&ring->stop_waitq);
                kfree(ent);
                return -ECONNABORTED;
        }
-       spin_unlock(&fc->lock);
+       spin_unlock(&fc->chan->lock);
 
        fuse_uring_prepare_cancel(cmd, issue_flags, ent);
 
index 5c31272a49024d984203f4f26bab610ae4cf5b1f..22d9c9e795d94d1d42b2bd0b3dd8a43b7977d6cd 100644 (file)
@@ -88,6 +88,14 @@ struct fuse_iqueue {
 };
 
 struct fuse_chan {
+       /** Lock protecting:
+           - devices
+           - connected
+           - ring
+           - ring->queues[qid]
+        */
+       spinlock_t lock;
+
        /** Input queue */
        struct fuse_iqueue iq;
 
index 59bdabaf994b1a60dad7c11d93f2b03b7f823194..6343218563b19413a3c481e2aa3e3ad61190d6c7 100644 (file)
@@ -421,7 +421,7 @@ enum fuse_req_flag {
  *
  * .waitq.lock protects the following fields:
  *   - FR_ABORTED
- *   - FR_LOCKED (may also be modified under fc->lock, tested under both)
+ *   - FR_LOCKED (may also be modified under fpq->lock, tested under both)
  */
 struct fuse_req {
        /** This can be on either pending processing or io lists in
@@ -520,7 +520,11 @@ struct fuse_sync_bucket {
  * fuse_mount is destroyed.
  */
 struct fuse_conn {
-       /** Lock protecting accessess to  members of this structure */
+       /** Lock protecting:
+           - polled_files
+           - backing_files_map
+           - curr_bucket
+        */
        spinlock_t lock;
 
        /** Refcount */
index ef2e39e4dcf461d3f5388ed2742d73a1fce6fee2..401d3545b0a883c8587cf072068a3ed67c399eb4 100644 (file)
@@ -89,9 +89,9 @@ static void fuse_check_timeout(struct work_struct *work)
        if (expired)
                goto abort_conn;
 
-       spin_lock(&fc->lock);
+       spin_lock(&fc->chan->lock);
        if (!fc->chan->connected) {
-               spin_unlock(&fc->lock);
+               spin_unlock(&fc->chan->lock);
                return;
        }
        list_for_each_entry(fud, &fc->chan->devices, entry) {
@@ -100,13 +100,13 @@ static void fuse_check_timeout(struct work_struct *work)
                if (fuse_request_expired(fc, &fpq->io) ||
                    fuse_fpq_processing_expired(fc, fpq->processing)) {
                        spin_unlock(&fpq->lock);
-                       spin_unlock(&fc->lock);
+                       spin_unlock(&fc->chan->lock);
                        goto abort_conn;
                }
 
                spin_unlock(&fpq->lock);
        }
-       spin_unlock(&fc->lock);
+       spin_unlock(&fc->chan->lock);
 
        if (fuse_uring_request_expired(fc))
                goto abort_conn;