Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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>
+40 −0
Original line number Original line Diff line number Diff line
@@ -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 = {
	.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);


+3 −0
Original line number Original line Diff line number Diff line
@@ -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 */