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;