diff --git a/stand/libsa/zfs/zfs.c b/stand/libsa/zfs/zfs.c --- a/stand/libsa/zfs/zfs.c +++ b/stand/libsa/zfs/zfs.c @@ -798,35 +798,12 @@ int zfs_get_bootenv(void *vdev, nvlist_t **benvp) { - struct zfs_devdesc *dev = (struct zfs_devdesc *)vdev; - nvlist_t *benv = NULL; - vdev_t *vd; spa_t *spa; - if (dev->dd.d_dev->dv_type != DEVT_ZFS) - return (ENOTSUP); - - if ((spa = spa_find_by_dev(dev)) == NULL) + if ((spa = spa_find_by_dev((struct zfs_devdesc *)vdev)) == NULL) return (ENXIO); - if (spa->spa_bootenv == NULL) { - STAILQ_FOREACH(vd, &spa->spa_root_vdev->v_children, - v_childlink) { - benv = vdev_read_bootenv(vd); - - if (benv != NULL) - break; - } - spa->spa_bootenv = benv; - } else { - benv = spa->spa_bootenv; - } - - if (benv == NULL) - return (ENOENT); - - *benvp = benv; - return (0); + return (zfs_get_bootenv_spa(spa, benvp)); } /* diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c --- a/stand/libsa/zfs/zfsimpl.c +++ b/stand/libsa/zfs/zfsimpl.c @@ -3853,3 +3853,33 @@ free(entry); return (rc); } + +/* + * Return either a cached copy of the bootenv, or read each of the vdev children + * looking for the bootenv. Cache what's found and return the results. Returns 0 + * when benvp is filled in, and some errno when not. + */ +static int +zfs_get_bootenv_spa(spa_t *spa, nvlist_t **benvp) +{ + vdev_t *vd; + nvlist_t *benv = NULL; + + if (spa->spa_bootenv == NULL) { + STAILQ_FOREACH(vd, &spa->spa_root_vdev->v_children, + v_childlink) { + benv = vdev_read_bootenv(vd); + + if (benv != NULL) + break; + } + spa->spa_bootenv = benv; + } + benv = spa->spa_bootenv; + + if (benv == NULL) + return (ENOENT); + + *benvp = benv; + return (0); +}