Commit 00c570f4 authored by Miklos Szeredi's avatar Miklos Szeredi

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: default avatarMiklos Szeredi <mszeredi@suse.cz>
Reviewed-by: default avatarAshish Samant <ashish.samant@oracle.com>
parent ee314a87
...@@ -321,6 +321,7 @@ Code Seq#(hex) Include File Comments ...@@ -321,6 +321,7 @@ Code Seq#(hex) Include File Comments
0xDB 00-0F drivers/char/mwave/mwavepub.h 0xDB 00-0F drivers/char/mwave/mwavepub.h
0xDD 00-3F ZFCP device driver see drivers/s390/scsi/ 0xDD 00-3F ZFCP device driver see drivers/s390/scsi/
<mailto:aherrman@de.ibm.com> <mailto:aherrman@de.ibm.com>
0xE5 00-3F linux/fuse.h
0xEC 00-01 drivers/platform/chrome/cros_ec_dev.h ChromeOS EC driver 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) 0xF3 00-3F drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development)
<mailto:thomas@winischhofer.net> <mailto:thomas@winischhofer.net>
......
...@@ -2197,6 +2197,44 @@ static int fuse_dev_fasync(int fd, struct file *file, int on) ...@@ -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); 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 = { const struct file_operations fuse_dev_operations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = fuse_dev_open, .open = fuse_dev_open,
...@@ -2208,6 +2246,8 @@ const struct file_operations fuse_dev_operations = { ...@@ -2208,6 +2246,8 @@ const struct file_operations fuse_dev_operations = {
.poll = fuse_dev_poll, .poll = fuse_dev_poll,
.release = fuse_dev_release, .release = fuse_dev_release,
.fasync = fuse_dev_fasync, .fasync = fuse_dev_fasync,
.unlocked_ioctl = fuse_dev_ioctl,
.compat_ioctl = fuse_dev_ioctl,
}; };
EXPORT_SYMBOL_GPL(fuse_dev_operations); EXPORT_SYMBOL_GPL(fuse_dev_operations);
......
...@@ -755,4 +755,7 @@ struct fuse_notify_retrieve_in { ...@@ -755,4 +755,7 @@ struct fuse_notify_retrieve_in {
uint64_t dummy4; uint64_t dummy4;
}; };
/* Device ioctls: */
#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t)
#endif /* _LINUX_FUSE_H */ #endif /* _LINUX_FUSE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment