]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fuse: abort related layering cleanup
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 24 Mar 2026 15:12:28 +0000 (16:12 +0100)
committerMiklos Szeredi <mszeredi@redhat.com>
Mon, 15 Jun 2026 12:06:17 +0000 (14:06 +0200)
 - rename fuse_abort_conn() to fuse_chan_abort(), pass fuse_chan pointer
   instead of fuse_conn

 - pass an abort_with_err argument that tells fuse_dev_(read|write) to
   return with ECONNABORTED instead of ENODEV

 - move fc->aborted to fch->abort_with_err

 - rename fuse_wait_aborted() to fuse_chan_wait_aborted()

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

index e6f513eb7d4a37f854ddb3ec5fd3e9e1b2ccc796..925a1548849966d9524f2ce7ac3051c7af4ffd0b 100644 (file)
@@ -38,9 +38,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
 {
        struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
        if (fc) {
-               if (fc->abort_err)
-                       fc->aborted = true;
-               fuse_abort_conn(fc);
+               fuse_chan_abort(fc->chan, fc->abort_err);
                fuse_conn_put(fc);
        }
        return count;
index 950c070ab3e963f69f412e944f8d69e8286bc8f9..321ba7af0ec5146be8bed52305089fe2ba667857 100644 (file)
@@ -426,7 +426,7 @@ err_unlock:
 err_region:
        unregister_chrdev_region(devt, 1);
 err:
-       fuse_abort_conn(fc);
+       fuse_chan_abort(fc->chan, false);
        goto out;
 }
 
@@ -596,7 +596,7 @@ static ssize_t cuse_class_abort_store(struct device *dev,
 {
        struct cuse_conn *cc = dev_get_drvdata(dev);
 
-       fuse_abort_conn(&cc->fc);
+       fuse_chan_abort(cc->fc.chan, false);
        return count;
 }
 static DEVICE_ATTR(abort, 0200, NULL, cuse_class_abort_store);
index 586d6fe46e317c9fa3fc30ef4f2871bc5a16fc16..c4a6ee9482829bae0e1355c9ef9f87ce09741eff 100644 (file)
@@ -90,7 +90,7 @@ static void fuse_drop_waiting(struct fuse_conn *fc)
 {
        /*
         * lockess check of fc->chan->connected is okay, because atomic_dec_and_test()
-        * provides a memory barrier matched with the one in fuse_wait_aborted()
+        * provides a memory barrier matched with the one in fuse_chan_wait_aborted()
         * to ensure no wake-up is missed.
         */
        if (atomic_dec_and_test(&fc->chan->num_waiting) &&
@@ -570,17 +570,17 @@ void fuse_chan_queue_forget(struct fuse_chan *fch, struct fuse_forget_link *forg
        fiq->ops->send_forget(fiq, forget);
 }
 
-static void flush_bg_queue(struct fuse_conn *fc)
+static void flush_bg_queue(struct fuse_chan *fch)
 {
-       struct fuse_iqueue *fiq = &fc->chan->iq;
+       struct fuse_iqueue *fiq = &fch->iq;
 
-       while (fc->chan->active_background < fc->chan->max_background &&
-              !list_empty(&fc->chan->bg_queue)) {
+       while (fch->active_background < fch->max_background &&
+              !list_empty(&fch->bg_queue)) {
                struct fuse_req *req;
 
-               req = list_first_entry(&fc->chan->bg_queue, struct fuse_req, list);
+               req = list_first_entry(&fch->bg_queue, struct fuse_req, list);
                list_del(&req->list);
-               fc->chan->active_background++;
+               fch->active_background++;
                fuse_send_one(fiq, req);
        }
 }
@@ -641,7 +641,7 @@ void fuse_request_end(struct fuse_req *req)
        if (test_bit(FR_BACKGROUND, &req->flags)) {
                spin_lock(&fc->chan->bg_lock);
                fuse_request_bg_finish(fc->chan, req);
-               flush_bg_queue(fc);
+               flush_bg_queue(fc->chan);
                spin_unlock(&fc->chan->bg_lock);
        } else {
                /* Wake up waiter sleeping in request_wait_answer() */
@@ -716,7 +716,7 @@ static void request_wait_answer(struct fuse_req *req)
                        return;
 
                if (req->args->abort_on_kill) {
-                       fuse_abort_conn(fc);
+                       fuse_chan_abort(fc->chan, false);
                        return;
                }
 
@@ -894,7 +894,7 @@ static int fuse_request_queue_background(struct fuse_req *req)
                if (fc->chan->num_background == fc->chan->max_background)
                        fc->chan->blocked = 1;
                list_add_tail(&req->list, &fc->chan->bg_queue);
-               flush_bg_queue(fc);
+               flush_bg_queue(fc->chan);
                queued = true;
        }
        spin_unlock(&fc->chan->bg_lock);
@@ -1590,7 +1590,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        }
 
        if (!fiq->connected) {
-               err = fc->aborted ? -ECONNABORTED : -ENODEV;
+               err = fc->chan->abort_with_err ? -ECONNABORTED : -ENODEV;
                goto err_unlock;
        }
 
@@ -1628,7 +1628,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        spin_lock(&fpq->lock);
        /*
         *  Must not put request on fpq->io queue after having been shut down by
-        *  fuse_abort_conn()
+        *  fuse_chan_abort()
         */
        if (!fpq->connected) {
                req->out.h.error = err = -ECONNABORTED;
@@ -1646,7 +1646,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        spin_lock(&fpq->lock);
        clear_bit(FR_LOCKED, &req->flags);
        if (!fpq->connected) {
-               err = fc->aborted ? -ECONNABORTED : -ENODEV;
+               err = fc->chan->abort_with_err ? -ECONNABORTED : -ENODEV;
                goto out_end;
        }
        if (err) {
@@ -2606,27 +2606,29 @@ static void end_polls(struct fuse_conn *fc)
  * is OK, the request will in that case be removed from the list before we touch
  * it.
  */
-void fuse_abort_conn(struct fuse_conn *fc)
+void fuse_chan_abort(struct fuse_chan *fch, bool abort_with_err)
 {
-       struct fuse_iqueue *fiq = &fc->chan->iq;
+       struct fuse_iqueue *fiq = &fch->iq;
 
-       spin_lock(&fc->chan->lock);
-       if (fc->chan->connected) {
+       fch->abort_with_err = abort_with_err;
+
+       spin_lock(&fch->lock);
+       if (fch->connected) {
                struct fuse_dev *fud;
                struct fuse_req *req, *next;
                LIST_HEAD(to_end);
                unsigned int i;
 
-               if (fc->chan->timeout.req_timeout)
-                       cancel_delayed_work(&fc->chan->timeout.work);
+               if (fch->timeout.req_timeout)
+                       cancel_delayed_work(&fch->timeout.work);
 
-               /* Background queuing checks fc->chan->connected under bg_lock */
-               spin_lock(&fc->chan->bg_lock);
-               fc->chan->connected = 0;
-               spin_unlock(&fc->chan->bg_lock);
+               /* Background queuing checks fch->connected under bg_lock */
+               spin_lock(&fch->bg_lock);
+               fch->connected = 0;
+               spin_unlock(&fch->bg_lock);
 
-               fuse_chan_set_initialized(fc->chan);
-               list_for_each_entry(fud, &fc->chan->devices, entry) {
+               fuse_chan_set_initialized(fch);
+               list_for_each_entry(fud, &fch->devices, entry) {
                        struct fuse_pqueue *fpq = &fud->pq;
 
                        spin_lock(&fpq->lock);
@@ -2647,11 +2649,11 @@ void fuse_abort_conn(struct fuse_conn *fc)
                                                      &to_end);
                        spin_unlock(&fpq->lock);
                }
-               spin_lock(&fc->chan->bg_lock);
-               fc->chan->blocked = 0;
-               fc->chan->max_background = UINT_MAX;
-               flush_bg_queue(fc);
-               spin_unlock(&fc->chan->bg_lock);
+               spin_lock(&fch->bg_lock);
+               fch->blocked = 0;
+               fch->max_background = UINT_MAX;
+               flush_bg_queue(fch);
+               spin_unlock(&fch->bg_lock);
 
                spin_lock(&fiq->lock);
                fiq->connected = 0;
@@ -2663,30 +2665,30 @@ void fuse_abort_conn(struct fuse_conn *fc)
                wake_up_all(&fiq->waitq);
                spin_unlock(&fiq->lock);
                kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
-               end_polls(fc);
-               wake_up_all(&fc->chan->blocked_waitq);
-               spin_unlock(&fc->chan->lock);
+               end_polls(fch->conn);
+               wake_up_all(&fch->blocked_waitq);
+               spin_unlock(&fch->lock);
 
                fuse_dev_end_requests(&to_end);
 
                /*
-                * fc->chan->lock must not be taken to avoid conflicts with io-uring
+                * fch->lock must not be taken to avoid conflicts with io-uring
                 * locks
                 */
-               fuse_uring_abort(fc->chan);
+               fuse_uring_abort(fch);
        } else {
-               spin_unlock(&fc->chan->lock);
+               spin_unlock(&fch->lock);
        }
 }
-EXPORT_SYMBOL_GPL(fuse_abort_conn);
+EXPORT_SYMBOL_GPL(fuse_chan_abort);
 
-void fuse_wait_aborted(struct fuse_conn *fc)
+void fuse_chan_wait_aborted(struct fuse_chan *fch)
 {
        /* matches implicit memory barrier in fuse_drop_waiting() */
        smp_mb();
-       wait_event(fc->chan->blocked_waitq, fuse_chan_num_waiting(fc->chan) == 0);
+       wait_event(fch->blocked_waitq, fuse_chan_num_waiting(fch) == 0);
 
-       fuse_uring_wait_stopped_queues(fc->chan);
+       fuse_uring_wait_stopped_queues(fch);
 }
 
 int fuse_dev_release(struct inode *inode, struct file *file)
@@ -2717,7 +2719,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
 
                if (last) {
                        WARN_ON(fc->chan->iq.fasync != NULL);
-                       fuse_abort_conn(fc);
+                       fuse_chan_abort(fc->chan, false);
                }
                fuse_conn_put(fc);
        }
index efdaf0bf6f0f3b57b43a48a5278a785e0e3780ef..a0c1212573d6c3e8f12f5e83bd73979a9249b14e 100644 (file)
@@ -42,7 +42,8 @@ struct fuse_dev *fuse_dev_grab(struct file *file);
 void fuse_init_server_timeout(struct fuse_chan *fch, unsigned int timeout);
 
 /* Abort all requests */
-void fuse_abort_conn(struct fuse_conn *fc);
+void fuse_chan_abort(struct fuse_chan *fch, bool abort_with_err);
+void fuse_chan_wait_aborted(struct fuse_chan *fch);
 
 #ifdef CONFIG_FUSE_IO_URING
 bool fuse_uring_enabled(void);
index 296da4ff233c77b5a3642bf67c03b397b93818a0..71608a5beead905123d8063eaeb784bd9187bc69 100644 (file)
@@ -1189,7 +1189,7 @@ int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
                return -EOPNOTSUPP;
        }
 
-       if (fc->aborted)
+       if (fc->chan->abort_with_err)
                return -ECONNABORTED;
        if (!fc->chan->connected)
                return -ENOTCONN;
index a0eb9cac9b2f4a9db88407ecb5fe67b8c12bdc55..34cf0ac411b78826a09083f699bee386933c2dee 100644 (file)
@@ -238,6 +238,9 @@ struct fuse_chan {
        /* Use io_uring for communication */
        unsigned int io_uring;
 
+       /** Connection aborted via sysfs, respond with ECONNABORTED on device I/O */
+       bool abort_with_err;
+
 #ifdef CONFIG_FUSE_IO_URING
        /**  uring connection information*/
        struct fuse_ring *ring;
index af8e05a403e54e4ae4b6d3d375abe600d63c51f1..b8655c3b48e25482866a3859aef604fee048adce 100644 (file)
@@ -483,9 +483,6 @@ struct fuse_conn {
        /** Number of background requests at which congestion starts */
        unsigned congestion_threshold;
 
-       /** Connection aborted via sysfs */
-       bool aborted;
-
        /** Connection failed (version mismatch).  Cannot race with
            setting other bitfields since it is only set once in INIT
            reply, before any other request, and never cleared */
@@ -996,8 +993,6 @@ static inline ssize_t fuse_simple_idmap_request(struct mnt_idmap *idmap,
 int fuse_simple_background(struct fuse_mount *fm, struct fuse_args *args,
                           gfp_t gfp_flags);
 
-void fuse_wait_aborted(struct fuse_conn *fc);
-
 void fuse_dentry_tree_init(void);
 void fuse_dentry_tree_cleanup(void);
 
index 5695a7dca05110752763bd963770e129ecbebee7..66e37af3a6dd4862b1e53948c66afff6b2bad608 100644 (file)
@@ -612,7 +612,7 @@ static void fuse_umount_begin(struct super_block *sb)
        if (fc->no_force_umount)
                return;
 
-       fuse_abort_conn(fc);
+       fuse_chan_abort(fc->chan, false);
 
        // Only retire block-device-based superblocks.
        if (sb->s_bdev != NULL)
@@ -1952,8 +1952,8 @@ void fuse_conn_destroy(struct fuse_mount *fm)
        if (fc->destroy)
                fuse_send_destroy(fm);
 
-       fuse_abort_conn(fc);
-       fuse_wait_aborted(fc);
+       fuse_chan_abort(fc->chan, false);
+       fuse_chan_wait_aborted(fc->chan);
 
        if (!list_empty(&fc->entry)) {
                mutex_lock(&fuse_mutex);
index 9c48789b941a95de7afe0938c0a4953289bfbdd1..6cc6fc491343778580748ce29c0c71ecd8aae54b 100644 (file)
@@ -79,13 +79,13 @@ static void fuse_check_timeout(struct work_struct *work)
        expired = fuse_request_expired(fch, &fiq->pending);
        spin_unlock(&fiq->lock);
        if (expired)
-               goto abort_conn;
+               goto chan_abort;
 
        spin_lock(&fch->bg_lock);
        expired = fuse_request_expired(fch, &fch->bg_queue);
        spin_unlock(&fch->bg_lock);
        if (expired)
-               goto abort_conn;
+               goto chan_abort;
 
        spin_lock(&fch->lock);
        if (!fch->connected) {
@@ -99,7 +99,7 @@ static void fuse_check_timeout(struct work_struct *work)
                    fuse_fpq_processing_expired(fch, fpq->processing)) {
                        spin_unlock(&fpq->lock);
                        spin_unlock(&fch->lock);
-                       goto abort_conn;
+                       goto chan_abort;
                }
 
                spin_unlock(&fpq->lock);
@@ -107,15 +107,15 @@ static void fuse_check_timeout(struct work_struct *work)
        spin_unlock(&fch->lock);
 
        if (fuse_uring_request_expired(fch))
-               goto abort_conn;
+               goto chan_abort;
 
 out:
        queue_delayed_work(system_percpu_wq, &fch->timeout.work,
                           fuse_timeout_timer_freq);
        return;
 
-abort_conn:
-       fuse_abort_conn(fch->conn);
+chan_abort:
+       fuse_chan_abort(fch, false);
 }
 
 static void set_request_timeout(struct fuse_chan *fch, unsigned int timeout)