git: 1f4366669ce1 - stable/12 - loader: setting vdev size based on label asize is not working
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 08 Oct 2021 06:10:58 UTC
The branch stable/12 has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=1f4366669ce1e6e9a750a90ff35a639e770a7521 commit 1f4366669ce1e6e9a750a90ff35a639e770a7521 Author: Toomas Soome <tsoome@FreeBSD.org> AuthorDate: 2020-07-09 13:19:00 +0000 Commit: Kyle Evans <kevans@FreeBSD.org> CommitDate: 2021-10-08 05:24:26 +0000 loader: setting vdev size based on label asize is not working Because we need to read asize from vdev_tree. We also need to consider different vdev type difference. (cherry picked from commit 1a4b982e1e22dc0bbcddbff082ee16abb2874871) --- stand/libsa/zfs/zfsimpl.c | 58 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c index 8f299a0a3baf..b8b06fd862d1 100644 --- a/stand/libsa/zfs/zfsimpl.c +++ b/stand/libsa/zfs/zfsimpl.c @@ -1582,6 +1582,57 @@ vdev_label_read(vdev_t *vd, int l, void *buf, uint64_t offset, return (vdev_read_phys(vd, &bp, buf, off, size)); } +static uint64_t +vdev_get_label_asize(nvlist_t *nvl) +{ + nvlist_t *vdevs; + uint64_t asize; + const char *type; + int len; + + asize = 0; + /* Get vdev tree */ + if (nvlist_find(nvl, ZPOOL_CONFIG_VDEV_TREE, DATA_TYPE_NVLIST, + NULL, &vdevs, NULL) != 0) + return (asize); + + /* + * Get vdev type. We will calculate asize for raidz, mirror and disk. + * For raidz, the asize is raw size of all children. + */ + if (nvlist_find(vdevs, ZPOOL_CONFIG_TYPE, DATA_TYPE_STRING, + NULL, &type, &len) != 0) + goto done; + + if (memcmp(type, VDEV_TYPE_MIRROR, len) != 0 && + memcmp(type, VDEV_TYPE_DISK, len) != 0 && + memcmp(type, VDEV_TYPE_RAIDZ, len) != 0) + goto done; + + if (nvlist_find(vdevs, ZPOOL_CONFIG_ASIZE, DATA_TYPE_UINT64, + NULL, &asize, NULL) != 0) + goto done; + + if (memcmp(type, VDEV_TYPE_RAIDZ, len) == 0) { + nvlist_t *kids; + int nkids; + + if (nvlist_find(vdevs, ZPOOL_CONFIG_CHILDREN, + DATA_TYPE_NVLIST_ARRAY, &nkids, &kids, NULL) != 0) { + asize = 0; + goto done; + } + + asize /= nkids; + nvlist_destroy(kids); + } + + asize += VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE; +done: + nvlist_destroy(vdevs); + return (asize); +} + static nvlist_t * vdev_label_read_config(vdev_t *vd, uint64_t txg) { @@ -1627,10 +1678,9 @@ vdev_label_read_config(vdev_t *vd, uint64_t txg) * Use asize from pool config. We need this * because we can get bad value from BIOS. */ - if (nvlist_find(nvl, ZPOOL_CONFIG_ASIZE, - DATA_TYPE_UINT64, NULL, &asize, NULL) == 0) { - vd->v_psize = asize + - VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE; + asize = vdev_get_label_asize(nvl); + if (asize != 0) { + vd->v_psize = asize; } } nvlist_destroy(tmp);