Skip to content

Commit 4ae404a

Browse files
author
Miklos Szeredi
committed
fuse: clean up device cloning
- fuse_mutex is not needed for device cloning, because fuse_dev_install() uses cmpxcg() to set fud->fc, which prevents races between clone/mount or clone/clone. This makes the logic simpler - Drop fc->dev_count. This is only used to check in release if the device is the last clone, but checking list_empty(&fc->devices) is equivalent after removing the released device from the list. Removing the fuse_dev before calling fuse_abort_conn() is okay, since the processing and io lists are now empty for this device. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1 parent d42eb23 commit 4ae404a

3 files changed

Lines changed: 15 additions & 24 deletions

File tree

fs/fuse/dev.c

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
25472547
struct fuse_pqueue *fpq = &fud->pq;
25482548
LIST_HEAD(to_end);
25492549
unsigned int i;
2550+
bool last;
25502551

25512552
spin_lock(&fpq->lock);
25522553
WARN_ON(!list_empty(&fpq->io));
@@ -2556,14 +2557,16 @@ int fuse_dev_release(struct inode *inode, struct file *file)
25562557

25572558
fuse_dev_end_requests(&to_end);
25582559

2560+
spin_lock(&fc->lock);
2561+
list_del(&fud->entry);
25592562
/* Are we the last open device? */
2560-
if (atomic_dec_and_test(&fc->dev_count)) {
2563+
last = list_empty(&fc->devices);
2564+
spin_unlock(&fc->lock);
2565+
2566+
if (last) {
25612567
WARN_ON(fc->iq.fasync != NULL);
25622568
fuse_abort_conn(fc);
25632569
}
2564-
spin_lock(&fc->lock);
2565-
list_del(&fud->entry);
2566-
spin_unlock(&fc->lock);
25672570
fuse_conn_put(fc);
25682571
}
25692572
fuse_dev_put(fud);
@@ -2582,23 +2585,10 @@ static int fuse_dev_fasync(int fd, struct file *file, int on)
25822585
return fasync_helper(fd, file, on, &fud->fc->iq.fasync);
25832586
}
25842587

2585-
static int fuse_device_clone(struct fuse_conn *fc, struct file *new)
2586-
{
2587-
struct fuse_dev *new_fud = fuse_file_to_fud(new);
2588-
2589-
if (fuse_dev_fc_get(new_fud))
2590-
return -EINVAL;
2591-
2592-
fuse_dev_install(new_fud, fc);
2593-
atomic_inc(&fc->dev_count);
2594-
2595-
return 0;
2596-
}
2597-
25982588
static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
25992589
{
26002590
int oldfd;
2601-
struct fuse_dev *fud;
2591+
struct fuse_dev *fud, *new_fud;
26022592

26032593
if (get_user(oldfd, argp))
26042594
return -EFAULT;
@@ -2618,8 +2608,13 @@ static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
26182608
if (IS_ERR(fud))
26192609
return PTR_ERR(fud);
26202610

2621-
guard(mutex)(&fuse_mutex);
2622-
return fuse_device_clone(fud->fc, file);
2611+
new_fud = fuse_file_to_fud(file);
2612+
if (fuse_dev_fc_get(new_fud))
2613+
return -EINVAL;
2614+
2615+
fuse_dev_install(new_fud, fud->fc);
2616+
2617+
return 0;
26232618
}
26242619

26252620
static long fuse_dev_ioctl_backing_open(struct file *file,

fs/fuse/fuse_i.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -650,9 +650,6 @@ struct fuse_conn {
650650
/** Refcount */
651651
refcount_t count;
652652

653-
/** Number of fuse_dev's */
654-
atomic_t dev_count;
655-
656653
/** Current epoch for up-to-date dentries */
657654
atomic_t epoch;
658655

fs/fuse/inode.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,6 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm,
10011001
spin_lock_init(&fc->bg_lock);
10021002
init_rwsem(&fc->killsb);
10031003
refcount_set(&fc->count, 1);
1004-
atomic_set(&fc->dev_count, 1);
10051004
atomic_set(&fc->epoch, 1);
10061005
INIT_WORK(&fc->epoch_work, fuse_epoch_work);
10071006
init_waitqueue_head(&fc->blocked_waitq);

0 commit comments

Comments
 (0)