diff options
| author | Miklos Szeredi <mszeredi@redhat.com> | 2026-03-11 22:05:17 +0100 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2026-04-02 20:43:24 +0200 |
| commit | e9bf38500ed9aec7cfdf9219c75d353645b41168 (patch) | |
| tree | d531d968cfd670f784d61f90ad4905d6ffb84c51 /fs/fuse/dev.c | |
| parent | a8dd5f1b73bc533e1192d38c82fc144595d3ce9a (diff) | |
| download | linux-next-e9bf38500ed9aec7cfdf9219c75d353645b41168.tar.gz linux-next-e9bf38500ed9aec7cfdf9219c75d353645b41168.zip | |
fuse: add refcount to fuse_dev
This will make it possible to grab the fuse_dev and subsequently release
the file that it came from.
In the above case, fud->fc will be set to FUSE_DEV_FC_DISCONNECTED to
indicate that this is no longer a functional device.
When trying to assign an fc to such a disconnected fuse_dev, the fc is set
to the disconnected state.
Use atomic operations xchg() and cmpxchg() to prevent races.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse/dev.c')
| -rw-r--r-- | fs/fuse/dev.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 0c03bbb21c12..3d96e7a16103 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2540,7 +2540,8 @@ void fuse_wait_aborted(struct fuse_conn *fc) int fuse_dev_release(struct inode *inode, struct file *file) { struct fuse_dev *fud = fuse_file_to_fud(file); - struct fuse_conn *fc = fuse_dev_fc_get(fud); + /* Pairs with cmpxchg() in fuse_dev_install() */ + struct fuse_conn *fc = xchg(&fud->fc, FUSE_DEV_FC_DISCONNECTED); if (fc) { struct fuse_pqueue *fpq = &fud->pq; @@ -2560,8 +2561,12 @@ int fuse_dev_release(struct inode *inode, struct file *file) WARN_ON(fc->iq.fasync != NULL); fuse_abort_conn(fc); } + spin_lock(&fc->lock); + list_del(&fud->entry); + spin_unlock(&fc->lock); + fuse_conn_put(fc); } - fuse_dev_free(fud); + fuse_dev_put(fud); return 0; } EXPORT_SYMBOL_GPL(fuse_dev_release); |
