diff options
| author | Miklos Szeredi <mszeredi@redhat.com> | 2026-03-11 21:02:41 +0100 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2026-04-02 20:43:24 +0200 |
| commit | a8dd5f1b73bc533e1192d38c82fc144595d3ce9a (patch) | |
| tree | 00b9f4425e3ff4deaf57204e81e7b896f11a9045 /fs/fuse/dev.c | |
| parent | e45f591f704aecec31dc738694a5e43acdfd020b (diff) | |
| download | linux-next-a8dd5f1b73bc533e1192d38c82fc144595d3ce9a.tar.gz linux-next-a8dd5f1b73bc533e1192d38c82fc144595d3ce9a.zip | |
fuse: create fuse_dev on /dev/fuse open instead of mount
Allocate struct fuse_dev when opening the device. This means that unlike
before, ->private_data is always set to a valid pointer.
The use of USE_DEV_SYNC_INIT magic pointer for the private_data is now
replaced with a simple bool sync_init member.
If sync INIT is not set, I/O on the device returns error before mount.
Keep this behavior by checking for the ->fc member. If fud->fc is set, the
mount has succeeded. Testing this used READ_ONCE(file->private_data) and
smp_mb() to try and provide the necessary semantics. Switch this to
smp_store_release() and smp_load_acquire().
Setting fud->fc is protected by fuse_mutex, this is unchanged.
Will need this later so the /dev/fuse open file reference is not held
during FSCONFIG_CMD_CREATE.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Diffstat (limited to 'fs/fuse/dev.c')
| -rw-r--r-- | fs/fuse/dev.c | 47 |
1 files changed, 18 insertions, 29 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 952dd56f0a02..0c03bbb21c12 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1548,32 +1548,24 @@ out_end: static int fuse_dev_open(struct inode *inode, struct file *file) { - /* - * The fuse device's file's private_data is used to hold - * the fuse_conn(ection) when it is mounted, and is used to - * keep track of whether the file has been mounted already. - */ - file->private_data = NULL; + struct fuse_dev *fud = fuse_dev_alloc(); + + if (!fud) + return -ENOMEM; + + file->private_data = fud; return 0; } struct fuse_dev *fuse_get_dev(struct file *file) { - struct fuse_dev *fud = __fuse_get_dev(file); + struct fuse_dev *fud = fuse_file_to_fud(file); int err; - if (likely(fud)) - return fud; - - err = wait_event_interruptible(fuse_dev_waitq, - READ_ONCE(file->private_data) != FUSE_DEV_SYNC_INIT); + err = wait_event_interruptible(fuse_dev_waitq, fuse_dev_fc_get(fud) != NULL); if (err) return ERR_PTR(err); - fud = __fuse_get_dev(file); - if (!fud) - return ERR_PTR(-EPERM); - return fud; } @@ -2547,10 +2539,10 @@ void fuse_wait_aborted(struct fuse_conn *fc) int fuse_dev_release(struct inode *inode, struct file *file) { - struct fuse_dev *fud = __fuse_get_dev(file); + struct fuse_dev *fud = fuse_file_to_fud(file); + struct fuse_conn *fc = fuse_dev_fc_get(fud); - if (fud) { - struct fuse_conn *fc = fud->fc; + if (fc) { struct fuse_pqueue *fpq = &fud->pq; LIST_HEAD(to_end); unsigned int i; @@ -2568,8 +2560,8 @@ int fuse_dev_release(struct inode *inode, struct file *file) WARN_ON(fc->iq.fasync != NULL); fuse_abort_conn(fc); } - fuse_dev_free(fud); } + fuse_dev_free(fud); return 0; } EXPORT_SYMBOL_GPL(fuse_dev_release); @@ -2587,16 +2579,12 @@ static int fuse_dev_fasync(int fd, struct file *file, int on) static int fuse_device_clone(struct fuse_conn *fc, struct file *new) { - struct fuse_dev *fud; + struct fuse_dev *new_fud = fuse_file_to_fud(new); - if (__fuse_get_dev(new)) + if (fuse_dev_fc_get(new_fud)) return -EINVAL; - fud = fuse_dev_alloc_install(fc); - if (!fud) - return -ENOMEM; - - new->private_data = fud; + fuse_dev_install(new_fud, fc); atomic_inc(&fc->dev_count); return 0; @@ -2667,10 +2655,11 @@ static long fuse_dev_ioctl_backing_close(struct file *file, __u32 __user *argp) static long fuse_dev_ioctl_sync_init(struct file *file) { int err = -EINVAL; + struct fuse_dev *fud = fuse_file_to_fud(file); mutex_lock(&fuse_mutex); - if (!__fuse_get_dev(file)) { - WRITE_ONCE(file->private_data, FUSE_DEV_SYNC_INIT); + if (!fuse_dev_fc_get(fud)) { + fud->sync_init = true; err = 0; } mutex_unlock(&fuse_mutex); |
