1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 28 * Copyright 2016 Toomas Soome <tsoome@me.com> 29 */ 30 31 #include <assert.h> 32 #include <libintl.h> 33 #include <libnvpair.h> 34 #include <libzfs.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <strings.h> 39 #include <errno.h> 40 #include <sys/mnttab.h> 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 #include <fcntl.h> 44 #include <unistd.h> 45 #include <sys/efi_partition.h> 46 47 #include <libbe.h> 48 #include <libbe_priv.h> 49 50 char *mnttab = MNTTAB; 51 52 /* 53 * Private function prototypes 54 */ 55 static int set_bootfs(char *boot_rpool, char *be_root_ds); 56 static int set_canmount(be_node_list_t *, char *); 57 static boolean_t be_do_install_mbr(char *, nvlist_t *); 58 static int be_do_installboot_helper(zpool_handle_t *, nvlist_t *, char *, 59 char *, uint16_t); 60 static int be_do_installboot(be_transaction_data_t *, uint16_t); 61 static int be_get_grub_vers(be_transaction_data_t *, char **, char **); 62 static int get_ver_from_capfile(char *, char **); 63 static int be_promote_zone_ds(char *, char *); 64 static int be_promote_ds_callback(zfs_handle_t *, void *); 65 66 /* ******************************************************************** */ 67 /* Public Functions */ 68 /* ******************************************************************** */ 69 70 /* 71 * Function: be_activate 72 * Description: Calls _be_activate which activates the BE named in the 73 * attributes passed in through be_attrs. The process of 74 * activation sets the bootfs property of the root pool, resets 75 * the canmount property to noauto, and sets the default in the 76 * grub menu to the entry corresponding to the entry for the named 77 * BE. 78 * Parameters: 79 * be_attrs - pointer to nvlist_t of attributes being passed in. 80 * The follow attribute values are used by this function: 81 * 82 * BE_ATTR_ORIG_BE_NAME *required 83 * Return: 84 * BE_SUCCESS - Success 85 * be_errno_t - Failure 86 * Scope: 87 * Public 88 */ 89 int 90 be_activate(nvlist_t *be_attrs) 91 { 92 int ret = BE_SUCCESS; 93 char *be_name = NULL; 94 95 /* Initialize libzfs handle */ 96 if (!be_zfs_init()) 97 return (BE_ERR_INIT); 98 99 /* Get the BE name to activate */ 100 if (nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, &be_name) 101 != 0) { 102 be_print_err(gettext("be_activate: failed to " 103 "lookup BE_ATTR_ORIG_BE_NAME attribute\n")); 104 be_zfs_fini(); 105 return (BE_ERR_INVAL); 106 } 107 108 /* Validate BE name */ 109 if (!be_valid_be_name(be_name)) { 110 be_print_err(gettext("be_activate: invalid BE name %s\n"), 111 be_name); 112 be_zfs_fini(); 113 return (BE_ERR_INVAL); 114 } 115 116 ret = _be_activate(be_name); 117 118 be_zfs_fini(); 119 120 return (ret); 121 } 122 123 /* 124 * Function: be_installboot 125 * Description: Calls be_do_installboot to install/update bootloader on 126 * pool passed in through be_attrs. The primary consumer is 127 * bootadm command to avoid duplication of the code. 128 * Parameters: 129 * be_attrs - pointer to nvlist_t of attributes being passed in. 130 * The following attribute values are used: 131 * 132 * BE_ATTR_ORIG_BE_NAME *required 133 * BE_ATTR_ORIG_BE_POOL *required 134 * BE_ATTR_ORIG_BE_ROOT *required 135 * BE_ATTR_INSTALL_FLAGS optional 136 * 137 * Return: 138 * BE_SUCCESS - Success 139 * be_errno_t - Failure 140 * Scope: 141 * Public 142 */ 143 int 144 be_installboot(nvlist_t *be_attrs) 145 { 146 int ret = BE_SUCCESS; 147 uint16_t flags = 0; 148 uint16_t verbose; 149 be_transaction_data_t bt = { 0 }; 150 151 /* Get flags */ 152 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 153 BE_ATTR_INSTALL_FLAGS, DATA_TYPE_UINT16, &flags, NULL) != 0) { 154 be_print_err(gettext("be_installboot: failed to lookup " 155 "BE_ATTR_INSTALL_FLAGS attribute\n")); 156 return (BE_ERR_INVAL); 157 } 158 159 /* Set verbose early, so we get all messages */ 160 verbose = flags & BE_INSTALLBOOT_FLAG_VERBOSE; 161 if (verbose == BE_INSTALLBOOT_FLAG_VERBOSE) 162 libbe_print_errors(B_TRUE); 163 164 ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, 165 &bt.obe_name); 166 if (ret != 0) { 167 be_print_err(gettext("be_installboot: failed to " 168 "lookup BE_ATTR_ORIG_BE_NAME attribute\n")); 169 return (BE_ERR_INVAL); 170 } 171 172 ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_POOL, 173 &bt.obe_zpool); 174 if (ret != 0) { 175 be_print_err(gettext("be_installboot: failed to " 176 "lookup BE_ATTR_ORIG_BE_POOL attribute\n")); 177 return (BE_ERR_INVAL); 178 } 179 180 ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_ROOT, 181 &bt.obe_root_ds); 182 if (ret != 0) { 183 be_print_err(gettext("be_installboot: failed to " 184 "lookup BE_ATTR_ORIG_BE_ROOT attribute\n")); 185 return (BE_ERR_INVAL); 186 } 187 188 /* Initialize libzfs handle */ 189 if (!be_zfs_init()) 190 return (BE_ERR_INIT); 191 192 ret = be_do_installboot(&bt, flags); 193 194 be_zfs_fini(); 195 196 return (ret); 197 } 198 199 /* ******************************************************************** */ 200 /* Semi Private Functions */ 201 /* ******************************************************************** */ 202 203 /* 204 * Function: _be_activate 205 * Description: This does the actual work described in be_activate. 206 * Parameters: 207 * be_name - pointer to the name of BE to activate. 208 * 209 * Return: 210 * BE_SUCCESS - Success 211 * be_errnot_t - Failure 212 * Scope: 213 * Public 214 */ 215 int 216 _be_activate(char *be_name) 217 { 218 be_transaction_data_t cb = { 0 }; 219 zfs_handle_t *zhp = NULL; 220 char root_ds[MAXPATHLEN]; 221 char active_ds[MAXPATHLEN]; 222 be_node_list_t *be_nodes = NULL; 223 uuid_t uu = {0}; 224 int entry, ret = BE_SUCCESS; 225 int zret = 0; 226 227 /* 228 * TODO: The BE needs to be validated to make sure that it is actually 229 * a bootable BE. 230 */ 231 232 if (be_name == NULL) 233 return (BE_ERR_INVAL); 234 235 /* Set obe_name to be_name in the cb structure */ 236 cb.obe_name = be_name; 237 238 /* find which zpool the be is in */ 239 if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &cb)) == 0) { 240 be_print_err(gettext("be_activate: failed to " 241 "find zpool for BE (%s)\n"), cb.obe_name); 242 return (BE_ERR_BE_NOENT); 243 } else if (zret < 0) { 244 be_print_err(gettext("be_activate: " 245 "zpool_iter failed: %s\n"), 246 libzfs_error_description(g_zfs)); 247 ret = zfs_err_to_be_err(g_zfs); 248 return (ret); 249 } 250 251 be_make_root_ds(cb.obe_zpool, cb.obe_name, root_ds, sizeof (root_ds)); 252 cb.obe_root_ds = strdup(root_ds); 253 254 if (getzoneid() == GLOBAL_ZONEID) { 255 ret = be_do_installboot(&cb, BE_INSTALLBOOT_FLAG_NULL); 256 if (ret != BE_SUCCESS) 257 return (ret); 258 259 if (!be_has_menu_entry(root_ds, cb.obe_zpool, &entry)) { 260 if ((ret = be_append_menu(cb.obe_name, cb.obe_zpool, 261 NULL, NULL, NULL)) != BE_SUCCESS) { 262 be_print_err(gettext("be_activate: Failed to " 263 "add BE (%s) to the menu\n"), 264 cb.obe_name); 265 goto done; 266 } 267 } 268 if (be_has_grub()) { 269 if ((ret = be_change_grub_default(cb.obe_name, 270 cb.obe_zpool)) != BE_SUCCESS) { 271 be_print_err(gettext("be_activate: failed to " 272 "change the default entry in menu.lst\n")); 273 goto done; 274 } 275 } 276 } 277 278 if ((ret = _be_list(cb.obe_name, &be_nodes)) != BE_SUCCESS) { 279 return (ret); 280 } 281 282 if ((ret = set_canmount(be_nodes, "noauto")) != BE_SUCCESS) { 283 be_print_err(gettext("be_activate: failed to set " 284 "canmount dataset property\n")); 285 goto done; 286 } 287 288 if (getzoneid() == GLOBAL_ZONEID) { 289 if ((ret = set_bootfs(be_nodes->be_rpool, 290 root_ds)) != BE_SUCCESS) { 291 be_print_err(gettext("be_activate: failed to set " 292 "bootfs pool property for %s\n"), root_ds); 293 goto done; 294 } 295 } 296 297 if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) != NULL) { 298 /* 299 * We don't need to close the zfs handle at this 300 * point because The callback funtion 301 * be_promote_ds_callback() will close it for us. 302 */ 303 if (be_promote_ds_callback(zhp, NULL) != 0) { 304 be_print_err(gettext("be_activate: " 305 "failed to activate the " 306 "datasets for %s: %s\n"), 307 root_ds, 308 libzfs_error_description(g_zfs)); 309 ret = BE_ERR_PROMOTE; 310 goto done; 311 } 312 } else { 313 be_print_err(gettext("be_activate: failed to open " 314 "dataset (%s): %s\n"), root_ds, 315 libzfs_error_description(g_zfs)); 316 ret = zfs_err_to_be_err(g_zfs); 317 goto done; 318 } 319 320 if (getzoneid() == GLOBAL_ZONEID && 321 be_get_uuid(cb.obe_root_ds, &uu) == BE_SUCCESS && 322 (ret = be_promote_zone_ds(cb.obe_name, cb.obe_root_ds)) 323 != BE_SUCCESS) { 324 be_print_err(gettext("be_activate: failed to promote " 325 "the active zonepath datasets for zones in BE %s\n"), 326 cb.obe_name); 327 } 328 329 if (getzoneid() != GLOBAL_ZONEID) { 330 if (!be_zone_compare_uuids(root_ds)) { 331 be_print_err(gettext("be_activate: activating zone " 332 "root dataset from non-active global BE is not " 333 "supported\n")); 334 ret = BE_ERR_NOTSUP; 335 goto done; 336 } 337 if ((zhp = zfs_open(g_zfs, root_ds, 338 ZFS_TYPE_FILESYSTEM)) == NULL) { 339 be_print_err(gettext("be_activate: failed to open " 340 "dataset (%s): %s\n"), root_ds, 341 libzfs_error_description(g_zfs)); 342 ret = zfs_err_to_be_err(g_zfs); 343 goto done; 344 } 345 /* Find current active zone root dataset */ 346 if ((ret = be_find_active_zone_root(zhp, cb.obe_zpool, 347 active_ds, sizeof (active_ds))) != BE_SUCCESS) { 348 be_print_err(gettext("be_activate: failed to find " 349 "active zone root dataset\n")); 350 ZFS_CLOSE(zhp); 351 goto done; 352 } 353 /* Do nothing if requested BE is already active */ 354 if (strcmp(root_ds, active_ds) == 0) { 355 ret = BE_SUCCESS; 356 ZFS_CLOSE(zhp); 357 goto done; 358 } 359 360 /* Set active property for BE */ 361 if (zfs_prop_set(zhp, BE_ZONE_ACTIVE_PROPERTY, "on") != 0) { 362 be_print_err(gettext("be_activate: failed to set " 363 "active property (%s): %s\n"), root_ds, 364 libzfs_error_description(g_zfs)); 365 ret = zfs_err_to_be_err(g_zfs); 366 ZFS_CLOSE(zhp); 367 goto done; 368 } 369 ZFS_CLOSE(zhp); 370 371 /* Unset active property for old active root dataset */ 372 if ((zhp = zfs_open(g_zfs, active_ds, 373 ZFS_TYPE_FILESYSTEM)) == NULL) { 374 be_print_err(gettext("be_activate: failed to open " 375 "dataset (%s): %s\n"), active_ds, 376 libzfs_error_description(g_zfs)); 377 ret = zfs_err_to_be_err(g_zfs); 378 goto done; 379 } 380 if (zfs_prop_set(zhp, BE_ZONE_ACTIVE_PROPERTY, "off") != 0) { 381 be_print_err(gettext("be_activate: failed to unset " 382 "active property (%s): %s\n"), active_ds, 383 libzfs_error_description(g_zfs)); 384 ret = zfs_err_to_be_err(g_zfs); 385 ZFS_CLOSE(zhp); 386 goto done; 387 } 388 ZFS_CLOSE(zhp); 389 } 390 done: 391 be_free_list(be_nodes); 392 return (ret); 393 } 394 395 /* 396 * Function: be_activate_current_be 397 * Description: Set the currently "active" BE to be "active on boot" 398 * Paramters: 399 * none 400 * Returns: 401 * BE_SUCCESS - Success 402 * be_errnot_t - Failure 403 * Scope: 404 * Semi-private (library wide use only) 405 */ 406 int 407 be_activate_current_be(void) 408 { 409 int ret = BE_SUCCESS; 410 be_transaction_data_t bt = { 0 }; 411 412 if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) { 413 return (ret); 414 } 415 416 if ((ret = _be_activate(bt.obe_name)) != BE_SUCCESS) { 417 be_print_err(gettext("be_activate_current_be: failed to " 418 "activate %s\n"), bt.obe_name); 419 return (ret); 420 } 421 422 return (BE_SUCCESS); 423 } 424 425 /* 426 * Function: be_is_active_on_boot 427 * Description: Checks if the BE name passed in has the "active on boot" 428 * property set to B_TRUE. 429 * Paramters: 430 * be_name - the name of the BE to check 431 * Returns: 432 * B_TRUE - if active on boot. 433 * B_FALSE - if not active on boot. 434 * Scope: 435 * Semi-private (library wide use only) 436 */ 437 boolean_t 438 be_is_active_on_boot(char *be_name) 439 { 440 be_node_list_t *be_node = NULL; 441 442 if (be_name == NULL) { 443 be_print_err(gettext("be_is_active_on_boot: " 444 "be_name must not be NULL\n")); 445 return (B_FALSE); 446 } 447 448 if (_be_list(be_name, &be_node) != BE_SUCCESS) { 449 return (B_FALSE); 450 } 451 452 if (be_node == NULL) { 453 return (B_FALSE); 454 } 455 456 if (be_node->be_active_on_boot) { 457 be_free_list(be_node); 458 return (B_TRUE); 459 } else { 460 be_free_list(be_node); 461 return (B_FALSE); 462 } 463 } 464 465 /* ******************************************************************** */ 466 /* Private Functions */ 467 /* ******************************************************************** */ 468 469 /* 470 * Function: set_bootfs 471 * Description: Sets the bootfs property on the boot pool to be the 472 * root dataset of the activated BE. 473 * Parameters: 474 * boot_pool - The pool we're setting bootfs in. 475 * be_root_ds - The main dataset for the BE. 476 * Return: 477 * BE_SUCCESS - Success 478 * be_errno_t - Failure 479 * Scope: 480 * Private 481 */ 482 static int 483 set_bootfs(char *boot_rpool, char *be_root_ds) 484 { 485 zpool_handle_t *zhp; 486 int err = BE_SUCCESS; 487 488 if ((zhp = zpool_open(g_zfs, boot_rpool)) == NULL) { 489 be_print_err(gettext("set_bootfs: failed to open pool " 490 "(%s): %s\n"), boot_rpool, libzfs_error_description(g_zfs)); 491 err = zfs_err_to_be_err(g_zfs); 492 return (err); 493 } 494 495 err = zpool_set_prop(zhp, "bootfs", be_root_ds); 496 if (err) { 497 be_print_err(gettext("set_bootfs: failed to set " 498 "bootfs property for pool %s: %s\n"), boot_rpool, 499 libzfs_error_description(g_zfs)); 500 err = zfs_err_to_be_err(g_zfs); 501 zpool_close(zhp); 502 return (err); 503 } 504 505 zpool_close(zhp); 506 return (BE_SUCCESS); 507 } 508 509 /* 510 * Function: set_canmount 511 * Description: Sets the canmount property on the datasets of the 512 * activated BE. 513 * Parameters: 514 * be_nodes - The be_node_t returned from be_list 515 * value - The value of canmount we setting, on|off|noauto. 516 * Return: 517 * BE_SUCCESS - Success 518 * be_errno_t - Failure 519 * Scope: 520 * Private 521 */ 522 static int 523 set_canmount(be_node_list_t *be_nodes, char *value) 524 { 525 char ds_path[MAXPATHLEN]; 526 zfs_handle_t *zhp = NULL; 527 be_node_list_t *list = be_nodes; 528 int err = BE_SUCCESS; 529 530 while (list != NULL) { 531 be_dataset_list_t *datasets = list->be_node_datasets; 532 533 be_make_root_ds(list->be_rpool, list->be_node_name, ds_path, 534 sizeof (ds_path)); 535 536 if ((zhp = zfs_open(g_zfs, ds_path, ZFS_TYPE_DATASET)) == 537 NULL) { 538 be_print_err(gettext("set_canmount: failed to open " 539 "dataset (%s): %s\n"), ds_path, 540 libzfs_error_description(g_zfs)); 541 err = zfs_err_to_be_err(g_zfs); 542 return (err); 543 } 544 if (zfs_prop_get_int(zhp, ZFS_PROP_MOUNTED)) { 545 /* 546 * it's already mounted so we can't change the 547 * canmount property anyway. 548 */ 549 err = BE_SUCCESS; 550 } else { 551 err = zfs_prop_set(zhp, 552 zfs_prop_to_name(ZFS_PROP_CANMOUNT), value); 553 if (err) { 554 ZFS_CLOSE(zhp); 555 be_print_err(gettext("set_canmount: failed to " 556 "set dataset property (%s): %s\n"), 557 ds_path, libzfs_error_description(g_zfs)); 558 err = zfs_err_to_be_err(g_zfs); 559 return (err); 560 } 561 } 562 ZFS_CLOSE(zhp); 563 564 while (datasets != NULL) { 565 be_make_root_ds(list->be_rpool, 566 datasets->be_dataset_name, ds_path, 567 sizeof (ds_path)); 568 569 if ((zhp = zfs_open(g_zfs, ds_path, ZFS_TYPE_DATASET)) 570 == NULL) { 571 be_print_err(gettext("set_canmount: failed to " 572 "open dataset %s: %s\n"), ds_path, 573 libzfs_error_description(g_zfs)); 574 err = zfs_err_to_be_err(g_zfs); 575 return (err); 576 } 577 if (zfs_prop_get_int(zhp, ZFS_PROP_MOUNTED)) { 578 /* 579 * it's already mounted so we can't change the 580 * canmount property anyway. 581 */ 582 err = BE_SUCCESS; 583 ZFS_CLOSE(zhp); 584 break; 585 } 586 err = zfs_prop_set(zhp, 587 zfs_prop_to_name(ZFS_PROP_CANMOUNT), value); 588 if (err) { 589 ZFS_CLOSE(zhp); 590 be_print_err(gettext("set_canmount: " 591 "Failed to set property value %s " 592 "for dataset %s: %s\n"), value, ds_path, 593 libzfs_error_description(g_zfs)); 594 err = zfs_err_to_be_err(g_zfs); 595 return (err); 596 } 597 ZFS_CLOSE(zhp); 598 datasets = datasets->be_next_dataset; 599 } 600 list = list->be_next_node; 601 } 602 return (err); 603 } 604 605 /* 606 * Function: be_get_grub_vers 607 * Description: Gets the grub version number from /boot/grub/capability. If 608 * capability file doesn't exist NULL is returned. 609 * Parameters: 610 * bt - The transaction data for the BE we're getting the grub 611 * version for. 612 * cur_vers - used to return the current version of grub from 613 * the root pool. 614 * new_vers - used to return the grub version of the BE we're 615 * activating. 616 * Return: 617 * BE_SUCCESS - Success 618 * be_errno_t - Failed to find version 619 * Scope: 620 * Private 621 */ 622 static int 623 be_get_grub_vers(be_transaction_data_t *bt, char **cur_vers, char **new_vers) 624 { 625 zfs_handle_t *zhp = NULL; 626 zfs_handle_t *pool_zhp = NULL; 627 int ret = BE_SUCCESS; 628 char cap_file[MAXPATHLEN]; 629 char *temp_mntpnt = NULL; 630 char *zpool_mntpt = NULL; 631 char *ptmp_mntpnt = NULL; 632 char *orig_mntpnt = NULL; 633 boolean_t be_mounted = B_FALSE; 634 boolean_t pool_mounted = B_FALSE; 635 636 if (!be_has_grub()) { 637 be_print_err(gettext("be_get_grub_vers: Not supported on " 638 "this architecture\n")); 639 return (BE_ERR_NOTSUP); 640 } 641 642 if (bt == NULL || bt->obe_name == NULL || bt->obe_zpool == NULL || 643 bt->obe_root_ds == NULL) { 644 be_print_err(gettext("be_get_grub_vers: Invalid BE\n")); 645 return (BE_ERR_INVAL); 646 } 647 648 if ((pool_zhp = zfs_open(g_zfs, bt->obe_zpool, ZFS_TYPE_FILESYSTEM)) == 649 NULL) { 650 be_print_err(gettext("be_get_grub_vers: zfs_open failed: %s\n"), 651 libzfs_error_description(g_zfs)); 652 return (zfs_err_to_be_err(g_zfs)); 653 } 654 655 /* 656 * Check to see if the pool's dataset is mounted. If it isn't we'll 657 * attempt to mount it. 658 */ 659 if ((ret = be_mount_pool(pool_zhp, &ptmp_mntpnt, 660 &orig_mntpnt, &pool_mounted)) != BE_SUCCESS) { 661 be_print_err(gettext("be_get_grub_vers: pool dataset " 662 "(%s) could not be mounted\n"), bt->obe_zpool); 663 ZFS_CLOSE(pool_zhp); 664 return (ret); 665 } 666 667 /* 668 * Get the mountpoint for the root pool dataset. 669 */ 670 if (!zfs_is_mounted(pool_zhp, &zpool_mntpt)) { 671 be_print_err(gettext("be_get_grub_vers: pool " 672 "dataset (%s) is not mounted. Can't read the " 673 "grub capability file.\n"), bt->obe_zpool); 674 ret = BE_ERR_NO_MENU; 675 goto cleanup; 676 } 677 678 /* 679 * get the version of the most recent grub update. 680 */ 681 (void) snprintf(cap_file, sizeof (cap_file), "%s%s", 682 zpool_mntpt, BE_CAP_FILE); 683 free(zpool_mntpt); 684 zpool_mntpt = NULL; 685 686 if ((ret = get_ver_from_capfile(cap_file, cur_vers)) != BE_SUCCESS) 687 goto cleanup; 688 689 if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) == 690 NULL) { 691 be_print_err(gettext("be_get_grub_vers: failed to " 692 "open BE root dataset (%s): %s\n"), bt->obe_root_ds, 693 libzfs_error_description(g_zfs)); 694 free(cur_vers); 695 ret = zfs_err_to_be_err(g_zfs); 696 goto cleanup; 697 } 698 if (!zfs_is_mounted(zhp, &temp_mntpnt)) { 699 if ((ret = _be_mount(bt->obe_name, &temp_mntpnt, 700 BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) { 701 be_print_err(gettext("be_get_grub_vers: failed to " 702 "mount BE (%s)\n"), bt->obe_name); 703 free(*cur_vers); 704 *cur_vers = NULL; 705 ZFS_CLOSE(zhp); 706 goto cleanup; 707 } 708 be_mounted = B_TRUE; 709 } 710 ZFS_CLOSE(zhp); 711 712 /* 713 * Now get the grub version for the BE being activated. 714 */ 715 (void) snprintf(cap_file, sizeof (cap_file), "%s%s", temp_mntpnt, 716 BE_CAP_FILE); 717 ret = get_ver_from_capfile(cap_file, new_vers); 718 if (ret != BE_SUCCESS) { 719 free(*cur_vers); 720 *cur_vers = NULL; 721 } 722 if (be_mounted) 723 (void) _be_unmount(bt->obe_name, 0); 724 725 cleanup: 726 if (pool_mounted) { 727 int iret = BE_SUCCESS; 728 iret = be_unmount_pool(pool_zhp, ptmp_mntpnt, orig_mntpnt); 729 if (ret == BE_SUCCESS) 730 ret = iret; 731 free(orig_mntpnt); 732 free(ptmp_mntpnt); 733 } 734 ZFS_CLOSE(pool_zhp); 735 736 free(temp_mntpnt); 737 return (ret); 738 } 739 740 /* 741 * Function: get_ver_from_capfile 742 * Description: Parses the capability file passed in looking for the VERSION 743 * line. If found the version is returned in vers, if not then 744 * NULL is returned in vers. 745 * 746 * Parameters: 747 * file - the path to the capability file we want to parse. 748 * vers - the version string that will be passed back. 749 * Return: 750 * BE_SUCCESS - Success 751 * be_errno_t - Failed to find version 752 * Scope: 753 * Private 754 */ 755 static int 756 get_ver_from_capfile(char *file, char **vers) 757 { 758 FILE *fp = NULL; 759 char line[BUFSIZ]; 760 char *last = NULL; 761 int err = BE_SUCCESS; 762 errno = 0; 763 764 if (!be_has_grub()) { 765 be_print_err(gettext("get_ver_from_capfile: Not supported " 766 "on this architecture\n")); 767 return (BE_ERR_NOTSUP); 768 } 769 770 /* 771 * Set version string to NULL; the only case this shouldn't be set 772 * to be NULL is when we've actually found a version in the capability 773 * file, which is set below. 774 */ 775 *vers = NULL; 776 777 /* 778 * If the capability file doesn't exist, we're returning success 779 * because on older releases, the capability file did not exist 780 * so this is a valid scenario. 781 */ 782 if (access(file, F_OK) == 0) { 783 if ((fp = fopen(file, "r")) == NULL) { 784 err = errno; 785 be_print_err(gettext("get_ver_from_capfile: failed to " 786 "open file %s with error %s\n"), file, 787 strerror(err)); 788 err = errno_to_be_err(err); 789 return (err); 790 } 791 792 while (fgets(line, BUFSIZ, fp)) { 793 char *tok = strtok_r(line, "=", &last); 794 795 if (tok == NULL || tok[0] == '#') { 796 continue; 797 } else if (strcmp(tok, "VERSION") == 0) { 798 *vers = strdup(last); 799 break; 800 } 801 } 802 (void) fclose(fp); 803 } 804 805 return (BE_SUCCESS); 806 } 807 808 /* 809 * To be able to boot EFI labeled disks, stage1 needs to be written 810 * into the MBR. We do not do this if we're on disks with a traditional 811 * fdisk partition table only, or if any foreign EFI partitions exist. 812 * In the trivial case of a whole-disk vdev we always write stage1 into 813 * the MBR. 814 */ 815 static boolean_t 816 be_do_install_mbr(char *diskname, nvlist_t *child) 817 { 818 struct uuid allowed_uuids[] = { 819 EFI_UNUSED, 820 EFI_RESV1, 821 EFI_BOOT, 822 EFI_ROOT, 823 EFI_SWAP, 824 EFI_USR, 825 EFI_BACKUP, 826 EFI_RESV2, 827 EFI_VAR, 828 EFI_HOME, 829 EFI_ALTSCTR, 830 EFI_RESERVED, 831 EFI_SYSTEM, 832 EFI_BIOS_BOOT, 833 EFI_SYMC_PUB, 834 EFI_SYMC_CDS 835 }; 836 837 uint64_t whole; 838 struct dk_gpt *gpt; 839 struct uuid *u; 840 int fd, npart, i, j; 841 842 (void) nvlist_lookup_uint64(child, ZPOOL_CONFIG_WHOLE_DISK, 843 &whole); 844 845 if (whole) 846 return (B_TRUE); 847 848 if ((fd = open(diskname, O_RDONLY|O_NDELAY)) < 0) 849 return (B_FALSE); 850 851 if ((npart = efi_alloc_and_read(fd, &gpt)) <= 0) 852 return (B_FALSE); 853 854 for (i = 0; i != npart; i++) { 855 int match = 0; 856 857 u = &gpt->efi_parts[i].p_guid; 858 859 for (j = 0; 860 j != sizeof (allowed_uuids) / sizeof (struct uuid); 861 j++) 862 if (bcmp(u, &allowed_uuids[j], 863 sizeof (struct uuid)) == 0) 864 match++; 865 866 if (match == 0) 867 return (B_FALSE); 868 } 869 870 return (B_TRUE); 871 } 872 873 static int 874 be_do_installboot_helper(zpool_handle_t *zphp, nvlist_t *child, char *stage1, 875 char *stage2, uint16_t flags) 876 { 877 char install_cmd[MAXPATHLEN]; 878 char be_run_cmd_errbuf[BUFSIZ]; 879 char be_run_cmd_outbuf[BUFSIZ]; 880 char diskname[MAXPATHLEN]; 881 char *vname; 882 char *path, *dsk_ptr; 883 char *flag = ""; 884 int ret; 885 vdev_stat_t *vs; 886 uint_t vsc; 887 888 if (nvlist_lookup_string(child, ZPOOL_CONFIG_PATH, &path) != 0) { 889 be_print_err(gettext("be_do_installboot: " 890 "failed to get device path\n")); 891 return (BE_ERR_NODEV); 892 } 893 894 if ((nvlist_lookup_uint64_array(child, ZPOOL_CONFIG_VDEV_STATS, 895 (uint64_t **)&vs, &vsc) != 0) || 896 vs->vs_state < VDEV_STATE_DEGRADED) { 897 /* 898 * Don't try to run installgrub on a vdev that is not ONLINE 899 * or DEGRADED. Try to print a warning for each such vdev. 900 */ 901 be_print_err(gettext("be_do_installboot: " 902 "vdev %s is %s, can't install boot loader\n"), 903 path, zpool_state_to_name(vs->vs_state, vs->vs_aux)); 904 return (BE_SUCCESS); 905 } 906 907 /* 908 * Modify the vdev path to point to the raw disk. 909 */ 910 path = strdup(path); 911 if (path == NULL) 912 return (BE_ERR_NOMEM); 913 914 dsk_ptr = strstr(path, "/dsk/"); 915 if (dsk_ptr != NULL) { 916 *dsk_ptr = '\0'; 917 dsk_ptr++; 918 } else { 919 dsk_ptr = ""; 920 } 921 922 (void) snprintf(diskname, sizeof (diskname), "%s/r%s", path, dsk_ptr); 923 free(path); 924 925 vname = zpool_vdev_name(g_zfs, zphp, child, B_FALSE); 926 if (vname == NULL) { 927 be_print_err(gettext("be_do_installboot: " 928 "failed to get device name: %s\n"), 929 libzfs_error_description(g_zfs)); 930 return (zfs_err_to_be_err(g_zfs)); 931 } 932 933 if (be_is_isa("i386")) { 934 uint16_t force = flags & BE_INSTALLBOOT_FLAG_FORCE; 935 uint16_t mbr = flags & BE_INSTALLBOOT_FLAG_MBR; 936 937 if (force == BE_INSTALLBOOT_FLAG_FORCE) { 938 if (mbr == BE_INSTALLBOOT_FLAG_MBR || 939 be_do_install_mbr(diskname, child)) 940 flag = "-F -m -f"; 941 else 942 flag = "-F"; 943 } else { 944 if (mbr == BE_INSTALLBOOT_FLAG_MBR || 945 be_do_install_mbr(diskname, child)) 946 flag = "-m -f"; 947 } 948 949 if (be_has_grub()) { 950 (void) snprintf(install_cmd, sizeof (install_cmd), 951 "%s %s %s %s %s", BE_INSTALL_GRUB, flag, 952 stage1, stage2, diskname); 953 } else { 954 (void) snprintf(install_cmd, sizeof (install_cmd), 955 "%s %s %s %s %s", BE_INSTALL_BOOT, flag, 956 stage1, stage2, diskname); 957 } 958 } else if (be_is_isa("sparc")) { 959 if ((flags & BE_INSTALLBOOT_FLAG_FORCE) == 960 BE_INSTALLBOOT_FLAG_FORCE) 961 flag = "-f -F zfs"; 962 else 963 flag = "-F zfs"; 964 965 (void) snprintf(install_cmd, sizeof (install_cmd), 966 "%s %s %s %s", BE_INSTALL_BOOT, flag, stage2, diskname); 967 } else { 968 be_print_err(gettext("be_do_installboot: unsupported " 969 "architecture.\n")); 970 return (BE_ERR_BOOTFILE_INST); 971 } 972 973 *be_run_cmd_outbuf = '\0'; 974 *be_run_cmd_errbuf = '\0'; 975 976 ret = be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ, 977 be_run_cmd_outbuf, BUFSIZ); 978 979 if (ret != BE_SUCCESS) { 980 be_print_err(gettext("be_do_installboot: install " 981 "failed for device %s.\n"), vname); 982 ret = BE_ERR_BOOTFILE_INST; 983 } 984 985 be_print_err(gettext(" Command: \"%s\"\n"), install_cmd); 986 if (be_run_cmd_outbuf[0] != 0) { 987 be_print_err(gettext(" Output:\n")); 988 be_print_err("%s", be_run_cmd_outbuf); 989 } 990 991 if (be_run_cmd_errbuf[0] != 0) { 992 be_print_err(gettext(" Errors:\n")); 993 be_print_err("%s", be_run_cmd_errbuf); 994 } 995 free(vname); 996 997 return (ret); 998 } 999 1000 /* 1001 * Function: be_do_copy_grub_cap 1002 * Description: This function will copy grub capability file to BE. 1003 * 1004 * Parameters: 1005 * bt - The transaction data for the BE we're activating. 1006 * Return: 1007 * BE_SUCCESS - Success 1008 * be_errno_t - Failure 1009 * 1010 * Scope: 1011 * Private 1012 */ 1013 static int 1014 be_do_copy_grub_cap(be_transaction_data_t *bt) 1015 { 1016 zfs_handle_t *zhp = NULL; 1017 char cap_file[MAXPATHLEN]; 1018 char zpool_cap_file[MAXPATHLEN]; 1019 char line[BUFSIZ]; 1020 char *tmp_mntpnt = NULL; 1021 char *orig_mntpnt = NULL; 1022 char *pool_mntpnt = NULL; 1023 FILE *cap_fp = NULL; 1024 FILE *zpool_cap_fp = NULL; 1025 int err = 0; 1026 int ret = BE_SUCCESS; 1027 boolean_t pool_mounted = B_FALSE; 1028 boolean_t be_mounted = B_FALSE; 1029 1030 /* 1031 * first get BE dataset mountpoint, we can free all the resources 1032 * once cap_file is built, leaving only be unmount to be done. 1033 */ 1034 if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) == 1035 NULL) { 1036 be_print_err(gettext("be_do_copy_grub_cap: failed to " 1037 "open BE root dataset (%s): %s\n"), bt->obe_root_ds, 1038 libzfs_error_description(g_zfs)); 1039 return (zfs_err_to_be_err(g_zfs)); 1040 } 1041 1042 if (!zfs_is_mounted(zhp, &tmp_mntpnt)) { 1043 if ((ret = _be_mount(bt->obe_name, &tmp_mntpnt, 1044 BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) { 1045 be_print_err(gettext("be_do_copy_grub_cap: failed to " 1046 "mount BE (%s)\n"), bt->obe_name); 1047 ZFS_CLOSE(zhp); 1048 goto done; 1049 } 1050 be_mounted = B_TRUE; 1051 } 1052 ZFS_CLOSE(zhp); /* BE dataset handle is not needed any more */ 1053 1054 (void) snprintf(cap_file, sizeof (cap_file), "%s%s", tmp_mntpnt, 1055 BE_CAP_FILE); 1056 free(tmp_mntpnt); 1057 1058 /* get pool root dataset mountpoint */ 1059 zhp = zfs_open(g_zfs, bt->obe_zpool, ZFS_TYPE_FILESYSTEM); 1060 if (zhp == NULL) { 1061 be_print_err(gettext("be_do_copy_grub_cap: zfs_open " 1062 "failed: %s\n"), libzfs_error_description(g_zfs)); 1063 ret = zfs_err_to_be_err(g_zfs); 1064 goto done; 1065 } 1066 1067 /* 1068 * Check to see if the pool's dataset is mounted. If it isn't we'll 1069 * attempt to mount it. 1070 */ 1071 if ((ret = be_mount_pool(zhp, &tmp_mntpnt, 1072 &orig_mntpnt, &pool_mounted)) != BE_SUCCESS) { 1073 be_print_err(gettext("be_do_copy_grub_cap: pool dataset " 1074 "(%s) could not be mounted\n"), bt->obe_zpool); 1075 ZFS_CLOSE(zhp); 1076 goto done; 1077 } 1078 1079 /* 1080 * Get the mountpoint for the root pool dataset. 1081 * NOTE: zhp must be kept for _be_unmount_pool() 1082 */ 1083 if (!zfs_is_mounted(zhp, &pool_mntpnt)) { 1084 be_print_err(gettext("be_do_copy_grub_cap: pool " 1085 "dataset (%s) is not mounted. Can't check the grub " 1086 "version from the grub capability file.\n"), bt->obe_zpool); 1087 ret = BE_ERR_NO_MENU; 1088 goto done; 1089 } 1090 1091 (void) snprintf(zpool_cap_file, sizeof (zpool_cap_file), "%s%s", 1092 pool_mntpnt, BE_CAP_FILE); 1093 free(pool_mntpnt); 1094 1095 if ((cap_fp = fopen(cap_file, "r")) == NULL) { 1096 err = errno; 1097 be_print_err(gettext("be_do_copy_grub_cap: failed to open grub " 1098 "capability file\n")); 1099 ret = errno_to_be_err(err); 1100 goto done; 1101 } 1102 if ((zpool_cap_fp = fopen(zpool_cap_file, "w")) == NULL) { 1103 err = errno; 1104 be_print_err(gettext("be_do_copy_grub_cap: failed to open new " 1105 "grub capability file\n")); 1106 ret = errno_to_be_err(err); 1107 (void) fclose(cap_fp); 1108 goto done; 1109 } 1110 1111 while (fgets(line, BUFSIZ, cap_fp)) { 1112 (void) fputs(line, zpool_cap_fp); 1113 } 1114 1115 (void) fclose(zpool_cap_fp); 1116 (void) fclose(cap_fp); 1117 1118 done: 1119 if (be_mounted) 1120 (void) _be_unmount(bt->obe_name, 0); 1121 1122 if (pool_mounted) { 1123 err = be_unmount_pool(zhp, tmp_mntpnt, orig_mntpnt); 1124 if (ret == BE_SUCCESS) 1125 ret = err; 1126 free(orig_mntpnt); 1127 free(tmp_mntpnt); 1128 zfs_close(zhp); 1129 } 1130 return (ret); 1131 } 1132 1133 /* 1134 * Function: be_is_install_needed 1135 * Description: Check detached version files to detect if bootloader 1136 * install/update is needed. 1137 * 1138 * Parameters: 1139 * bt - The transaction data for the BE we're activating. 1140 * update - set B_TRUE is update is needed. 1141 * Return: 1142 * BE_SUCCESS - Success 1143 * be_errno_t - Failure 1144 * 1145 * Scope: 1146 * Private 1147 */ 1148 static int 1149 be_is_install_needed(be_transaction_data_t *bt, boolean_t *update) 1150 { 1151 int ret = BE_SUCCESS; 1152 char *cur_vers = NULL, *new_vers = NULL; 1153 1154 assert(bt != NULL); 1155 assert(update != NULL); 1156 1157 if (!be_has_grub()) { 1158 /* 1159 * no detached versioning, let installboot to manage 1160 * versioning. 1161 */ 1162 *update = B_TRUE; 1163 return (ret); 1164 } 1165 1166 *update = B_FALSE; /* set default */ 1167 1168 /* 1169 * We need to check to see if the version number from 1170 * the BE being activated is greater than the current 1171 * one. 1172 */ 1173 ret = be_get_grub_vers(bt, &cur_vers, &new_vers); 1174 if (ret != BE_SUCCESS) { 1175 be_print_err(gettext("be_activate: failed to get grub " 1176 "versions from capability files.\n")); 1177 return (ret); 1178 } 1179 /* update if we have both versions and can compare */ 1180 if (cur_vers != NULL) { 1181 if (new_vers != NULL) { 1182 if (atof(cur_vers) < atof(new_vers)) 1183 *update = B_TRUE; 1184 free(new_vers); 1185 } 1186 free(cur_vers); 1187 } else if (new_vers != NULL) { 1188 /* we only got new version - update */ 1189 *update = B_TRUE; 1190 free(new_vers); 1191 } 1192 return (ret); 1193 } 1194 1195 /* 1196 * Function: be_do_installboot 1197 * Description: This function runs installgrub/installboot using the boot 1198 * loader files from the BE we're activating and installing 1199 * them on the pool the BE lives in. 1200 * 1201 * Parameters: 1202 * bt - The transaction data for the BE we're activating. 1203 * flags - flags for bootloader install 1204 * Return: 1205 * BE_SUCCESS - Success 1206 * be_errno_t - Failure 1207 * 1208 * Scope: 1209 * Private 1210 */ 1211 static int 1212 be_do_installboot(be_transaction_data_t *bt, uint16_t flags) 1213 { 1214 zpool_handle_t *zphp = NULL; 1215 zfs_handle_t *zhp = NULL; 1216 nvlist_t **child, *nv, *config; 1217 uint_t c, children = 0; 1218 char *tmp_mntpt = NULL; 1219 char stage1[MAXPATHLEN]; 1220 char stage2[MAXPATHLEN]; 1221 char *vname; 1222 int ret = BE_SUCCESS; 1223 boolean_t be_mounted = B_FALSE; 1224 boolean_t update = B_FALSE; 1225 boolean_t verbose = B_FALSE; 1226 1227 /* 1228 * check versions. This call is to support detached 1229 * version implementation like grub. Embedded versioning is 1230 * checked by actual installer. 1231 */ 1232 if ((flags & BE_INSTALLBOOT_FLAG_FORCE) != BE_INSTALLBOOT_FLAG_FORCE) { 1233 ret = be_is_install_needed(bt, &update); 1234 if (ret != BE_SUCCESS || update == B_FALSE) 1235 return (ret); 1236 } 1237 verbose = do_print; 1238 1239 if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) == 1240 NULL) { 1241 be_print_err(gettext("be_do_installboot: failed to " 1242 "open BE root dataset (%s): %s\n"), bt->obe_root_ds, 1243 libzfs_error_description(g_zfs)); 1244 ret = zfs_err_to_be_err(g_zfs); 1245 return (ret); 1246 } 1247 if (!zfs_is_mounted(zhp, &tmp_mntpt)) { 1248 if ((ret = _be_mount(bt->obe_name, &tmp_mntpt, 1249 BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) { 1250 be_print_err(gettext("be_do_installboot: failed to " 1251 "mount BE (%s)\n"), bt->obe_name); 1252 ZFS_CLOSE(zhp); 1253 return (ret); 1254 } 1255 be_mounted = B_TRUE; 1256 } 1257 ZFS_CLOSE(zhp); 1258 1259 if (be_is_isa("i386")) { 1260 if (be_has_grub()) { 1261 (void) snprintf(stage1, sizeof (stage1), "%s%s", 1262 tmp_mntpt, BE_GRUB_STAGE_1); 1263 (void) snprintf(stage2, sizeof (stage2), "%s%s", 1264 tmp_mntpt, BE_GRUB_STAGE_2); 1265 } else { 1266 (void) snprintf(stage1, sizeof (stage1), "%s%s", 1267 tmp_mntpt, BE_LOADER_STAGE_1); 1268 (void) snprintf(stage2, sizeof (stage2), "%s%s", 1269 tmp_mntpt, BE_LOADER_STAGE_2); 1270 } 1271 } else if (be_is_isa("sparc")) { 1272 char *platform = be_get_platform(); 1273 1274 if (platform == NULL) { 1275 be_print_err(gettext("be_do_installboot: " 1276 "failed to detect system platform name\n")); 1277 if (be_mounted) 1278 (void) _be_unmount(bt->obe_name, 0); 1279 free(tmp_mntpt); 1280 return (BE_ERR_BOOTFILE_INST); 1281 } 1282 stage1[0] = '\0'; /* sparc has no stage1 */ 1283 (void) snprintf(stage2, sizeof (stage2), 1284 "%s/usr/platform/%s%s", tmp_mntpt, 1285 platform, BE_SPARC_BOOTBLK); 1286 } else { 1287 be_print_err(gettext("be_do_installboot: unsupported " 1288 "architecture.\n")); 1289 return (BE_ERR_BOOTFILE_INST); 1290 } 1291 1292 if ((zphp = zpool_open(g_zfs, bt->obe_zpool)) == NULL) { 1293 be_print_err(gettext("be_do_installboot: failed to open " 1294 "pool (%s): %s\n"), bt->obe_zpool, 1295 libzfs_error_description(g_zfs)); 1296 ret = zfs_err_to_be_err(g_zfs); 1297 if (be_mounted) 1298 (void) _be_unmount(bt->obe_name, 0); 1299 free(tmp_mntpt); 1300 return (ret); 1301 } 1302 1303 if ((config = zpool_get_config(zphp, NULL)) == NULL) { 1304 be_print_err(gettext("be_do_installboot: failed to get zpool " 1305 "configuration information. %s\n"), 1306 libzfs_error_description(g_zfs)); 1307 ret = zfs_err_to_be_err(g_zfs); 1308 goto done; 1309 } 1310 1311 /* 1312 * Get the vdev tree 1313 */ 1314 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nv) != 0) { 1315 be_print_err(gettext("be_do_installboot: failed to get vdev " 1316 "tree: %s\n"), libzfs_error_description(g_zfs)); 1317 ret = zfs_err_to_be_err(g_zfs); 1318 goto done; 1319 } 1320 1321 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1322 &children) != 0) { 1323 be_print_err(gettext("be_do_installboot: failed to traverse " 1324 "the vdev tree: %s\n"), libzfs_error_description(g_zfs)); 1325 ret = zfs_err_to_be_err(g_zfs); 1326 goto done; 1327 } 1328 for (c = 0; c < children; c++) { 1329 uint_t i, nchildren = 0; 1330 nvlist_t **nvchild; 1331 1332 /* ensure update on child status */ 1333 vname = zpool_vdev_name(g_zfs, zphp, child[c], verbose); 1334 if (vname == NULL) { 1335 be_print_err(gettext( 1336 "be_do_installboot: " 1337 "failed to get device name: %s\n"), 1338 libzfs_error_description(g_zfs)); 1339 ret = zfs_err_to_be_err(g_zfs); 1340 goto done; 1341 } else if (verbose == B_TRUE) { 1342 be_print_err(gettext("be_do_installboot: " 1343 "device %s\n"), vname); 1344 } 1345 free(vname); 1346 1347 ret = nvlist_lookup_nvlist_array(child[c], 1348 ZPOOL_CONFIG_CHILDREN, &nvchild, &nchildren); 1349 if (ret != 0) { 1350 if (ret != ENOENT) { 1351 be_print_err(gettext("be_do_installboot: " 1352 "failed to traverse the vdev tree: %s\n"), 1353 libzfs_error_description(g_zfs)); 1354 ret = zfs_err_to_be_err(g_zfs); 1355 goto done; 1356 } 1357 nchildren = 0; /* This is leaf device. */ 1358 } 1359 1360 if (nchildren != 0) { 1361 for (i = 0; i < nchildren; i++) { 1362 /* ensure update on child status */ 1363 vname = zpool_vdev_name(g_zfs, zphp, 1364 nvchild[i], verbose); 1365 if (vname == NULL) { 1366 be_print_err(gettext( 1367 "be_do_installboot: " 1368 "failed to get device name: %s\n"), 1369 libzfs_error_description(g_zfs)); 1370 ret = zfs_err_to_be_err(g_zfs); 1371 goto done; 1372 } else if (verbose == B_TRUE) { 1373 be_print_err(gettext( 1374 "be_do_installboot: device %s\n"), 1375 vname); 1376 } 1377 free(vname); 1378 ret = be_do_installboot_helper(zphp, nvchild[i], 1379 stage1, stage2, flags); 1380 if (ret != BE_SUCCESS) 1381 goto done; 1382 } 1383 } else { 1384 ret = be_do_installboot_helper(zphp, child[c], stage1, 1385 stage2, flags); 1386 if (ret != BE_SUCCESS) 1387 goto done; 1388 } 1389 } 1390 1391 if (be_has_grub()) { 1392 ret = be_do_copy_grub_cap(bt); 1393 } 1394 1395 done: 1396 ZFS_CLOSE(zhp); 1397 if (be_mounted) 1398 (void) _be_unmount(bt->obe_name, 0); 1399 zpool_close(zphp); 1400 free(tmp_mntpt); 1401 return (ret); 1402 } 1403 1404 /* 1405 * Function: be_promote_zone_ds 1406 * Description: This function finds the zones for the BE being activated 1407 * and the active zonepath dataset for each zone. Then each 1408 * active zonepath dataset is promoted. 1409 * 1410 * Parameters: 1411 * be_name - the name of the global zone BE that we need to 1412 * find the zones for. 1413 * be_root_ds - the root dataset for be_name. 1414 * Return: 1415 * BE_SUCCESS - Success 1416 * be_errno_t - Failure 1417 * 1418 * Scope: 1419 * Private 1420 */ 1421 static int 1422 be_promote_zone_ds(char *be_name, char *be_root_ds) 1423 { 1424 char *zone_ds = NULL; 1425 char *temp_mntpt = NULL; 1426 char origin[MAXPATHLEN]; 1427 char zoneroot_ds[MAXPATHLEN]; 1428 zfs_handle_t *zhp = NULL; 1429 zfs_handle_t *z_zhp = NULL; 1430 zoneList_t zone_list = NULL; 1431 zoneBrandList_t *brands = NULL; 1432 boolean_t be_mounted = B_FALSE; 1433 int zone_index = 0; 1434 int err = BE_SUCCESS; 1435 1436 /* 1437 * Get the supported zone brands so we can pass that 1438 * to z_get_nonglobal_zone_list_by_brand. Currently 1439 * only the ipkg and labeled brand zones are supported 1440 * 1441 */ 1442 if ((brands = be_get_supported_brandlist()) == NULL) { 1443 be_print_err(gettext("be_promote_zone_ds: no supported " 1444 "brands\n")); 1445 return (BE_SUCCESS); 1446 } 1447 1448 if ((zhp = zfs_open(g_zfs, be_root_ds, 1449 ZFS_TYPE_FILESYSTEM)) == NULL) { 1450 be_print_err(gettext("be_promote_zone_ds: Failed to open " 1451 "dataset (%s): %s\n"), be_root_ds, 1452 libzfs_error_description(g_zfs)); 1453 err = zfs_err_to_be_err(g_zfs); 1454 z_free_brand_list(brands); 1455 return (err); 1456 } 1457 1458 if (!zfs_is_mounted(zhp, &temp_mntpt)) { 1459 if ((err = _be_mount(be_name, &temp_mntpt, 1460 BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) { 1461 be_print_err(gettext("be_promote_zone_ds: failed to " 1462 "mount the BE for zones procesing.\n")); 1463 ZFS_CLOSE(zhp); 1464 z_free_brand_list(brands); 1465 return (err); 1466 } 1467 be_mounted = B_TRUE; 1468 } 1469 1470 /* 1471 * Set the zone root to the temp mount point for the BE we just mounted. 1472 */ 1473 z_set_zone_root(temp_mntpt); 1474 1475 /* 1476 * Get all the zones based on the brands we're looking for. If no zones 1477 * are found that we're interested in unmount the BE and move on. 1478 */ 1479 if ((zone_list = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) { 1480 if (be_mounted) 1481 (void) _be_unmount(be_name, 0); 1482 ZFS_CLOSE(zhp); 1483 z_free_brand_list(brands); 1484 free(temp_mntpt); 1485 return (BE_SUCCESS); 1486 } 1487 for (zone_index = 0; z_zlist_get_zonename(zone_list, zone_index) 1488 != NULL; zone_index++) { 1489 char *zone_path = NULL; 1490 1491 /* Skip zones that aren't at least installed */ 1492 if (z_zlist_get_current_state(zone_list, zone_index) < 1493 ZONE_STATE_INSTALLED) 1494 continue; 1495 1496 if (((zone_path = 1497 z_zlist_get_zonepath(zone_list, zone_index)) == NULL) || 1498 ((zone_ds = be_get_ds_from_dir(zone_path)) == NULL) || 1499 !be_zone_supported(zone_ds)) 1500 continue; 1501 1502 if (be_find_active_zone_root(zhp, zone_ds, 1503 zoneroot_ds, sizeof (zoneroot_ds)) != 0) { 1504 be_print_err(gettext("be_promote_zone_ds: " 1505 "Zone does not have an active root " 1506 "dataset, skipping this zone.\n")); 1507 continue; 1508 } 1509 1510 if ((z_zhp = zfs_open(g_zfs, zoneroot_ds, 1511 ZFS_TYPE_FILESYSTEM)) == NULL) { 1512 be_print_err(gettext("be_promote_zone_ds: " 1513 "Failed to open dataset " 1514 "(%s): %s\n"), zoneroot_ds, 1515 libzfs_error_description(g_zfs)); 1516 err = zfs_err_to_be_err(g_zfs); 1517 goto done; 1518 } 1519 1520 if (zfs_prop_get(z_zhp, ZFS_PROP_ORIGIN, origin, 1521 sizeof (origin), NULL, NULL, 0, B_FALSE) != 0) { 1522 ZFS_CLOSE(z_zhp); 1523 continue; 1524 } 1525 1526 /* 1527 * We don't need to close the zfs handle at this 1528 * point because the callback funtion 1529 * be_promote_ds_callback() will close it for us. 1530 */ 1531 if (be_promote_ds_callback(z_zhp, NULL) != 0) { 1532 be_print_err(gettext("be_promote_zone_ds: " 1533 "failed to activate the " 1534 "datasets for %s: %s\n"), 1535 zoneroot_ds, 1536 libzfs_error_description(g_zfs)); 1537 err = BE_ERR_PROMOTE; 1538 goto done; 1539 } 1540 } 1541 done: 1542 if (be_mounted) 1543 (void) _be_unmount(be_name, 0); 1544 ZFS_CLOSE(zhp); 1545 free(temp_mntpt); 1546 z_free_brand_list(brands); 1547 z_free_zone_list(zone_list); 1548 return (err); 1549 } 1550 1551 /* 1552 * Function: be_promote_ds_callback 1553 * Description: This function is used to promote the datasets for the BE 1554 * being activated as well as the datasets for the zones BE 1555 * being activated. 1556 * 1557 * Parameters: 1558 * zhp - the zfs handle for zone BE being activated. 1559 * data - not used. 1560 * Return: 1561 * 0 - Success 1562 * be_errno_t - Failure 1563 * 1564 * Scope: 1565 * Private 1566 */ 1567 static int 1568 /* LINTED */ 1569 be_promote_ds_callback(zfs_handle_t *zhp, void *data) 1570 { 1571 char origin[MAXPATHLEN]; 1572 char *sub_dataset = NULL; 1573 int ret = 0; 1574 1575 if (zhp != NULL) { 1576 sub_dataset = strdup(zfs_get_name(zhp)); 1577 if (sub_dataset == NULL) { 1578 ret = BE_ERR_NOMEM; 1579 goto done; 1580 } 1581 } else { 1582 be_print_err(gettext("be_promote_ds_callback: " 1583 "Invalid zfs handle passed into function\n")); 1584 ret = BE_ERR_INVAL; 1585 goto done; 1586 } 1587 1588 /* 1589 * This loop makes sure that we promote the dataset to the 1590 * top of the tree so that it is no longer a decendent of any 1591 * dataset. The ZFS close and then open is used to make sure that 1592 * the promotion is updated before we move on. 1593 */ 1594 while (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, 1595 sizeof (origin), NULL, NULL, 0, B_FALSE) == 0) { 1596 if (zfs_promote(zhp) != 0) { 1597 if (libzfs_errno(g_zfs) != EZFS_EXISTS) { 1598 be_print_err(gettext("be_promote_ds_callback: " 1599 "promote of %s failed: %s\n"), 1600 zfs_get_name(zhp), 1601 libzfs_error_description(g_zfs)); 1602 ret = zfs_err_to_be_err(g_zfs); 1603 goto done; 1604 } else { 1605 /* 1606 * If the call to zfs_promote returns the 1607 * error EZFS_EXISTS we've hit a snapshot name 1608 * collision. This means we're probably 1609 * attemping to promote a zone dataset above a 1610 * parent dataset that belongs to another zone 1611 * which this zone was cloned from. 1612 * 1613 * TODO: If this is a zone dataset at some 1614 * point we should skip this if the zone 1615 * paths for the dataset and the snapshot 1616 * don't match. 1617 */ 1618 be_print_err(gettext("be_promote_ds_callback: " 1619 "promote of %s failed due to snapshot " 1620 "name collision: %s\n"), zfs_get_name(zhp), 1621 libzfs_error_description(g_zfs)); 1622 ret = zfs_err_to_be_err(g_zfs); 1623 goto done; 1624 } 1625 } 1626 ZFS_CLOSE(zhp); 1627 if ((zhp = zfs_open(g_zfs, sub_dataset, 1628 ZFS_TYPE_FILESYSTEM)) == NULL) { 1629 be_print_err(gettext("be_promote_ds_callback: " 1630 "Failed to open dataset (%s): %s\n"), sub_dataset, 1631 libzfs_error_description(g_zfs)); 1632 ret = zfs_err_to_be_err(g_zfs); 1633 goto done; 1634 } 1635 } 1636 1637 /* Iterate down this dataset's children and promote them */ 1638 ret = zfs_iter_filesystems(zhp, be_promote_ds_callback, NULL); 1639 1640 done: 1641 free(sub_dataset); 1642 ZFS_CLOSE(zhp); 1643 return (ret); 1644 } 1645