diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2015-07-01 17:26:08 +0300 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2015-07-01 17:26:08 +0300 |
commit | 00c570f4ba43ae73b41fa0a2269c3b0ac20386ef (patch) | |
tree | 5dad39b5bf083a172c7ac544ae0121d7fab1eeb0 | |
parent | ee314a870e402f4e63b8a651bc96c740ed69cb31 (diff) | |
download | linux-00c570f4ba43ae73b41fa0a2269c3b0ac20386ef.tar.xz |
fuse: device fd clone
Allow an open fuse device to be "cloned". Userspace can create a clone by:
newfd = open("/dev/fuse", O_RDWR)
ioctl(newfd, FUSE_DEV_IOC_CLONE, &oldfd);
At this point newfd will refer to the same fuse connection as oldfd.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Reviewed-by: Ashish Samant <ashish.samant@oracle.com>
-rw-r--r-- | Documentation/ioctl/ioctl-number.txt | 1 | ||||
-rw-r--r-- | fs/fuse/dev.c | 40 | ||||
-rw-r--r-- | include/uapi/linux/fuse.h | 3 |
3 files changed, 44 insertions, 0 deletions
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 51f4221657bf..611c52267d24 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -321,6 +321,7 @@ Code Seq#(hex) Include File Comments 0xDB 00-0F drivers/char/mwave/mwavepub.h 0xDD 00-3F ZFCP device driver see drivers/s390/scsi/ <mailto:aherrman@de.ibm.com> +0xE5 00-3F linux/fuse.h 0xEC 00-01 drivers/platform/chrome/cros_ec_dev.h ChromeOS EC driver 0xF3 00-3F drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development) <mailto:thomas@winischhofer.net> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index dcfc87172a47..d405c1fa4618 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2197,6 +2197,44 @@ static int fuse_dev_fasync(int fd, struct file *file, int on) return fasync_helper(fd, file, on, &fc->iq.fasync); } +static int fuse_device_clone(struct fuse_conn *fc, struct file *new) +{ + if (new->private_data) + return -EINVAL; + + new->private_data = fuse_conn_get(fc); + + return 0; +} + +static long fuse_dev_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int err = -ENOTTY; + + if (cmd == FUSE_DEV_IOC_CLONE) { + int oldfd; + + err = -EFAULT; + if (!get_user(oldfd, (__u32 __user *) arg)) { + struct file *old = fget(oldfd); + + err = -EINVAL; + if (old) { + struct fuse_conn *fc = fuse_get_conn(old); + + if (fc) { + mutex_lock(&fuse_mutex); + err = fuse_device_clone(fc, file); + mutex_unlock(&fuse_mutex); + } + fput(old); + } + } + } + return err; +} + const struct file_operations fuse_dev_operations = { .owner = THIS_MODULE, .open = fuse_dev_open, @@ -2208,6 +2246,8 @@ const struct file_operations fuse_dev_operations = { .poll = fuse_dev_poll, .release = fuse_dev_release, .fasync = fuse_dev_fasync, + .unlocked_ioctl = fuse_dev_ioctl, + .compat_ioctl = fuse_dev_ioctl, }; EXPORT_SYMBOL_GPL(fuse_dev_operations); diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 25084a052a1e..c9aca042e61d 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -755,4 +755,7 @@ struct fuse_notify_retrieve_in { uint64_t dummy4; }; +/* Device ioctls: */ +#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t) + #endif /* _LINUX_FUSE_H */ |