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, *type, *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_TYPE, &type) != 0) { 889 be_print_err(gettext("%s: failed to get device type\n"), 890 __func__); 891 return (BE_ERR_NODEV); 892 } 893 /* Skip indirect devices. */ 894 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) 895 return (BE_ERR_NOTSUP); 896 897 if (nvlist_lookup_string(child, ZPOOL_CONFIG_PATH, &path) != 0) { 898 be_print_err(gettext("%s: failed to get device path\n"), 899 __func__); 900 return (BE_ERR_NODEV); 901 } 902 903 if ((nvlist_lookup_uint64_array(child, ZPOOL_CONFIG_VDEV_STATS, 904 (uint64_t **)&vs, &vsc) != 0) || 905 vs->vs_state < VDEV_STATE_DEGRADED) { 906 /* 907 * Don't try to run installgrub on a vdev that is not ONLINE 908 * or DEGRADED. Try to print a warning for each such vdev. 909 */ 910 be_print_err(gettext("%s: vdev %s is %s, can't install " 911 "boot loader\n"), __func__, path, 912 zpool_state_to_name(vs->vs_state, vs->vs_aux)); 913 return (BE_SUCCESS); 914 } 915 916 /* 917 * Modify the vdev path to point to the raw disk. 918 */ 919 path = strdup(path); 920 if (path == NULL) 921 return (BE_ERR_NOMEM); 922 923 dsk_ptr = strstr(path, "/dsk/"); 924 if (dsk_ptr != NULL) { 925 *dsk_ptr = '\0'; 926 dsk_ptr++; 927 } else { 928 dsk_ptr = ""; 929 } 930 931 (void) snprintf(diskname, sizeof (diskname), "%s/r%s", path, dsk_ptr); 932 free(path); 933 934 vname = zpool_vdev_name(g_zfs, zphp, child, B_FALSE); 935 if (vname == NULL) { 936 be_print_err(gettext("%s: failed to get device name: %s\n"), 937 __func__, libzfs_error_description(g_zfs)); 938 return (zfs_err_to_be_err(g_zfs)); 939 } 940 941 if (be_is_isa("i386")) { 942 uint16_t force = flags & BE_INSTALLBOOT_FLAG_FORCE; 943 uint16_t mbr = flags & BE_INSTALLBOOT_FLAG_MBR; 944 945 if (force == BE_INSTALLBOOT_FLAG_FORCE) { 946 if (mbr == BE_INSTALLBOOT_FLAG_MBR || 947 be_do_install_mbr(diskname, child)) 948 flag = "-F -m -f"; 949 else 950 flag = "-F"; 951 } else { 952 if (mbr == BE_INSTALLBOOT_FLAG_MBR || 953 be_do_install_mbr(diskname, child)) 954 flag = "-m -f"; 955 } 956 957 if (be_has_grub()) { 958 (void) snprintf(install_cmd, sizeof (install_cmd), 959 "%s %s %s %s %s", BE_INSTALL_GRUB, flag, 960 stage1, stage2, diskname); 961 } else { 962 (void) snprintf(install_cmd, sizeof (install_cmd), 963 "%s %s %s %s %s", BE_INSTALL_BOOT, flag, 964 stage1, stage2, diskname); 965 } 966 } else if (be_is_isa("sparc")) { 967 if ((flags & BE_INSTALLBOOT_FLAG_FORCE) == 968 BE_INSTALLBOOT_FLAG_FORCE) 969 flag = "-f -F zfs"; 970 else 971 flag = "-F zfs"; 972 973 (void) snprintf(install_cmd, sizeof (install_cmd), 974 "%s %s %s %s", BE_INSTALL_BOOT, flag, stage2, diskname); 975 } else { 976 be_print_err(gettext("%s: unsupported architecture.\n"), 977 __func__); 978 return (BE_ERR_BOOTFILE_INST); 979 } 980 981 *be_run_cmd_outbuf = '\0'; 982 *be_run_cmd_errbuf = '\0'; 983 984 ret = be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ, 985 be_run_cmd_outbuf, BUFSIZ); 986 987 if (ret != BE_SUCCESS) { 988 be_print_err(gettext("%s: install failed for device %s.\n"), 989 __func__, vname); 990 ret = BE_ERR_BOOTFILE_INST; 991 } 992 993 be_print_err(gettext(" Command: \"%s\"\n"), install_cmd); 994 if (be_run_cmd_outbuf[0] != 0) { 995 be_print_err(gettext(" Output:\n")); 996 be_print_err("%s", be_run_cmd_outbuf); 997 } 998 999 if (be_run_cmd_errbuf[0] != 0) { 1000 be_print_err(gettext(" Errors:\n")); 1001 be_print_err("%s", be_run_cmd_errbuf); 1002 } 1003 free(vname); 1004 1005 return (ret); 1006 } 1007 1008 /* 1009 * Function: be_do_copy_grub_cap 1010 * Description: This function will copy grub capability file to BE. 1011 * 1012 * Parameters: 1013 * bt - The transaction data for the BE we're activating. 1014 * Return: 1015 * BE_SUCCESS - Success 1016 * be_errno_t - Failure 1017 * 1018 * Scope: 1019 * Private 1020 */ 1021 static int 1022 be_do_copy_grub_cap(be_transaction_data_t *bt) 1023 { 1024 zfs_handle_t *zhp = NULL; 1025 char cap_file[MAXPATHLEN]; 1026 char zpool_cap_file[MAXPATHLEN]; 1027 char line[BUFSIZ]; 1028 char *tmp_mntpnt = NULL; 1029 char *orig_mntpnt = NULL; 1030 char *pool_mntpnt = NULL; 1031 FILE *cap_fp = NULL; 1032 FILE *zpool_cap_fp = NULL; 1033 int err = 0; 1034 int ret = BE_SUCCESS; 1035 boolean_t pool_mounted = B_FALSE; 1036 boolean_t be_mounted = B_FALSE; 1037 1038 /* 1039 * first get BE dataset mountpoint, we can free all the resources 1040 * once cap_file is built, leaving only be unmount to be done. 1041 */ 1042 if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) == 1043 NULL) { 1044 be_print_err(gettext("%s: failed to " 1045 "open BE root dataset (%s): %s\n"), __func__, 1046 bt->obe_root_ds, libzfs_error_description(g_zfs)); 1047 return (zfs_err_to_be_err(g_zfs)); 1048 } 1049 1050 if (!zfs_is_mounted(zhp, &tmp_mntpnt)) { 1051 if ((ret = _be_mount(bt->obe_name, &tmp_mntpnt, 1052 BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) { 1053 be_print_err(gettext("%s: failed to " 1054 "mount BE (%s)\n"), __func__, bt->obe_name); 1055 ZFS_CLOSE(zhp); 1056 goto done; 1057 } 1058 be_mounted = B_TRUE; 1059 } 1060 ZFS_CLOSE(zhp); /* BE dataset handle is not needed any more */ 1061 1062 (void) snprintf(cap_file, sizeof (cap_file), "%s%s", tmp_mntpnt, 1063 BE_CAP_FILE); 1064 free(tmp_mntpnt); 1065 1066 /* get pool root dataset mountpoint */ 1067 zhp = zfs_open(g_zfs, bt->obe_zpool, ZFS_TYPE_FILESYSTEM); 1068 if (zhp == NULL) { 1069 be_print_err(gettext("%s: zfs_open failed: %s\n"), 1070 __func__, libzfs_error_description(g_zfs)); 1071 ret = zfs_err_to_be_err(g_zfs); 1072 goto done; 1073 } 1074 1075 /* 1076 * Check to see if the pool's dataset is mounted. If it isn't we'll 1077 * attempt to mount it. 1078 */ 1079 if ((ret = be_mount_pool(zhp, &tmp_mntpnt, 1080 &orig_mntpnt, &pool_mounted)) != BE_SUCCESS) { 1081 be_print_err(gettext("%s: pool dataset " 1082 "(%s) could not be mounted\n"), __func__, bt->obe_zpool); 1083 ZFS_CLOSE(zhp); 1084 goto done; 1085 } 1086 1087 /* 1088 * Get the mountpoint for the root pool dataset. 1089 * NOTE: zhp must be kept for _be_unmount_pool() 1090 */ 1091 if (!zfs_is_mounted(zhp, &pool_mntpnt)) { 1092 be_print_err(gettext("%s: pool " 1093 "dataset (%s) is not mounted. Can't check the grub " 1094 "version from the grub capability file.\n"), __func__, 1095 bt->obe_zpool); 1096 ret = BE_ERR_NO_MENU; 1097 goto done; 1098 } 1099 1100 (void) snprintf(zpool_cap_file, sizeof (zpool_cap_file), "%s%s", 1101 pool_mntpnt, BE_CAP_FILE); 1102 free(pool_mntpnt); 1103 1104 if ((cap_fp = fopen(cap_file, "r")) == NULL) { 1105 err = errno; 1106 be_print_err(gettext("%s: failed to open grub " 1107 "capability file\n"), __func__); 1108 ret = errno_to_be_err(err); 1109 goto done; 1110 } 1111 if ((zpool_cap_fp = fopen(zpool_cap_file, "w")) == NULL) { 1112 err = errno; 1113 be_print_err(gettext("%s: failed to open new " 1114 "grub capability file\n"), __func__); 1115 ret = errno_to_be_err(err); 1116 (void) fclose(cap_fp); 1117 goto done; 1118 } 1119 1120 while (fgets(line, BUFSIZ, cap_fp)) { 1121 (void) fputs(line, zpool_cap_fp); 1122 } 1123 1124 (void) fclose(zpool_cap_fp); 1125 (void) fclose(cap_fp); 1126 1127 done: 1128 if (be_mounted) 1129 (void) _be_unmount(bt->obe_name, 0); 1130 1131 if (pool_mounted) { 1132 err = be_unmount_pool(zhp, tmp_mntpnt, orig_mntpnt); 1133 if (ret == BE_SUCCESS) 1134 ret = err; 1135 free(orig_mntpnt); 1136 free(tmp_mntpnt); 1137 zfs_close(zhp); 1138 } 1139 return (ret); 1140 } 1141 1142 /* 1143 * Function: be_is_install_needed 1144 * Description: Check detached version files to detect if bootloader 1145 * install/update is needed. 1146 * 1147 * Parameters: 1148 * bt - The transaction data for the BE we're activating. 1149 * update - set B_TRUE is update is needed. 1150 * Return: 1151 * BE_SUCCESS - Success 1152 * be_errno_t - Failure 1153 * 1154 * Scope: 1155 * Private 1156 */ 1157 static int 1158 be_is_install_needed(be_transaction_data_t *bt, boolean_t *update) 1159 { 1160 int ret = BE_SUCCESS; 1161 char *cur_vers = NULL, *new_vers = NULL; 1162 1163 assert(bt != NULL); 1164 assert(update != NULL); 1165 1166 if (!be_has_grub()) { 1167 /* 1168 * no detached versioning, let installboot to manage 1169 * versioning. 1170 */ 1171 *update = B_TRUE; 1172 return (ret); 1173 } 1174 1175 *update = B_FALSE; /* set default */ 1176 1177 /* 1178 * We need to check to see if the version number from 1179 * the BE being activated is greater than the current 1180 * one. 1181 */ 1182 ret = be_get_grub_vers(bt, &cur_vers, &new_vers); 1183 if (ret != BE_SUCCESS) { 1184 be_print_err(gettext("be_activate: failed to get grub " 1185 "versions from capability files.\n")); 1186 return (ret); 1187 } 1188 /* update if we have both versions and can compare */ 1189 if (cur_vers != NULL) { 1190 if (new_vers != NULL) { 1191 if (atof(cur_vers) < atof(new_vers)) 1192 *update = B_TRUE; 1193 free(new_vers); 1194 } 1195 free(cur_vers); 1196 } else if (new_vers != NULL) { 1197 /* we only got new version - update */ 1198 *update = B_TRUE; 1199 free(new_vers); 1200 } 1201 return (ret); 1202 } 1203 1204 static int 1205 be_do_installboot_walk(zpool_handle_t *zphp, nvlist_t *nv, char *stage1, 1206 char *stage2, uint16_t flags) 1207 { 1208 boolean_t verbose = do_print; 1209 nvlist_t **child; 1210 uint_t children = 0; 1211 int ret = -1; 1212 1213 /* It is OK to have no children. */ 1214 (void) nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1215 &children); 1216 1217 for (int c = 0; c < children; c++) { 1218 char *vname; 1219 int rv; 1220 1221 /* ensure update on child status */ 1222 vname = zpool_vdev_name(g_zfs, zphp, child[c], verbose); 1223 if (vname == NULL) { 1224 be_print_err(gettext("%s: " 1225 "failed to get device name: %s\n"), __func__, 1226 libzfs_error_description(g_zfs)); 1227 return (zfs_err_to_be_err(g_zfs)); 1228 } else { 1229 be_print_err(gettext("%s: child %d of %d device %s\n"), 1230 __func__, c, children, vname); 1231 } 1232 1233 rv = be_do_installboot_walk(zphp, child[c], stage1, stage2, 1234 flags); 1235 switch (rv) { 1236 case BE_ERR_NOTSUP: 1237 /* ignore unsupported devices */ 1238 be_print_err( 1239 gettext("%s: device %s is not supported\n"), 1240 __func__, vname); 1241 break; 1242 case BE_SUCCESS: 1243 /* catch at least one success */ 1244 ret = rv; 1245 break; 1246 default: 1247 if (ret == -1) 1248 ret = rv; 1249 break; 1250 } 1251 free(vname); 1252 } 1253 1254 if (children > 0) 1255 return (ret == -1? BE_ERR_NOTSUP : ret); 1256 return (be_do_installboot_helper(zphp, nv, stage1, stage2, flags)); 1257 } 1258 1259 /* 1260 * Function: be_do_installboot 1261 * Description: This function runs installgrub/installboot using the boot 1262 * loader files from the BE we're activating and installing 1263 * them on the pool the BE lives in. 1264 * 1265 * Parameters: 1266 * bt - The transaction data for the BE we're activating. 1267 * flags - flags for bootloader install 1268 * Return: 1269 * BE_SUCCESS - Success 1270 * be_errno_t - Failure 1271 * 1272 * Scope: 1273 * Private 1274 */ 1275 static int 1276 be_do_installboot(be_transaction_data_t *bt, uint16_t flags) 1277 { 1278 zpool_handle_t *zphp = NULL; 1279 zfs_handle_t *zhp = NULL; 1280 nvlist_t *nv, *config; 1281 char *tmp_mntpt = NULL; 1282 char stage1[MAXPATHLEN]; 1283 char stage2[MAXPATHLEN]; 1284 int ret = BE_SUCCESS; 1285 boolean_t be_mounted = B_FALSE; 1286 boolean_t update = B_FALSE; 1287 1288 /* 1289 * check versions. This call is to support detached 1290 * version implementation like grub. Embedded versioning is 1291 * checked by actual installer. 1292 */ 1293 if ((flags & BE_INSTALLBOOT_FLAG_FORCE) != BE_INSTALLBOOT_FLAG_FORCE) { 1294 ret = be_is_install_needed(bt, &update); 1295 if (ret != BE_SUCCESS || update == B_FALSE) 1296 return (ret); 1297 } 1298 1299 if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) == 1300 NULL) { 1301 be_print_err(gettext("%s: failed to " 1302 "open BE root dataset (%s): %s\n"), __func__, 1303 bt->obe_root_ds, libzfs_error_description(g_zfs)); 1304 ret = zfs_err_to_be_err(g_zfs); 1305 return (ret); 1306 } 1307 if (!zfs_is_mounted(zhp, &tmp_mntpt)) { 1308 if ((ret = _be_mount(bt->obe_name, &tmp_mntpt, 1309 BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) { 1310 be_print_err(gettext("%s: failed to " 1311 "mount BE (%s)\n"), __func__, bt->obe_name); 1312 ZFS_CLOSE(zhp); 1313 return (ret); 1314 } 1315 be_mounted = B_TRUE; 1316 } 1317 ZFS_CLOSE(zhp); 1318 1319 if (be_is_isa("i386")) { 1320 if (be_has_grub()) { 1321 (void) snprintf(stage1, sizeof (stage1), "%s%s", 1322 tmp_mntpt, BE_GRUB_STAGE_1); 1323 (void) snprintf(stage2, sizeof (stage2), "%s%s", 1324 tmp_mntpt, BE_GRUB_STAGE_2); 1325 } else { 1326 (void) snprintf(stage1, sizeof (stage1), "%s%s", 1327 tmp_mntpt, BE_LOADER_STAGE_1); 1328 (void) snprintf(stage2, sizeof (stage2), "%s%s", 1329 tmp_mntpt, BE_LOADER_STAGE_2); 1330 } 1331 } else if (be_is_isa("sparc")) { 1332 char *platform = be_get_platform(); 1333 1334 if (platform == NULL) { 1335 be_print_err(gettext("%s: failed to detect system " 1336 "platform name\n"), __func__); 1337 if (be_mounted) 1338 (void) _be_unmount(bt->obe_name, 0); 1339 free(tmp_mntpt); 1340 return (BE_ERR_BOOTFILE_INST); 1341 } 1342 stage1[0] = '\0'; /* sparc has no stage1 */ 1343 (void) snprintf(stage2, sizeof (stage2), 1344 "%s/usr/platform/%s%s", tmp_mntpt, 1345 platform, BE_SPARC_BOOTBLK); 1346 } else { 1347 be_print_err(gettext("%s: unsupported architecture.\n"), 1348 __func__); 1349 return (BE_ERR_BOOTFILE_INST); 1350 } 1351 1352 if ((zphp = zpool_open(g_zfs, bt->obe_zpool)) == NULL) { 1353 be_print_err(gettext("%s: failed to open " 1354 "pool (%s): %s\n"), __func__, bt->obe_zpool, 1355 libzfs_error_description(g_zfs)); 1356 ret = zfs_err_to_be_err(g_zfs); 1357 if (be_mounted) 1358 (void) _be_unmount(bt->obe_name, 0); 1359 free(tmp_mntpt); 1360 return (ret); 1361 } 1362 1363 if ((config = zpool_get_config(zphp, NULL)) == NULL) { 1364 be_print_err(gettext("%s: failed to get zpool " 1365 "configuration information. %s\n"), __func__, 1366 libzfs_error_description(g_zfs)); 1367 ret = zfs_err_to_be_err(g_zfs); 1368 goto done; 1369 } 1370 1371 /* 1372 * Get the vdev tree 1373 */ 1374 if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nv) != 0) { 1375 be_print_err(gettext("%s: failed to get vdev " 1376 "tree: %s\n"), __func__, libzfs_error_description(g_zfs)); 1377 ret = zfs_err_to_be_err(g_zfs); 1378 goto done; 1379 } 1380 1381 ret = be_do_installboot_walk(zphp, nv, stage1, stage2, flags); 1382 1383 if (be_has_grub()) { 1384 ret = be_do_copy_grub_cap(bt); 1385 } 1386 1387 done: 1388 ZFS_CLOSE(zhp); 1389 if (be_mounted) 1390 (void) _be_unmount(bt->obe_name, 0); 1391 zpool_close(zphp); 1392 free(tmp_mntpt); 1393 return (ret); 1394 } 1395 1396 /* 1397 * Function: be_promote_zone_ds 1398 * Description: This function finds the zones for the BE being activated 1399 * and the active zonepath dataset for each zone. Then each 1400 * active zonepath dataset is promoted. 1401 * 1402 * Parameters: 1403 * be_name - the name of the global zone BE that we need to 1404 * find the zones for. 1405 * be_root_ds - the root dataset for be_name. 1406 * Return: 1407 * BE_SUCCESS - Success 1408 * be_errno_t - Failure 1409 * 1410 * Scope: 1411 * Private 1412 */ 1413 static int 1414 be_promote_zone_ds(char *be_name, char *be_root_ds) 1415 { 1416 char *zone_ds = NULL; 1417 char *temp_mntpt = NULL; 1418 char origin[MAXPATHLEN]; 1419 char zoneroot_ds[MAXPATHLEN]; 1420 zfs_handle_t *zhp = NULL; 1421 zfs_handle_t *z_zhp = NULL; 1422 zoneList_t zone_list = NULL; 1423 zoneBrandList_t *brands = NULL; 1424 boolean_t be_mounted = B_FALSE; 1425 int zone_index = 0; 1426 int err = BE_SUCCESS; 1427 1428 /* 1429 * Get the supported zone brands so we can pass that 1430 * to z_get_nonglobal_zone_list_by_brand. Currently 1431 * only the ipkg and labeled brand zones are supported 1432 * 1433 */ 1434 if ((brands = be_get_supported_brandlist()) == NULL) { 1435 be_print_err(gettext("be_promote_zone_ds: no supported " 1436 "brands\n")); 1437 return (BE_SUCCESS); 1438 } 1439 1440 if ((zhp = zfs_open(g_zfs, be_root_ds, 1441 ZFS_TYPE_FILESYSTEM)) == NULL) { 1442 be_print_err(gettext("be_promote_zone_ds: Failed to open " 1443 "dataset (%s): %s\n"), be_root_ds, 1444 libzfs_error_description(g_zfs)); 1445 err = zfs_err_to_be_err(g_zfs); 1446 z_free_brand_list(brands); 1447 return (err); 1448 } 1449 1450 if (!zfs_is_mounted(zhp, &temp_mntpt)) { 1451 if ((err = _be_mount(be_name, &temp_mntpt, 1452 BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) { 1453 be_print_err(gettext("be_promote_zone_ds: failed to " 1454 "mount the BE for zones procesing.\n")); 1455 ZFS_CLOSE(zhp); 1456 z_free_brand_list(brands); 1457 return (err); 1458 } 1459 be_mounted = B_TRUE; 1460 } 1461 1462 /* 1463 * Set the zone root to the temp mount point for the BE we just mounted. 1464 */ 1465 z_set_zone_root(temp_mntpt); 1466 1467 /* 1468 * Get all the zones based on the brands we're looking for. If no zones 1469 * are found that we're interested in unmount the BE and move on. 1470 */ 1471 if ((zone_list = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) { 1472 if (be_mounted) 1473 (void) _be_unmount(be_name, 0); 1474 ZFS_CLOSE(zhp); 1475 z_free_brand_list(brands); 1476 free(temp_mntpt); 1477 return (BE_SUCCESS); 1478 } 1479 for (zone_index = 0; z_zlist_get_zonename(zone_list, zone_index) 1480 != NULL; zone_index++) { 1481 char *zone_path = NULL; 1482 1483 /* Skip zones that aren't at least installed */ 1484 if (z_zlist_get_current_state(zone_list, zone_index) < 1485 ZONE_STATE_INSTALLED) 1486 continue; 1487 1488 if (((zone_path = 1489 z_zlist_get_zonepath(zone_list, zone_index)) == NULL) || 1490 ((zone_ds = be_get_ds_from_dir(zone_path)) == NULL) || 1491 !be_zone_supported(zone_ds)) 1492 continue; 1493 1494 if (be_find_active_zone_root(zhp, zone_ds, 1495 zoneroot_ds, sizeof (zoneroot_ds)) != 0) { 1496 be_print_err(gettext("be_promote_zone_ds: " 1497 "Zone does not have an active root " 1498 "dataset, skipping this zone.\n")); 1499 continue; 1500 } 1501 1502 if ((z_zhp = zfs_open(g_zfs, zoneroot_ds, 1503 ZFS_TYPE_FILESYSTEM)) == NULL) { 1504 be_print_err(gettext("be_promote_zone_ds: " 1505 "Failed to open dataset " 1506 "(%s): %s\n"), zoneroot_ds, 1507 libzfs_error_description(g_zfs)); 1508 err = zfs_err_to_be_err(g_zfs); 1509 goto done; 1510 } 1511 1512 if (zfs_prop_get(z_zhp, ZFS_PROP_ORIGIN, origin, 1513 sizeof (origin), NULL, NULL, 0, B_FALSE) != 0) { 1514 ZFS_CLOSE(z_zhp); 1515 continue; 1516 } 1517 1518 /* 1519 * We don't need to close the zfs handle at this 1520 * point because the callback funtion 1521 * be_promote_ds_callback() will close it for us. 1522 */ 1523 if (be_promote_ds_callback(z_zhp, NULL) != 0) { 1524 be_print_err(gettext("be_promote_zone_ds: " 1525 "failed to activate the " 1526 "datasets for %s: %s\n"), 1527 zoneroot_ds, 1528 libzfs_error_description(g_zfs)); 1529 err = BE_ERR_PROMOTE; 1530 goto done; 1531 } 1532 } 1533 done: 1534 if (be_mounted) 1535 (void) _be_unmount(be_name, 0); 1536 ZFS_CLOSE(zhp); 1537 free(temp_mntpt); 1538 z_free_brand_list(brands); 1539 z_free_zone_list(zone_list); 1540 return (err); 1541 } 1542 1543 /* 1544 * Function: be_promote_ds_callback 1545 * Description: This function is used to promote the datasets for the BE 1546 * being activated as well as the datasets for the zones BE 1547 * being activated. 1548 * 1549 * Parameters: 1550 * zhp - the zfs handle for zone BE being activated. 1551 * data - not used. 1552 * Return: 1553 * 0 - Success 1554 * be_errno_t - Failure 1555 * 1556 * Scope: 1557 * Private 1558 */ 1559 static int 1560 /* LINTED */ 1561 be_promote_ds_callback(zfs_handle_t *zhp, void *data) 1562 { 1563 char origin[MAXPATHLEN]; 1564 char *sub_dataset = NULL; 1565 int ret = 0; 1566 1567 if (zhp != NULL) { 1568 sub_dataset = strdup(zfs_get_name(zhp)); 1569 if (sub_dataset == NULL) { 1570 ret = BE_ERR_NOMEM; 1571 goto done; 1572 } 1573 } else { 1574 be_print_err(gettext("be_promote_ds_callback: " 1575 "Invalid zfs handle passed into function\n")); 1576 ret = BE_ERR_INVAL; 1577 goto done; 1578 } 1579 1580 /* 1581 * This loop makes sure that we promote the dataset to the 1582 * top of the tree so that it is no longer a decendent of any 1583 * dataset. The ZFS close and then open is used to make sure that 1584 * the promotion is updated before we move on. 1585 */ 1586 while (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, 1587 sizeof (origin), NULL, NULL, 0, B_FALSE) == 0) { 1588 if (zfs_promote(zhp) != 0) { 1589 if (libzfs_errno(g_zfs) != EZFS_EXISTS) { 1590 be_print_err(gettext("be_promote_ds_callback: " 1591 "promote of %s failed: %s\n"), 1592 zfs_get_name(zhp), 1593 libzfs_error_description(g_zfs)); 1594 ret = zfs_err_to_be_err(g_zfs); 1595 goto done; 1596 } else { 1597 /* 1598 * If the call to zfs_promote returns the 1599 * error EZFS_EXISTS we've hit a snapshot name 1600 * collision. This means we're probably 1601 * attemping to promote a zone dataset above a 1602 * parent dataset that belongs to another zone 1603 * which this zone was cloned from. 1604 * 1605 * TODO: If this is a zone dataset at some 1606 * point we should skip this if the zone 1607 * paths for the dataset and the snapshot 1608 * don't match. 1609 */ 1610 be_print_err(gettext("be_promote_ds_callback: " 1611 "promote of %s failed due to snapshot " 1612 "name collision: %s\n"), zfs_get_name(zhp), 1613 libzfs_error_description(g_zfs)); 1614 ret = zfs_err_to_be_err(g_zfs); 1615 goto done; 1616 } 1617 } 1618 ZFS_CLOSE(zhp); 1619 if ((zhp = zfs_open(g_zfs, sub_dataset, 1620 ZFS_TYPE_FILESYSTEM)) == NULL) { 1621 be_print_err(gettext("be_promote_ds_callback: " 1622 "Failed to open dataset (%s): %s\n"), sub_dataset, 1623 libzfs_error_description(g_zfs)); 1624 ret = zfs_err_to_be_err(g_zfs); 1625 goto done; 1626 } 1627 } 1628 1629 /* Iterate down this dataset's children and promote them */ 1630 ret = zfs_iter_filesystems(zhp, be_promote_ds_callback, NULL); 1631 1632 done: 1633 free(sub_dataset); 1634 ZFS_CLOSE(zhp); 1635 return (ret); 1636 } 1637