]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fuse: create poll.c
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 31 Mar 2026 11:49:22 +0000 (13:49 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Mon, 15 Jun 2026 12:06:17 +0000 (14:06 +0200)
Move f_op->poll related functions to the new source file.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/Makefile
fs/fuse/dev.c
fs/fuse/dev.h
fs/fuse/file.c
fs/fuse/poll.c [new file with mode: 0644]

index 08be6817a1cc4f65d54598fff6453869df960794..26086bf5b49426eb391555d44d4332166c8e923b 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_VIRTIO_FS) += virtiofs.o
 
 fuse-y := trace.o      # put trace.o first so we see ftrace errors sooner
 fuse-y += dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o ioctl.o req_timeout.o req.o
+fuse-y += poll.o
 fuse-y += iomode.o
 fuse-$(CONFIG_FUSE_DAX) += dax.o
 fuse-$(CONFIG_FUSE_PASSTHROUGH) += passthrough.o backing.o
index dbbd20265dfcaa8c6bce189323e7ff21cbba47fb..18a9c4f3d63c756e1db4b453b9ecaa7e4d0c7d72 100644 (file)
@@ -80,10 +80,10 @@ void fuse_chan_set_initialized(struct fuse_chan *fch)
        wake_up_all(&fch->blocked_waitq);
 }
 
-static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
+static bool fuse_block_alloc(struct fuse_chan *fch, bool for_background)
 {
-       return !fc->chan->initialized || (for_background && fc->chan->blocked) ||
-              (fc->chan->io_uring && fc->chan->connected && !fuse_uring_ready(fc->chan));
+       return !fch->initialized || (for_background && fch->blocked) ||
+              (fch->io_uring && fch->connected && !fuse_uring_ready(fch));
 }
 
 static void fuse_drop_waiting(struct fuse_chan *fch)
@@ -109,10 +109,10 @@ static struct fuse_req *fuse_get_req(struct fuse_chan *fch, bool for_background)
 
        atomic_inc(&fch->num_waiting);
 
-       if (fuse_block_alloc(fch->conn, for_background)) {
+       if (fuse_block_alloc(fch, for_background)) {
                err = -EINTR;
                if (wait_event_state_exclusive(fch->blocked_waitq,
-                               !fuse_block_alloc(fch->conn, for_background),
+                               !fuse_block_alloc(fch, for_background),
                                (TASK_KILLABLE | TASK_FREEZABLE)))
                        goto out;
        }
@@ -2070,21 +2070,21 @@ static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
  * if the FUSE daemon takes careful measures to avoid processing duplicated
  * non-idempotent requests.
  */
-static void fuse_resend(struct fuse_conn *fc)
+static void fuse_resend(struct fuse_chan *fch)
 {
        struct fuse_dev *fud;
        struct fuse_req *req, *next;
-       struct fuse_iqueue *fiq = &fc->chan->iq;
+       struct fuse_iqueue *fiq = &fch->iq;
        LIST_HEAD(to_queue);
        unsigned int i;
 
-       spin_lock(&fc->chan->lock);
-       if (!fc->chan->connected) {
-               spin_unlock(&fc->chan->lock);
+       spin_lock(&fch->lock);
+       if (!fch->connected) {
+               spin_unlock(&fch->lock);
                return;
        }
 
-       list_for_each_entry(fud, &fc->chan->devices, entry) {
+       list_for_each_entry(fud, &fch->devices, entry) {
                struct fuse_pqueue *fpq = &fud->pq;
 
                spin_lock(&fpq->lock);
@@ -2092,7 +2092,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->chan->lock);
+       spin_unlock(&fch->lock);
 
        list_for_each_entry_safe(req, next, &to_queue, list) {
                set_bit(FR_PENDING, &req->flags);
@@ -2124,7 +2124,7 @@ static void fuse_resend(struct fuse_conn *fc)
 
 static int fuse_notify_resend(struct fuse_conn *fc)
 {
-       fuse_resend(fc);
+       fuse_resend(fc->chan);
        return 0;
 }
 
@@ -2512,23 +2512,6 @@ void fuse_dev_end_requests(struct list_head *head)
        }
 }
 
-static void end_polls(struct fuse_conn *fc)
-{
-       struct rb_node *p;
-
-       spin_lock(&fc->lock);
-       p = rb_first(&fc->polled_files);
-
-       while (p) {
-               struct fuse_file *ff;
-               ff = rb_entry(p, struct fuse_file, polled_node);
-               wake_up_interruptible_all(&ff->poll_wait);
-
-               p = rb_next(p);
-       }
-       spin_unlock(&fc->lock);
-}
-
 /*
  * Abort all requests.
  *
@@ -2606,7 +2589,7 @@ void fuse_chan_abort(struct fuse_chan *fch, bool abort_with_err)
                wake_up_all(&fiq->waitq);
                spin_unlock(&fiq->lock);
                kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
-               end_polls(fch->conn);
+               fuse_end_polls(fch->conn);
                wake_up_all(&fch->blocked_waitq);
                spin_unlock(&fch->lock);
 
index 9a1f79b130bdc195ebd3feaaa1203d8139dc8ecb..2c4d0c53ffbb4af3201c018f8311410b1273fa78 100644 (file)
@@ -49,6 +49,8 @@ void fuse_init_server_timeout(struct fuse_chan *fch, unsigned int timeout);
 void fuse_chan_abort(struct fuse_chan *fch, bool abort_with_err);
 void fuse_chan_wait_aborted(struct fuse_chan *fch);
 
+void fuse_end_polls(struct fuse_conn *fc);
+
 #ifdef CONFIG_FUSE_IO_URING
 bool fuse_uring_enabled(void);
 void fuse_uring_destruct(struct fuse_chan *fch);
index 057ff884500d5165f6ecafdd6c71b83665833695..e8833e2a6610f0987cb51166e421528dd6bdaa4b 100644 (file)
@@ -2683,125 +2683,6 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
        return retval;
 }
 
-/*
- * All files which have been polled are linked to RB tree
- * fuse_conn->polled_files which is indexed by kh.  Walk the tree and
- * find the matching one.
- */
-static struct rb_node **fuse_find_polled_node(struct fuse_conn *fc, u64 kh,
-                                             struct rb_node **parent_out)
-{
-       struct rb_node **link = &fc->polled_files.rb_node;
-       struct rb_node *last = NULL;
-
-       while (*link) {
-               struct fuse_file *ff;
-
-               last = *link;
-               ff = rb_entry(last, struct fuse_file, polled_node);
-
-               if (kh < ff->kh)
-                       link = &last->rb_left;
-               else if (kh > ff->kh)
-                       link = &last->rb_right;
-               else
-                       return link;
-       }
-
-       if (parent_out)
-               *parent_out = last;
-       return link;
-}
-
-/*
- * The file is about to be polled.  Make sure it's on the polled_files
- * RB tree.  Note that files once added to the polled_files tree are
- * not removed before the file is released.  This is because a file
- * polled once is likely to be polled again.
- */
-static void fuse_register_polled_file(struct fuse_conn *fc,
-                                     struct fuse_file *ff)
-{
-       spin_lock(&fc->lock);
-       if (RB_EMPTY_NODE(&ff->polled_node)) {
-               struct rb_node **link, *parent;
-
-               link = fuse_find_polled_node(fc, ff->kh, &parent);
-               BUG_ON(*link);
-               rb_link_node(&ff->polled_node, parent, link);
-               rb_insert_color(&ff->polled_node, &fc->polled_files);
-       }
-       spin_unlock(&fc->lock);
-}
-
-__poll_t fuse_file_poll(struct file *file, poll_table *wait)
-{
-       struct fuse_file *ff = file->private_data;
-       struct fuse_mount *fm = ff->fm;
-       struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
-       struct fuse_poll_out outarg;
-       FUSE_ARGS(args);
-       int err;
-
-       if (fm->fc->no_poll)
-               return DEFAULT_POLLMASK;
-
-       poll_wait(file, &ff->poll_wait, wait);
-       inarg.events = mangle_poll(poll_requested_events(wait));
-
-       /*
-        * Ask for notification iff there's someone waiting for it.
-        * The client may ignore the flag and always notify.
-        */
-       if (waitqueue_active(&ff->poll_wait)) {
-               inarg.flags |= FUSE_POLL_SCHEDULE_NOTIFY;
-               fuse_register_polled_file(fm->fc, ff);
-       }
-
-       args.opcode = FUSE_POLL;
-       args.nodeid = ff->nodeid;
-       args.in_numargs = 1;
-       args.in_args[0].size = sizeof(inarg);
-       args.in_args[0].value = &inarg;
-       args.out_numargs = 1;
-       args.out_args[0].size = sizeof(outarg);
-       args.out_args[0].value = &outarg;
-       err = fuse_simple_request(fm, &args);
-
-       if (!err)
-               return demangle_poll(outarg.revents);
-       if (err == -ENOSYS) {
-               fm->fc->no_poll = 1;
-               return DEFAULT_POLLMASK;
-       }
-       return EPOLLERR;
-}
-EXPORT_SYMBOL_GPL(fuse_file_poll);
-
-/*
- * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and
- * wakes up the poll waiters.
- */
-int fuse_notify_poll_wakeup(struct fuse_conn *fc,
-                           struct fuse_notify_poll_wakeup_out *outarg)
-{
-       u64 kh = outarg->kh;
-       struct rb_node **link;
-
-       spin_lock(&fc->lock);
-
-       link = fuse_find_polled_node(fc, kh, NULL);
-       if (*link) {
-               struct fuse_file *ff;
-
-               ff = rb_entry(*link, struct fuse_file, polled_node);
-               wake_up_interruptible_sync(&ff->poll_wait);
-       }
-
-       spin_unlock(&fc->lock);
-       return 0;
-}
-
 static void fuse_do_truncate(struct file *file)
 {
        struct inode *inode = file->f_mapping->host;
diff --git a/fs/fuse/poll.c b/fs/fuse/poll.c
new file mode 100644 (file)
index 0000000..bce3ee2
--- /dev/null
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include "dev.h"
+#include "fuse_i.h"
+
+void fuse_end_polls(struct fuse_conn *fc)
+{
+       struct rb_node *p;
+
+       spin_lock(&fc->lock);
+       p = rb_first(&fc->polled_files);
+
+       while (p) {
+               struct fuse_file *ff;
+               ff = rb_entry(p, struct fuse_file, polled_node);
+               wake_up_interruptible_all(&ff->poll_wait);
+
+               p = rb_next(p);
+       }
+       spin_unlock(&fc->lock);
+}
+
+/*
+ * All files which have been polled are linked to RB tree
+ * fuse_conn->polled_files which is indexed by kh.  Walk the tree and
+ * find the matching one.
+ */
+static struct rb_node **fuse_find_polled_node(struct fuse_conn *fc, u64 kh,
+                                             struct rb_node **parent_out)
+{
+       struct rb_node **link = &fc->polled_files.rb_node;
+       struct rb_node *last = NULL;
+
+       while (*link) {
+               struct fuse_file *ff;
+
+               last = *link;
+               ff = rb_entry(last, struct fuse_file, polled_node);
+
+               if (kh < ff->kh)
+                       link = &last->rb_left;
+               else if (kh > ff->kh)
+                       link = &last->rb_right;
+               else
+                       return link;
+       }
+
+       if (parent_out)
+               *parent_out = last;
+       return link;
+}
+
+/*
+ * The file is about to be polled.  Make sure it's on the polled_files
+ * RB tree.  Note that files once added to the polled_files tree are
+ * not removed before the file is released.  This is because a file
+ * polled once is likely to be polled again.
+ */
+static void fuse_register_polled_file(struct fuse_conn *fc,
+                                     struct fuse_file *ff)
+{
+       spin_lock(&fc->lock);
+       if (RB_EMPTY_NODE(&ff->polled_node)) {
+               struct rb_node **link, *parent;
+
+               link = fuse_find_polled_node(fc, ff->kh, &parent);
+               BUG_ON(*link);
+               rb_link_node(&ff->polled_node, parent, link);
+               rb_insert_color(&ff->polled_node, &fc->polled_files);
+       }
+       spin_unlock(&fc->lock);
+}
+
+__poll_t fuse_file_poll(struct file *file, poll_table *wait)
+{
+       struct fuse_file *ff = file->private_data;
+       struct fuse_mount *fm = ff->fm;
+       struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
+       struct fuse_poll_out outarg;
+       FUSE_ARGS(args);
+       int err;
+
+       if (fm->fc->no_poll)
+               return DEFAULT_POLLMASK;
+
+       poll_wait(file, &ff->poll_wait, wait);
+       inarg.events = mangle_poll(poll_requested_events(wait));
+
+       /*
+        * Ask for notification iff there's someone waiting for it.
+        * The client may ignore the flag and always notify.
+        */
+       if (waitqueue_active(&ff->poll_wait)) {
+               inarg.flags |= FUSE_POLL_SCHEDULE_NOTIFY;
+               fuse_register_polled_file(fm->fc, ff);
+       }
+
+       args.opcode = FUSE_POLL;
+       args.nodeid = ff->nodeid;
+       args.in_numargs = 1;
+       args.in_args[0].size = sizeof(inarg);
+       args.in_args[0].value = &inarg;
+       args.out_numargs = 1;
+       args.out_args[0].size = sizeof(outarg);
+       args.out_args[0].value = &outarg;
+       err = fuse_simple_request(fm, &args);
+
+       if (!err)
+               return demangle_poll(outarg.revents);
+       if (err == -ENOSYS) {
+               fm->fc->no_poll = 1;
+               return DEFAULT_POLLMASK;
+       }
+       return EPOLLERR;
+}
+EXPORT_SYMBOL_GPL(fuse_file_poll);
+
+/*
+ * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and
+ * wakes up the poll waiters.
+ */
+int fuse_notify_poll_wakeup(struct fuse_conn *fc,
+                           struct fuse_notify_poll_wakeup_out *outarg)
+{
+       u64 kh = outarg->kh;
+       struct rb_node **link;
+
+       spin_lock(&fc->lock);
+
+       link = fuse_find_polled_node(fc, kh, NULL);
+       if (*link) {
+               struct fuse_file *ff;
+
+               ff = rb_entry(*link, struct fuse_file, polled_node);
+               wake_up_interruptible_sync(&ff->poll_wait);
+       }
+
+       spin_unlock(&fc->lock);
+       return 0;
+}
+