Module Name:    src
Committed By:   mlelstv
Date:           Sat Feb 29 17:03:33 UTC 2020

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

Log Message:
Fix disk geometry calculation. Add DIOCGPARTINFO to support
getdisksize() used by other drivers, filesystems and specfs.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 \
    src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.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/zvol.c
diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c:1.12 src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c:1.13
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c:1.12	Wed May 22 08:47:02 2019
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zvol.c	Sat Feb 29 17:03:33 2020
@@ -72,6 +72,9 @@
 #include <sys/dnode.h>
 #include <sys/dsl_dataset.h>
 #include <sys/dsl_prop.h>
+#ifdef __NetBSD__
+#include <sys/disklabel.h>
+#endif
 #include <sys/dkio.h>
 #include <sys/byteorder.h>
 #include <sys/sunddi.h>
@@ -316,12 +319,17 @@ zvol_size_changed(zvol_state_t *zv, uint
 #endif /* __FreeBSD__ */
 #ifdef __NetBSD__
 	struct disk_geom *dg = &zv->zv_dk.dk_geom;
+	objset_t *os = zv->zv_objset;
+	spa_t *spa = dmu_objset_spa(os);
+	unsigned secsize;
 
 	zv->zv_volsize = volsize;
 
+	secsize = MAX(DEV_BSIZE, 1U << spa->spa_max_ashift);
+
 	memset(dg, 0, sizeof(*dg));
-	dg->dg_secsize = DEV_BSIZE; /* XXX 512? */
-	dg->dg_secperunit = zv->zv_volsize / dg->dg_secsize;;
+	dg->dg_secsize = secsize;
+	dg->dg_secperunit = volsize / secsize;
 	disk_set_info(NULL, &zv->zv_dk, "ZVOL");
 #endif
 }
@@ -3589,19 +3597,47 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t 
 	case DIOCGWEDGEINFO:
 	{
 		struct dkwedge_info *dkw = (void *) arg;
-		
+		struct disk_geom *dg = &zv->zv_dk.dk_geom;
+
 		memset(dkw, 0, sizeof(*dkw));
 		strlcpy(dkw->dkw_devname, zv->zv_name,
 		    sizeof(dkw->dkw_devname));
+
+		/*
+		 * dkw_parent is interpreted as disk device name by the kernel
+		 * to locate the disk driver and its geometry data. The faked
+		 * name "ZFS" must never match a device name. The kernel will
+		 * then call DIOCGPARTINFO below to retrieve the missing
+		 * information.
+		 *
+		 * Userland will also be confused, but it can use the
+		 * proplib based DIOCGDISKINFO to get the geometry
+		 * information.
+		 */
 		strlcpy(dkw->dkw_parent, "ZFS", sizeof(dkw->dkw_parent));
-		
+
 		dkw->dkw_offset = 0;
-		dkw->dkw_size = zv->zv_volsize / DEV_BSIZE;
+		dkw->dkw_size = dg->dg_secperunit;
 		strcpy(dkw->dkw_ptype, DKW_PTYPE_FFS);
 
 		break;
 	}
 
+	case DIOCGPARTINFO:
+	{
+		struct partinfo *pi = (void *) arg;
+		struct disk_geom *dg = &zv->zv_dk.dk_geom;
+
+		memset(pi, 0, sizeof(*pi));
+		pi->pi_offset = 0;
+		pi->pi_secsize = dg->dg_secsize;
+		pi->pi_size = dg->dg_secperunit;
+		pi->pi_fstype = FS_OTHER;
+		pi->pi_bsize = MAX(BLKDEV_IOSIZE, pi->pi_secsize);
+
+		break;
+	}
+
 	default:
 		dprintf("unknown disk_ioctl called\n");
 		error = ENOTTY;

Reply via email to