summaryrefslogtreecommitdiff
path: root/usr/src/lib/libbe
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libbe')
-rw-r--r--usr/src/lib/libbe/common/be_activate.c153
-rw-r--r--usr/src/lib/libbe/common/libbe.h13
-rw-r--r--usr/src/lib/libbe/common/mapfile-vers1
3 files changed, 146 insertions, 21 deletions
diff --git a/usr/src/lib/libbe/common/be_activate.c b/usr/src/lib/libbe/common/be_activate.c
index 985a585094..6eda8eebba 100644
--- a/usr/src/lib/libbe/common/be_activate.c
+++ b/usr/src/lib/libbe/common/be_activate.c
@@ -55,8 +55,8 @@ static int set_bootfs(char *boot_rpool, char *be_root_ds);
static int set_canmount(be_node_list_t *, char *);
static boolean_t be_do_install_mbr(char *, nvlist_t *);
static int be_do_installboot_helper(zpool_handle_t *, nvlist_t *, char *,
- char *);
-static int be_do_installboot(be_transaction_data_t *);
+ char *, uint16_t);
+static int be_do_installboot(be_transaction_data_t *, uint16_t);
static int be_get_grub_vers(be_transaction_data_t *, char **, char **);
static int get_ver_from_capfile(char *, char **);
static int be_promote_zone_ds(char *, char *);
@@ -119,6 +119,82 @@ be_activate(nvlist_t *be_attrs)
return (ret);
}
+/*
+ * Function: be_installboot
+ * Description: Calls be_do_installboot to install/update bootloader on
+ * pool passed in through be_attrs. The primary consumer is
+ * bootadm command to avoid duplication of the code.
+ * Parameters:
+ * be_attrs - pointer to nvlist_t of attributes being passed in.
+ * The following attribute values are used:
+ *
+ * BE_ATTR_ORIG_BE_NAME *required
+ * BE_ATTR_ORIG_BE_POOL *required
+ * BE_ATTR_ORIG_BE_ROOT *required
+ * BE_ATTR_INSTALL_FLAGS optional
+ *
+ * Return:
+ * BE_SUCCESS - Success
+ * be_errno_t - Failure
+ * Scope:
+ * Public
+ */
+int
+be_installboot(nvlist_t *be_attrs)
+{
+ int ret = BE_SUCCESS;
+ uint16_t flags = 0;
+ uint16_t verbose;
+ be_transaction_data_t bt = { 0 };
+
+ /* Get flags */
+ if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
+ BE_ATTR_INSTALL_FLAGS, DATA_TYPE_UINT16, &flags, NULL) != 0) {
+ be_print_err(gettext("be_installboot: failed to lookup "
+ "BE_ATTR_INSTALL_FLAGS attribute\n"));
+ return (BE_ERR_INVAL);
+ }
+
+ /* Set verbose early, so we get all messages */
+ verbose = flags & BE_INSTALLBOOT_FLAG_VERBOSE;
+ if (verbose == BE_INSTALLBOOT_FLAG_VERBOSE)
+ libbe_print_errors(B_TRUE);
+
+ ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME,
+ &bt.obe_name);
+ if (ret != 0) {
+ be_print_err(gettext("be_installboot: failed to "
+ "lookup BE_ATTR_ORIG_BE_NAME attribute\n"));
+ return (BE_ERR_INVAL);
+ }
+
+ ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_POOL,
+ &bt.obe_zpool);
+ if (ret != 0) {
+ be_print_err(gettext("be_installboot: failed to "
+ "lookup BE_ATTR_ORIG_BE_POOL attribute\n"));
+ return (BE_ERR_INVAL);
+ }
+
+ ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_ROOT,
+ &bt.obe_root_ds);
+ if (ret != 0) {
+ be_print_err(gettext("be_installboot: failed to "
+ "lookup BE_ATTR_ORIG_BE_ROOT attribute\n"));
+ return (BE_ERR_INVAL);
+ }
+
+ /* Initialize libzfs handle */
+ if (!be_zfs_init())
+ return (BE_ERR_INIT);
+
+ ret = be_do_installboot(&bt, flags);
+
+ be_zfs_fini();
+
+ return (ret);
+}
+
/* ******************************************************************** */
/* Semi Private Functions */
/* ******************************************************************** */
@@ -175,7 +251,8 @@ _be_activate(char *be_name)
cb.obe_root_ds = strdup(root_ds);
if (getzoneid() == GLOBAL_ZONEID) {
- if ((ret = be_do_installboot(&cb)) != BE_SUCCESS)
+ ret = be_do_installboot(&cb, BE_INSTALLBOOT_FLAG_NULL);
+ if (ret != BE_SUCCESS)
return (ret);
if (!be_has_menu_entry(root_ds, cb.obe_zpool, &entry)) {
@@ -794,14 +871,16 @@ be_do_install_mbr(char *diskname, nvlist_t *child)
static int
be_do_installboot_helper(zpool_handle_t *zphp, nvlist_t *child, char *stage1,
- char *stage2)
+ char *stage2, uint16_t flags)
{
char install_cmd[MAXPATHLEN];
char be_run_cmd_errbuf[BUFSIZ];
+ char be_run_cmd_outbuf[BUFSIZ];
char diskname[MAXPATHLEN];
char *vname;
char *path, *dsk_ptr;
char *flag = "";
+ int ret;
if (nvlist_lookup_string(child, ZPOOL_CONFIG_PATH, &path) != 0) {
be_print_err(gettext("be_do_installboot: "
@@ -836,31 +915,60 @@ be_do_installboot_helper(zpool_handle_t *zphp, nvlist_t *child, char *stage1,
}
if (be_is_isa("i386")) {
- if (be_do_install_mbr(diskname, child))
- flag = "-m -f";
+ uint16_t force = flags & BE_INSTALLBOOT_FLAG_FORCE;
+ uint16_t mbr = flags & BE_INSTALLBOOT_FLAG_MBR;
+
+ if (force == BE_INSTALLBOOT_FLAG_FORCE) {
+ if (mbr == BE_INSTALLBOOT_FLAG_MBR ||
+ be_do_install_mbr(diskname, child))
+ flag = "-F -m -f";
+ else
+ flag = "-F";
+ } else {
+ if (mbr == BE_INSTALLBOOT_FLAG_MBR ||
+ be_do_install_mbr(diskname, child))
+ flag = "-m -f";
+ }
+
(void) snprintf(install_cmd, sizeof (install_cmd),
"%s %s %s %s %s", BE_INSTALL_GRUB, flag,
stage1, stage2, diskname);
} else {
- flag = "-F zfs";
+ if ((flags & BE_INSTALLBOOT_FLAG_FORCE) ==
+ BE_INSTALLBOOT_FLAG_FORCE)
+ flag = "-f -F zfs";
+ else
+ flag = "-F zfs";
+
(void) snprintf(install_cmd, sizeof (install_cmd),
"%s %s %s %s", BE_INSTALL_BOOT, flag, stage2, diskname);
}
- if (be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ, NULL, 0)
- != BE_SUCCESS) {
+ *be_run_cmd_outbuf = '\0';
+ *be_run_cmd_errbuf = '\0';
+
+ ret = be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ,
+ be_run_cmd_outbuf, BUFSIZ);
+
+ if (ret != BE_SUCCESS) {
be_print_err(gettext("be_do_installboot: install "
"failed for device %s.\n"), vname);
- /* Assume localized cmd err output. */
- be_print_err(gettext(" Command: \"%s\"\n"),
- install_cmd);
+ ret = BE_ERR_BOOTFILE_INST;
+ }
+
+ be_print_err(gettext(" Command: \"%s\"\n"), install_cmd);
+ if (be_run_cmd_outbuf[0] != 0) {
+ be_print_err(gettext(" Output:\n"));
+ be_print_err("%s", be_run_cmd_outbuf);
+ }
+
+ if (be_run_cmd_errbuf[0] != 0) {
+ be_print_err(gettext(" Errors:\n"));
be_print_err("%s", be_run_cmd_errbuf);
- free(vname);
- return (BE_ERR_BOOTFILE_INST);
}
free(vname);
- return (BE_SUCCESS);
+ return (ret);
}
/*
@@ -1069,6 +1177,7 @@ be_is_install_needed(be_transaction_data_t *bt, boolean_t *update)
*
* Parameters:
* bt - The transaction data for the BE we're activating.
+ * flags - flags for bootloader install
* Return:
* BE_SUCCESS - Success
* be_errno_t - Failure
@@ -1077,7 +1186,7 @@ be_is_install_needed(be_transaction_data_t *bt, boolean_t *update)
* Private
*/
static int
-be_do_installboot(be_transaction_data_t *bt)
+be_do_installboot(be_transaction_data_t *bt, uint16_t flags)
{
zpool_handle_t *zphp = NULL;
zfs_handle_t *zhp = NULL;
@@ -1096,9 +1205,11 @@ be_do_installboot(be_transaction_data_t *bt)
* version implementation like grub. Embedded versioning is
* checked by actual installer.
*/
- ret = be_is_install_needed(bt, &update);
- if (ret != BE_SUCCESS || update == B_FALSE)
- return (ret);
+ if ((flags & BE_INSTALLBOOT_FLAG_FORCE) != BE_INSTALLBOOT_FLAG_FORCE) {
+ ret = be_is_install_needed(bt, &update);
+ if (ret != BE_SUCCESS || update == B_FALSE)
+ return (ret);
+ }
if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) ==
NULL) {
@@ -1205,7 +1316,7 @@ be_do_installboot(be_transaction_data_t *bt)
for (i = 0; i < nchildren; i++) {
ret = be_do_installboot_helper(zphp, nvchild[i],
- stage1, stage2);
+ stage1, stage2, flags);
if (ret != BE_SUCCESS)
goto done;
}
@@ -1213,7 +1324,7 @@ be_do_installboot(be_transaction_data_t *bt)
free(vname);
ret = be_do_installboot_helper(zphp, child[c], stage1,
- stage2);
+ stage2, flags);
if (ret != BE_SUCCESS)
goto done;
}
diff --git a/usr/src/lib/libbe/common/libbe.h b/usr/src/lib/libbe/common/libbe.h
index c5662893a2..994bc881ac 100644
--- a/usr/src/lib/libbe/common/libbe.h
+++ b/usr/src/lib/libbe/common/libbe.h
@@ -42,6 +42,7 @@ extern "C" {
#define BE_ATTR_ORIG_BE_NAME "orig_be_name"
#define BE_ATTR_ORIG_BE_POOL "orig_be_pool"
+#define BE_ATTR_ORIG_BE_ROOT "orig_be_root"
#define BE_ATTR_SNAP_NAME "snap_name"
#define BE_ATTR_NEW_BE_NAME "new_be_name"
@@ -59,6 +60,7 @@ extern "C" {
#define BE_ATTR_MOUNT_FLAGS "mount_flags"
#define BE_ATTR_UNMOUNT_FLAGS "unmount_flags"
#define BE_ATTR_DESTROY_FLAGS "destroy_flags"
+#define BE_ATTR_INSTALL_FLAGS "install_flags"
#define BE_ATTR_ROOT_DS "root_ds"
#define BE_ATTR_UUID_STR "uuid_str"
@@ -205,6 +207,12 @@ typedef struct be_node_list {
#define BE_DESTROY_FLAG_SNAPSHOTS 0x00000001
#define BE_DESTROY_FLAG_FORCE_UNMOUNT 0x00000002
+/* Flags for installboot */
+#define BE_INSTALLBOOT_FLAG_NULL 0x00000000
+#define BE_INSTALLBOOT_FLAG_MBR 0x00000001
+#define BE_INSTALLBOOT_FLAG_FORCE 0x00000002
+#define BE_INSTALLBOOT_FLAG_VERBOSE 0x00000004
+
/* sort rules for be_sort() */
typedef enum {
BE_SORT_UNSPECIFIED = -1,
@@ -244,6 +252,11 @@ char *be_err_to_str(int);
int be_sort(be_node_list_t **, int);
/*
+ * Installboot support
+ */
+int be_installboot(nvlist_t *);
+
+/*
* Library functions
*/
void libbe_print_errors(boolean_t);
diff --git a/usr/src/lib/libbe/common/mapfile-vers b/usr/src/lib/libbe/common/mapfile-vers
index 0e57583dab..0602bd7de3 100644
--- a/usr/src/lib/libbe/common/mapfile-vers
+++ b/usr/src/lib/libbe/common/mapfile-vers
@@ -49,6 +49,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
be_err_to_str;
be_free_list;
be_init;
+ be_installboot;
be_list;
be_mount;
be_rename;