diff options
| author | Miklos Szeredi <mszeredi@redhat.com> | 2026-03-17 12:44:31 +0100 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2026-06-15 14:06:15 +0200 |
| commit | d8189630a1a1468a8702e252dd93e36d6ec8121e (patch) | |
| tree | 102b6a196b0867d1371c712d0878ce9e614d68ea /fs/fuse/dev.c | |
| parent | b88fb2b92b24b3eee0ea87001c8d9fbf5ba54bb7 (diff) | |
| download | linux-next-d8189630a1a1468a8702e252dd93e36d6ec8121e.tar.gz linux-next-d8189630a1a1468a8702e252dd93e36d6ec8121e.zip | |
fuse: move fuse_dev and fuse_pqueue to dev.c
Move function definitions to dev.c, struct definitions to fuse_dev_i.h.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse/dev.c')
| -rw-r--r-- | fs/fuse/dev.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 0c0906a2372a..7339959fa8d3 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -365,6 +365,100 @@ struct fuse_chan *fuse_dev_chan_new(void) } EXPORT_SYMBOL_GPL(fuse_dev_chan_new); +void fuse_pqueue_init(struct fuse_pqueue *fpq) +{ + unsigned int i; + + spin_lock_init(&fpq->lock); + for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) + INIT_LIST_HEAD(&fpq->processing[i]); + INIT_LIST_HEAD(&fpq->io); + fpq->connected = 1; +} + +struct fuse_dev *fuse_dev_alloc(void) +{ + struct fuse_dev *fud; + struct list_head *pq; + + fud = kzalloc_obj(struct fuse_dev); + if (!fud) + return NULL; + + refcount_set(&fud->ref, 1); + pq = kzalloc_objs(struct list_head, FUSE_PQ_HASH_SIZE); + if (!pq) { + kfree(fud); + return NULL; + } + + fud->pq.processing = pq; + fuse_pqueue_init(&fud->pq); + + return fud; +} +EXPORT_SYMBOL_GPL(fuse_dev_alloc); + +void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc) +{ + struct fuse_conn *old_fc; + + spin_lock(&fc->lock); + /* + * Pairs with: + * - xchg() in fuse_dev_release() + * - smp_load_acquire() in fuse_dev_fc_get() + */ + old_fc = cmpxchg(&fud->fc, NULL, fc); + if (old_fc) { + /* + * failed to set fud->fc because + * - it was already set to a different fc + * - it was set to disconneted + */ + fc->connected = 0; + } else { + list_add_tail(&fud->entry, &fc->devices); + fuse_conn_get(fc); + } + spin_unlock(&fc->lock); +} +EXPORT_SYMBOL_GPL(fuse_dev_install); + +struct fuse_dev *fuse_dev_alloc_install(struct fuse_conn *fc) +{ + struct fuse_dev *fud; + + fud = fuse_dev_alloc(); + if (!fud) + return NULL; + + fuse_dev_install(fud, fc); + return fud; +} +EXPORT_SYMBOL_GPL(fuse_dev_alloc_install); + +void fuse_dev_put(struct fuse_dev *fud) +{ + struct fuse_conn *fc; + + if (!refcount_dec_and_test(&fud->ref)) + return; + + 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); + list_del(&fud->entry); + spin_unlock(&fc->lock); + + fuse_conn_put(fc); + } + kfree(fud->pq.processing); + kfree(fud); +} +EXPORT_SYMBOL_GPL(fuse_dev_put); + static void fuse_send_one(struct fuse_iqueue *fiq, struct fuse_req *req) { req->in.h.len = sizeof(struct fuse_in_header) + |
