diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c index d15818c0b292..8fba88570b27 100644 --- a/stand/libsa/zfs/zfsimpl.c +++ b/stand/libsa/zfs/zfsimpl.c @@ -1102,7 +1102,7 @@ vdev_init_from_nvlist(const unsigned char *nvlist, vdev_t *pvdev, vdev_t **vdevp, int is_newer) { int rc; - uint64_t guid, id, ashift, nparity; + uint64_t guid, id, ashift, asize, nparity; const char *type; const char *path; vdev_t *vdev, *kid; @@ -1181,6 +1181,11 @@ vdev_init_from_nvlist(const unsigned char *nvlist, vdev_t *pvdev, } else { vdev->v_ashift = 0; } + if (nvlist_find(nvlist, ZPOOL_CONFIG_ASIZE, + DATA_TYPE_UINT64, NULL, &asize) == 0) { + vdev->v_psize = asize + + VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE; + } if (nvlist_find(nvlist, ZPOOL_CONFIG_NPARITY, DATA_TYPE_UINT64, NULL, &nparity) == 0) { vdev->v_nparity = nparity; @@ -1547,7 +1552,6 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap) uint64_t guid; uint64_t best_txg = 0; uint64_t pool_txg, pool_guid; - uint64_t psize; const char *pool_name; const unsigned char *vdevs; const unsigned char *features; @@ -1562,17 +1566,17 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap) memset(&vtmp, 0, sizeof(vtmp)); vtmp.v_phys_read = _read; vtmp.v_read_priv = read_priv; - psize = P2ALIGN(ldi_get_size(read_priv), + vtmp.v_psize = P2ALIGN(ldi_get_size(read_priv), (uint64_t)sizeof (vdev_label_t)); /* Test for minimum pool size. */ - if (psize < SPA_MINDEVSIZE) + if (vtmp.v_psize < SPA_MINDEVSIZE) return (EIO); tmp_label = zfs_alloc(sizeof(vdev_phys_t)); for (l = 0; l < VDEV_LABELS; l++) { - off = vdev_label_offset(psize, l, + off = vdev_label_offset(vtmp.v_psize, l, offsetof(vdev_label_t, vl_vdev_phys)); BP_ZERO(&bp); @@ -1595,8 +1599,20 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap) continue; if (best_txg <= pool_txg) { + uint64_t asize; + best_txg = pool_txg; memcpy(vdev_label, tmp_label, sizeof (vdev_phys_t)); + + /* + * Use asize from pool config. We need this + * because we can get bad value from BIOS. + */ + if (nvlist_find(nvlist, ZPOOL_CONFIG_ASIZE, + DATA_TYPE_UINT64, NULL, &asize) == 0) { + vtmp.v_psize = asize + + VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE; + } } } @@ -1716,6 +1732,7 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap) vdev->v_phys_read = _read; vdev->v_read_priv = read_priv; vdev->v_state = VDEV_STATE_HEALTHY; + vdev->v_psize = vtmp.v_psize; } else { printf("ZFS: inconsistent nvlist contents\n"); return (EIO); @@ -1735,7 +1752,7 @@ vdev_probe(vdev_phys_read_t *_read, void *read_priv, spa_t **spap) up = (const struct uberblock *)upbuf; for (l = 0; l < VDEV_LABELS; l++) { for (i = 0; i < VDEV_UBERBLOCK_COUNT(vdev); i++) { - off = vdev_label_offset(psize, l, + off = vdev_label_offset(vdev->v_psize, l, VDEV_UBERBLOCK_OFFSET(vdev, i)); BP_ZERO(&bp); DVA_SET_OFFSET(&bp.blk_dva[0], off); diff --git a/sys/cddl/boot/zfs/zfsimpl.h b/sys/cddl/boot/zfs/zfsimpl.h index 8d291e1916eb..aa80a30d7ada 100644 --- a/sys/cddl/boot/zfs/zfsimpl.h +++ b/sys/cddl/boot/zfs/zfsimpl.h @@ -1660,7 +1660,8 @@ typedef struct vdev { vdev_list_t v_children; /* children of this vdev */ const char *v_name; /* vdev name */ uint64_t v_guid; /* vdev guid */ - int v_id; /* index in parent */ + uint64_t v_id; /* index in parent */ + uint64_t v_psize; /* physical device capacity */ int v_ashift; /* offset to block shift */ int v_nparity; /* # parity for raidz */ struct vdev *v_top; /* parent vdev */