summaryrefslogtreecommitdiff
path: root/fs/fuse/dev.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2026-03-19 15:40:10 +0100
committerMiklos Szeredi <mszeredi@redhat.com>2026-06-15 14:06:16 +0200
commitb6d83d4e3eff4532c4c93d958dec78099ea37f5a (patch)
tree62ad1b44ab7e797ec311e861c4c781bb85ea5f1f /fs/fuse/dev.c
parentc1265fe4994b75fa378f6379705fb6c354a1cc6c (diff)
downloadlinux-b6d83d4e3eff4532c4c93d958dec78099ea37f5a.tar.gz
linux-b6d83d4e3eff4532c4c93d958dec78099ea37f5a.zip
fuse: don't access transport layer structs directly from the fs layer
Add helpers (get and set functions mainly) that cleanly separate the layers. Remove #include "fuse_dev_i.h" from: - inode.c - file.c - control.c Remove #include "dev_uring_i.h" from inode.c. [Li Wang: drop redundant initializer in process_init_limits()] Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r--fs/fuse/dev.c77
1 files changed, 72 insertions, 5 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 19b8cee3cff3..df851c2383e9 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -70,11 +70,12 @@ static void __fuse_put_request(struct fuse_req *req)
refcount_dec(&req->count);
}
-void fuse_set_initialized(struct fuse_conn *fc)
+void fuse_chan_set_initialized(struct fuse_chan *fch)
{
/* Make sure stores before this are seen on another CPU */
smp_wmb();
- fc->chan->initialized = 1;
+ fch->initialized = 1;
+ wake_up_all(&fch->blocked_waitq);
}
static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
@@ -119,7 +120,7 @@ static struct fuse_req *fuse_get_req(struct mnt_idmap *idmap,
(TASK_KILLABLE | TASK_FREEZABLE)))
goto out;
}
- /* Matches smp_wmb() in fuse_set_initialized() */
+ /* Matches smp_wmb() in fuse_chan_set_initialized() */
smp_rmb();
err = -ENOTCONN;
@@ -339,6 +340,9 @@ void fuse_chan_release(struct fuse_chan *fch)
if (fiq->ops->release)
fiq->ops->release(fiq);
+
+ if (fch->timeout.req_timeout)
+ cancel_delayed_work_sync(&fch->timeout.work);
}
void fuse_chan_free(struct fuse_chan *fch)
@@ -382,6 +386,41 @@ struct fuse_chan *fuse_dev_chan_new(void)
}
EXPORT_SYMBOL_GPL(fuse_dev_chan_new);
+unsigned int fuse_chan_num_background(struct fuse_chan *fch)
+{
+ return fch->num_background;
+}
+
+unsigned int fuse_chan_max_background(struct fuse_chan *fch)
+{
+ return READ_ONCE(fch->max_background);
+}
+
+void fuse_chan_max_background_set(struct fuse_chan *fch, unsigned int val)
+{
+ spin_lock(&fch->bg_lock);
+ fch->max_background = val;
+ fch->blocked = fch->num_background >= fch->max_background;
+ if (!fch->blocked)
+ wake_up(&fch->blocked_waitq);
+ spin_unlock(&fch->bg_lock);
+}
+
+unsigned int fuse_chan_num_waiting(struct fuse_chan *fch)
+{
+ return atomic_read(&fch->num_waiting);
+}
+
+void fuse_chan_set_fc(struct fuse_chan *fch, struct fuse_conn *fc)
+{
+ fch->conn = fc;
+}
+
+void fuse_chan_io_uring_enable(struct fuse_chan *fch)
+{
+ fch->io_uring = 1;
+}
+
void fuse_pqueue_init(struct fuse_pqueue *fpq)
{
unsigned int i;
@@ -476,6 +515,34 @@ void fuse_dev_put(struct fuse_dev *fud)
}
EXPORT_SYMBOL_GPL(fuse_dev_put);
+bool fuse_dev_is_installed(struct fuse_dev *fud)
+{
+ struct fuse_conn *fc = fuse_dev_fc_get(fud);
+
+ return fc != NULL && fc != FUSE_DEV_FC_DISCONNECTED;
+}
+
+/*
+ * Checks if @fc matches the one installed in @fud
+ */
+bool fuse_dev_verify(struct fuse_dev *fud, struct fuse_conn *fc)
+{
+ return fuse_dev_fc_get(fud) == fc;
+}
+
+bool fuse_dev_is_sync_init(struct fuse_dev *fud)
+{
+ return fud->sync_init;
+}
+
+struct fuse_dev *fuse_dev_grab(struct file *file)
+{
+ struct fuse_dev *fud = fuse_file_to_fud(file);
+
+ refcount_inc(&fud->ref);
+ return fud;
+}
+
static void fuse_send_one(struct fuse_iqueue *fiq, struct fuse_req *req)
{
req->in.h.len = sizeof(struct fuse_in_header) +
@@ -2550,7 +2617,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
fc->chan->connected = 0;
spin_unlock(&fc->chan->bg_lock);
- fuse_set_initialized(fc);
+ fuse_chan_set_initialized(fc->chan);
list_for_each_entry(fud, &fc->chan->devices, entry) {
struct fuse_pqueue *fpq = &fud->pq;
@@ -2609,7 +2676,7 @@ void fuse_wait_aborted(struct fuse_conn *fc)
{
/* matches implicit memory barrier in fuse_drop_waiting() */
smp_mb();
- wait_event(fc->chan->blocked_waitq, atomic_read(&fc->chan->num_waiting) == 0);
+ wait_event(fc->chan->blocked_waitq, fuse_chan_num_waiting(fc->chan) == 0);
fuse_uring_wait_stopped_queues(fc);
}