Module Name:    src
Committed By:   hannken
Date:           Sat Jan 12 10:43:33 UTC 2019

Modified Files:
        src/external/cddl/osnet/dist/uts/common/fs/zfs: zfs_ioctl.c
            zfs_onexit.c

Log Message:
The ZFS onexit routines expect opening ZFS_DEV with O_EXCL to return
a cloned device with an unique minor number.

Use fd_clone() on this condition to return a cloned device descriptor.


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 \
    src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c
cvs rdiff -u -r1.2 -r1.3 \
    src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_onexit.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c
diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c:1.14 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c:1.15
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c:1.14	Tue Jan  1 10:08:01 2019
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c	Sat Jan 12 10:43:33 2019
@@ -6205,6 +6205,8 @@ zfs_ctldev_init(dev_t *devp)
 
 #ifdef __FreeBSD__
 	devfs_set_cdevpriv((void *)(uintptr_t)minor, zfsdev_close);
+#else
+	*devp = makedev(major(*devp), minor);
 #endif
 
 	zs = ddi_get_soft_state(zfsdev_state, minor);
@@ -6973,11 +6975,52 @@ MODULE_DEPEND(zfsctrl, acl_nfs4, 1, 1, 1
 
 MODULE(MODULE_CLASS_DRIVER, zfs, "solaris");
 
+static const struct fileops zfs_fileops;
+
+static int
+nb_zfsdev_fioctl(struct file *fp,  u_long cmd, void *argp)
+{
+	dev_t dev = (dev_t)(uintptr_t)fp->f_data;
+	int rval;
+
+	return zfsdev_ioctl(dev, cmd, (intptr_t)argp, fp->f_flag,
+	    kauth_cred_get(), &rval);
+}
+
+static int
+nb_zfsdev_fclose(struct file *fp)
+{
+	dev_t dev = (dev_t)(uintptr_t)fp->f_data;
+	int error;
+
+	return zfsdev_close(dev, fp->f_flag, OTYPCHR, fp->f_cred);
+}
+
 static int
 nb_zfsdev_copen(dev_t dev, int flag, int mode, lwp_t *l)
 {
+	const bool must_clone = (getminor(dev) == 0 && (flag & FEXCL) != 0);
+	struct file *fp;
+	int error, fd;
+
+	if (must_clone) {
+		error = fd_allocfile(&fp, &fd);
+		if (error)
+			return error;
+	}
+
+	error = zfsdev_open(&dev, flag, OTYPCHR, kauth_cred_get());
 
-	return zfsdev_open(&dev, flag, OTYPCHR, kauth_cred_get());
+	if (must_clone) {
+		if (error) {
+			fd_abort(curproc, fp, fd);
+			return error;
+		}
+		return fd_clone(fp, fd, flag, &zfs_fileops,
+		    (void *)(uintptr_t)dev);
+	}
+
+	return error;
 }
 
 static int
@@ -7031,6 +7074,19 @@ nb_zvol_strategy(struct buf *bp)
 	(void) zvol_strategy(bp);
 }
 
+static const struct fileops zfs_fileops = {
+	.fo_name = "zfs",
+	.fo_read = fbadop_read,
+	.fo_write = fbadop_write,
+	.fo_ioctl = nb_zfsdev_fioctl,
+	.fo_fcntl = fnullop_fcntl,
+	.fo_poll = fnullop_poll,
+	.fo_stat = fbadop_stat,
+	.fo_close = nb_zfsdev_fclose,
+	.fo_kqfilter = fnullop_kqfilter,
+	.fo_restart = fnullop_restart,
+};
+
 const struct bdevsw zfs_bdevsw = {
 	.d_open = nb_zfsdev_bopen,
 	.d_close = nb_zfsdev_bclose,

Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_onexit.c
diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_onexit.c:1.2 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_onexit.c:1.3
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_onexit.c:1.2	Mon May 28 21:05:07 2018
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_onexit.c	Sat Jan 12 10:43:33 2019
@@ -146,7 +146,8 @@ zfs_onexit_fd_hold(int fd, minor_t *mino
 	if (fp == NULL)
 		return (SET_ERROR(EBADF));
 
-	*minorp = getminor(fp->f_vnode->v_rdev);
+	ASSERT(strcmp(fp->f_ops->fo_name, "zfs") == 0);
+	*minorp = minor((dev_t)(uintptr_t)fp->f_data);
 #endif
 
 	return (zfs_onexit_minor_to_state(*minorp, &zo));

Reply via email to