From 44d5374cb94c56b9a82f26def1fc8f701c6aa8b1 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Fri, 5 Aug 2016 10:32:05 +0300 Subject: [PATCH] libbe: be_do_installboot() pool traverse rewrite. The pool traverse in be_do_installboot() is faulty and can cause an attempt to install bootblock on non-leaf devices. --- usr/src/lib/libbe/common/be_activate.c | 41 ++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/usr/src/lib/libbe/common/be_activate.c b/usr/src/lib/libbe/common/be_activate.c index cbd7fb7e8a..9602333a56 100644 --- a/usr/src/lib/libbe/common/be_activate.c +++ b/usr/src/lib/libbe/common/be_activate.c @@ -1222,6 +1222,7 @@ be_do_installboot(be_transaction_data_t *bt, uint16_t flags) int ret = BE_SUCCESS; boolean_t be_mounted = B_FALSE; boolean_t update = B_FALSE; + boolean_t verbose = B_FALSE; /* * check versions. This call is to support detached @@ -1233,6 +1234,7 @@ be_do_installboot(be_transaction_data_t *bt, uint16_t flags) if (ret != BE_SUCCESS || update == B_FALSE) return (ret); } + verbose = do_print; if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) { @@ -1326,7 +1328,9 @@ be_do_installboot(be_transaction_data_t *bt, uint16_t flags) for (c = 0; c < children; c++) { uint_t i, nchildren = 0; nvlist_t **nvchild; - vname = zpool_vdev_name(g_zfs, zphp, child[c], B_FALSE); + + /* ensure update on child status */ + vname = zpool_vdev_name(g_zfs, zphp, child[c], verbose); if (vname == NULL) { be_print_err(gettext( "be_do_installboot: " @@ -1334,30 +1338,49 @@ be_do_installboot(be_transaction_data_t *bt, uint16_t flags) libzfs_error_description(g_zfs)); ret = zfs_err_to_be_err(g_zfs); goto done; + } else if (verbose == B_TRUE) { + be_print_err(gettext("be_do_installboot: " + "device %s\n"), vname); } - if (strcmp(vname, "mirror") == 0 || - strcmp(vname, "raidz") == 0 || - vname[0] != 'c') { - free(vname); + free(vname); - if (nvlist_lookup_nvlist_array(child[c], - ZPOOL_CONFIG_CHILDREN, &nvchild, &nchildren) != 0) { + ret = nvlist_lookup_nvlist_array(child[c], + ZPOOL_CONFIG_CHILDREN, &nvchild, &nchildren); + if (ret != 0) { + if (ret != ENOENT) { be_print_err(gettext("be_do_installboot: " "failed to traverse the vdev tree: %s\n"), libzfs_error_description(g_zfs)); ret = zfs_err_to_be_err(g_zfs); goto done; } + nchildren = 0; /* This is leaf device. */ + } + if (nchildren != 0) { for (i = 0; i < nchildren; i++) { + /* ensure update on child status */ + vname = zpool_vdev_name(g_zfs, zphp, + nvchild[i], verbose); + if (vname == NULL) { + be_print_err(gettext( + "be_do_installboot: " + "failed to get device name: %s\n"), + libzfs_error_description(g_zfs)); + ret = zfs_err_to_be_err(g_zfs); + goto done; + } else if (verbose == B_TRUE) { + be_print_err(gettext( + "be_do_installboot: device %s\n"), + vname); + } + free(vname); ret = be_do_installboot_helper(zphp, nvchild[i], stage1, stage2, flags); if (ret != BE_SUCCESS) goto done; } } else { - free(vname); - ret = be_do_installboot_helper(zphp, child[c], stage1, stage2, flags); if (ret != BE_SUCCESS) -- 2.11.4.GIT