Module Name:    src
Committed By:   hannken
Date:           Wed May 22 08:44:49 UTC 2019

Modified Files:
        src/external/cddl/osnet/dist/uts/common/fs/zfs: zfs_ioctl.c zvol.c
        src/external/cddl/osnet/sys/kern: ddi.c
        src/external/cddl/osnet/sys/sys: sunddi.h

Log Message:
Update ddi environment:
- Put device major numbers into "dev_info_t".
- Fix an off-by-one in zvol_create_minor().
- When creating a node handle existing nodes
  and add owner read/write permission.
- When removing nodes remove now empty directories.


To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 \
    src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c
cvs rdiff -u -r1.8 -r1.9 \
    src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c
cvs rdiff -u -r1.6 -r1.7 src/external/cddl/osnet/sys/kern/ddi.c
cvs rdiff -u -r1.5 -r1.6 src/external/cddl/osnet/sys/sys/sunddi.h

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.17 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c:1.18
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c:1.17	Tue May  7 08:51:09 2019
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c	Wed May 22 08:44:48 2019
@@ -211,11 +211,8 @@ static struct cdev *zfsdev;
 #endif
 
 #ifdef __NetBSD__
-static int zfs_cmajor = -1;
-static int zfs_bmajor = -1;
-dev_info_t *zfs_dip;
-
-#define ddi_driver_major(x)	zfs_cmajor
+static dev_info_t __zfs_devinfo = { -1, -1 };
+dev_info_t *zfs_dip = &__zfs_devinfo;
 
 #define zfs_init() /* nothing */
 #define zfs_fini() /* nothing */
@@ -7204,8 +7201,8 @@ zfs_modcmd(modcmd_t cmd, void *arg)
 		zfs_ioctl_init();
 		zfs_sysctl_init();
 
-		error = devsw_attach("zfs", &zfs_bdevsw, &zfs_bmajor,
-		    &zfs_cdevsw, &zfs_cmajor);
+		error = devsw_attach("zfs", &zfs_bdevsw, &zfs_dip->di_bmajor,
+		    &zfs_cdevsw, &zfs_dip->di_cmajor);
 		if (error != 0) {
 			goto attacherr;
 		}

Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c
diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c:1.8 src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c:1.9
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c:1.8	Mon May 28 21:05:07 2018
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c	Wed May 22 08:44:48 2019
@@ -676,7 +676,7 @@ zvol_create_minor(const char *name)
 	minor_t minor = 0;
 	vnode_t *vp = NULL;
 	char *devpath;
-	size_t devpathlen = strlen(ZVOL_FULL_DEV_DIR) + strlen(name) + 1;
+	size_t devpathlen = strlen(ZVOL_FULL_DEV_DIR) + strlen(name) + 2;
 #endif
 
 	mutex_enter(&zfsdev_state_lock);

Index: src/external/cddl/osnet/sys/kern/ddi.c
diff -u src/external/cddl/osnet/sys/kern/ddi.c:1.6 src/external/cddl/osnet/sys/kern/ddi.c:1.7
--- src/external/cddl/osnet/sys/kern/ddi.c:1.6	Mon May 28 21:05:09 2018
+++ src/external/cddl/osnet/sys/kern/ddi.c	Wed May 22 08:44:48 2019
@@ -65,6 +65,7 @@
 #include <sys/cmn_err.h>
 #include <sys/namei.h>
 #include <sys/stat.h>
+#include <sys/vnode.h>
 #include <sys/vfs_syscalls.h>
 
 __strong_alias(ddi_strtol,ddi_strtoul)
@@ -142,6 +143,50 @@ do_mkdirp(const char *path)
 	return error;
 }
 
+static void
+do_rmdirp(const char *path)
+{
+	struct pathbuf *pb;
+	struct nameidata nd;
+	char *here, *e;
+	int error;
+
+	here = PNBUF_GET();
+	strlcpy(here, path, MAXPATHLEN);
+	while ((e = strrchr(here, '/')) && e != here) {
+		*e = '\0';
+		pb = pathbuf_create(here);
+		if (pb == NULL)
+			break;
+		/* XXX need do_sys_rmdir()? */
+		NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, pb);
+		error = namei(&nd);
+		if (error) {
+			pathbuf_destroy(pb);
+			break;
+		}
+		if ((nd.ni_vp->v_vflag & VV_ROOT) ||
+		    nd.ni_vp->v_type != VDIR ||
+		    nd.ni_vp->v_mountedhere ||
+		    nd.ni_vp == nd.ni_dvp) {
+			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+			if (nd.ni_vp == nd.ni_dvp)
+				vrele(nd.ni_dvp);
+			else
+				vput(nd.ni_dvp);
+			vput(nd.ni_vp);
+			pathbuf_destroy(pb);
+			break;
+		}
+		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
+		vput(nd.ni_dvp);
+		pathbuf_destroy(pb);
+		if (error)
+			break;
+	}
+	PNBUF_PUT(here);
+}
+
 int
 ddi_strtoul(const char *str, char **nptr, int base, unsigned long *result)
 {
@@ -562,25 +607,49 @@ ddi_create_minor_node(dev_info_t *dip, c
     minor_t minor_num, char *node_type, int flag)
 {
 	struct lwp *l = curlwp;
+	vnode_t *vp;
+	enum vtype vtype;
+	struct stat sb;
 	char *pn;
 	dev_t dev;
 	int error;
 	register_t ret;
 
-	printf("ddi_create_minor_node: name %s\n", name);
-
-	dev = makedev(flag, minor_num);
-	
 	pn = PNBUF_GET();
-	if (spec_type == S_IFCHR)
+	if (spec_type == S_IFCHR) {
+		vtype = VCHR;
+		dev = makedev(dip->di_cmajor, minor_num);
 		snprintf(pn, MAXPATHLEN, "/dev/zvol/rdsk/%s", name);
-	else
+	} else if (spec_type == S_IFBLK) {
+		vtype = VBLK;
+		dev = makedev(dip->di_bmajor, minor_num);
 		snprintf(pn, MAXPATHLEN, "/dev/zvol/dsk/%s", name);
+	} else {
+		panic("bad spectype %#x", spec_type);
+	}
+	spec_type |= (S_IRUSR | S_IWUSR);
 
+	/* Create missing directories. */
 	if ((error = do_mkdirp(pn)) != 0)
 		goto exit;
-	
-	error = do_sys_mknod(l, (const char *)pn, spec_type, dev, &ret, UIO_SYSSPACE);
+
+	/*
+	 * If node exists and has correct type and rdev all done,
+	 * otherwise unlink the node.
+	 */
+	if (namei_simple_kernel(pn, NSM_NOFOLLOW_NOEMULROOT, &vp) == 0) {
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+		error = vn_stat(vp, &sb);
+		VOP_UNLOCK(vp, 0);
+		if (error == 0 && vp->v_type == vtype && sb.st_rdev == dev) {
+			vrele(vp);
+			return 0;
+		}
+		vrele(vp);
+		(void)do_sys_unlink(pn, UIO_SYSSPACE);
+	}
+
+	error = do_sys_mknod(l, pn, spec_type, dev, &ret, UIO_SYSSPACE);
 
 exit:
 	PNBUF_PUT(pn);
@@ -592,17 +661,19 @@ void
 ddi_remove_minor_node(dev_info_t *dip, char *name)
 {
 	char *pn;
-	int error;
 
+	/* Unlink block device and remove empty directories. */
 	pn = PNBUF_GET();
 	snprintf(pn, MAXPATHLEN, "/dev/zvol/dsk/%s", name);
 	(void)do_sys_unlink(pn, UIO_SYSSPACE);
+	do_rmdirp(pn);
 	PNBUF_PUT(pn);
 
-	/* We need to remove raw and block device nodes */
+	/* Unlink raw device and remove empty directories. */
 	pn = PNBUF_GET();
 	snprintf(pn, MAXPATHLEN, "/dev/zvol/rdsk/%s", name);
 	(void)do_sys_unlink(pn, UIO_SYSSPACE);
+	do_rmdirp(pn);
 	PNBUF_PUT(pn);
 }
 

Index: src/external/cddl/osnet/sys/sys/sunddi.h
diff -u src/external/cddl/osnet/sys/sys/sunddi.h:1.5 src/external/cddl/osnet/sys/sys/sunddi.h:1.6
--- src/external/cddl/osnet/sys/sys/sunddi.h:1.5	Mon May 28 21:05:10 2018
+++ src/external/cddl/osnet/sys/sys/sunddi.h	Wed May 22 08:44:48 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: sunddi.h,v 1.5 2018/05/28 21:05:10 chs Exp $	*/
+/*	$NetBSD: sunddi.h,v 1.6 2019/05/22 08:44:48 hannken Exp $	*/
 
 /*-
  * Copyright (c) 2007 Pawel Jakub Dawidek <p...@freebsd.org>
@@ -70,7 +70,12 @@ int _ddi_log_sysevent(char *vendor, char
 
 #define	DDI_PSEUDO	""
 
-typedef void	*dev_info_t;
+struct dev_info {
+	int di_cmajor;
+	int di_bmajor;
+};
+typedef struct dev_info dev_info_t;
+
 int	ddi_create_minor_node(dev_info_t *, char *, int,
                               minor_t, char *, int);
 void	ddi_remove_minor_node(dev_info_t *, char *);

Reply via email to