Backport from ml:

commit 00c570f4ba43ae73b41fa0a2269c3b0ac20386ef
Author: Miklos Szeredi <[email protected]>
Date:   Wed Jul 1 16:26:08 2015 +0200

    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 <[email protected]>
    Reviewed-by: Ashish Samant <[email protected]>

Signed-off-by: Maxim Patlasov <[email protected]>
---
 Documentation/ioctl/ioctl-number.txt |    1 +
 fs/fuse/dev.c                        |   40 ++++++++++++++++++++++++++++++++++
 include/uapi/linux/fuse.h            |    3 +++
 3 files changed, 44 insertions(+)

diff --git a/Documentation/ioctl/ioctl-number.txt 
b/Documentation/ioctl/ioctl-number.txt
index cc47d4e..ddaa510 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -323,6 +323,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:[email protected]>
+0xE5   00-3F   linux/fuse.h
 0xF3   00-3F   drivers/usb/misc/sisusbvga/sisusb.h     sisfb (in development)
                                        <mailto:[email protected]>
 0xF4   00-1F   video/mbxfb.h           mbxfb
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 70694ed..c2aac08 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2192,6 +2192,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,
        .llseek         = no_llseek,
@@ -2204,6 +2242,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 cb3cd15..3262980 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -749,4 +749,7 @@ struct fuse_notify_inval_files_out {
        __u64   ino;
 };
 
+/* Device ioctls: */
+#define FUSE_DEV_IOC_CLONE     _IOR(229, 0, uint32_t)
+
 #endif /* _LINUX_FUSE_H */

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to