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 2011 Nexenta Systems, Inc. All rights reserved. 28 */ 29 30 /* 31 * System includes 32 */ 33 34 #include <assert.h> 35 #include <ctype.h> 36 #include <errno.h> 37 #include <libgen.h> 38 #include <libintl.h> 39 #include <libnvpair.h> 40 #include <libzfs.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <sys/mnttab.h> 45 #include <sys/mount.h> 46 #include <sys/stat.h> 47 #include <sys/types.h> 48 #include <sys/wait.h> 49 #include <unistd.h> 50 51 #include <libbe.h> 52 #include <libbe_priv.h> 53 54 /* Library wide variables */ 55 libzfs_handle_t *g_zfs = NULL; 56 57 /* Private function prototypes */ 58 static int _be_destroy(const char *, be_destroy_data_t *); 59 static int be_destroy_zones(char *, char *, be_destroy_data_t *); 60 static int be_destroy_zone_roots(char *, be_destroy_data_t *); 61 static int be_destroy_zone_roots_callback(zfs_handle_t *, void *); 62 static int be_copy_zones(char *, char *, char *); 63 static int be_clone_fs_callback(zfs_handle_t *, void *); 64 static int be_destroy_callback(zfs_handle_t *, void *); 65 static int be_send_fs_callback(zfs_handle_t *, void *); 66 static int be_demote_callback(zfs_handle_t *, void *); 67 static int be_demote_find_clone_callback(zfs_handle_t *, void *); 68 static int be_has_snapshot_callback(zfs_handle_t *, void *); 69 static int be_demote_get_one_clone(zfs_handle_t *, void *); 70 static int be_get_snap(char *, char **); 71 static int be_prep_clone_send_fs(zfs_handle_t *, be_transaction_data_t *, 72 char *, int); 73 static boolean_t be_create_container_ds(char *); 74 static char *be_get_zone_be_name(char *root_ds, char *container_ds); 75 static int be_zone_root_exists_callback(zfs_handle_t *, void *); 76 77 /* ******************************************************************** */ 78 /* Public Functions */ 79 /* ******************************************************************** */ 80 81 /* 82 * Function: be_init 83 * Description: Creates the initial datasets for a BE and leaves them 84 * unpopulated. The resultant BE can be mounted but can't 85 * yet be activated or booted. 86 * Parameters: 87 * be_attrs - pointer to nvlist_t of attributes being passed in. 88 * The following attributes are used by this function: 89 * 90 * BE_ATTR_NEW_BE_NAME *required 91 * BE_ATTR_NEW_BE_POOL *required 92 * BE_ATTR_ZFS_PROPERTIES *optional 93 * BE_ATTR_FS_NAMES *optional 94 * BE_ATTR_FS_NUM *optional 95 * BE_ATTR_SHARED_FS_NAMES *optional 96 * BE_ATTR_SHARED_FS_NUM *optional 97 * Return: 98 * BE_SUCCESS - Success 99 * be_errno_t - Failure 100 * Scope: 101 * Public 102 */ 103 int 104 be_init(nvlist_t *be_attrs) 105 { 106 be_transaction_data_t bt = { 0 }; 107 zpool_handle_t *zlp; 108 nvlist_t *zfs_props = NULL; 109 char nbe_root_ds[MAXPATHLEN]; 110 char child_fs[MAXPATHLEN]; 111 char **fs_names = NULL; 112 char **shared_fs_names = NULL; 113 uint16_t fs_num = 0; 114 uint16_t shared_fs_num = 0; 115 int nelem; 116 int i; 117 int zret = 0, ret = BE_SUCCESS; 118 119 /* Initialize libzfs handle */ 120 if (!be_zfs_init()) 121 return (BE_ERR_INIT); 122 123 /* Get new BE name */ 124 if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME, &bt.nbe_name) 125 != 0) { 126 be_print_err(gettext("be_init: failed to lookup " 127 "BE_ATTR_NEW_BE_NAME attribute\n")); 128 return (BE_ERR_INVAL); 129 } 130 131 /* Validate new BE name */ 132 if (!be_valid_be_name(bt.nbe_name)) { 133 be_print_err(gettext("be_init: invalid BE name %s\n"), 134 bt.nbe_name); 135 return (BE_ERR_INVAL); 136 } 137 138 /* Get zpool name */ 139 if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_POOL, &bt.nbe_zpool) 140 != 0) { 141 be_print_err(gettext("be_init: failed to lookup " 142 "BE_ATTR_NEW_BE_POOL attribute\n")); 143 return (BE_ERR_INVAL); 144 } 145 146 /* Get file system attributes */ 147 nelem = 0; 148 if (nvlist_lookup_pairs(be_attrs, 0, 149 BE_ATTR_FS_NUM, DATA_TYPE_UINT16, &fs_num, 150 BE_ATTR_FS_NAMES, DATA_TYPE_STRING_ARRAY, &fs_names, &nelem, 151 NULL) != 0) { 152 be_print_err(gettext("be_init: failed to lookup fs " 153 "attributes\n")); 154 return (BE_ERR_INVAL); 155 } 156 if (nelem != fs_num) { 157 be_print_err(gettext("be_init: size of FS_NAMES array (%d) " 158 "does not match FS_NUM (%d)\n"), nelem, fs_num); 159 return (BE_ERR_INVAL); 160 } 161 162 /* Get shared file system attributes */ 163 nelem = 0; 164 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 165 BE_ATTR_SHARED_FS_NUM, DATA_TYPE_UINT16, &shared_fs_num, 166 BE_ATTR_SHARED_FS_NAMES, DATA_TYPE_STRING_ARRAY, &shared_fs_names, 167 &nelem, NULL) != 0) { 168 be_print_err(gettext("be_init: failed to lookup " 169 "shared fs attributes\n")); 170 return (BE_ERR_INVAL); 171 } 172 if (nelem != shared_fs_num) { 173 be_print_err(gettext("be_init: size of SHARED_FS_NAMES " 174 "array does not match SHARED_FS_NUM\n")); 175 return (BE_ERR_INVAL); 176 } 177 178 /* Verify that nbe_zpool exists */ 179 if ((zlp = zpool_open(g_zfs, bt.nbe_zpool)) == NULL) { 180 be_print_err(gettext("be_init: failed to " 181 "find existing zpool (%s): %s\n"), bt.nbe_zpool, 182 libzfs_error_description(g_zfs)); 183 return (zfs_err_to_be_err(g_zfs)); 184 } 185 zpool_close(zlp); 186 187 /* 188 * Verify BE container dataset in nbe_zpool exists. 189 * If not, create it. 190 */ 191 if (!be_create_container_ds(bt.nbe_zpool)) 192 return (BE_ERR_CREATDS); 193 194 /* 195 * Verify that nbe_name doesn't already exist in some pool. 196 */ 197 if ((zret = zpool_iter(g_zfs, be_exists_callback, bt.nbe_name)) > 0) { 198 be_print_err(gettext("be_init: BE (%s) already exists\n"), 199 bt.nbe_name); 200 return (BE_ERR_BE_EXISTS); 201 } else if (zret < 0) { 202 be_print_err(gettext("be_init: zpool_iter failed: %s\n"), 203 libzfs_error_description(g_zfs)); 204 return (zfs_err_to_be_err(g_zfs)); 205 } 206 207 /* Generate string for BE's root dataset */ 208 be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds, 209 sizeof (nbe_root_ds)); 210 211 /* 212 * Create property list for new BE root dataset. If some 213 * zfs properties were already provided by the caller, dup 214 * that list. Otherwise initialize a new property list. 215 */ 216 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 217 BE_ATTR_ZFS_PROPERTIES, DATA_TYPE_NVLIST, &zfs_props, NULL) 218 != 0) { 219 be_print_err(gettext("be_init: failed to lookup " 220 "BE_ATTR_ZFS_PROPERTIES attribute\n")); 221 return (BE_ERR_INVAL); 222 } 223 if (zfs_props != NULL) { 224 /* Make sure its a unique nvlist */ 225 if (!(zfs_props->nvl_nvflag & NV_UNIQUE_NAME) && 226 !(zfs_props->nvl_nvflag & NV_UNIQUE_NAME_TYPE)) { 227 be_print_err(gettext("be_init: ZFS property list " 228 "not unique\n")); 229 return (BE_ERR_INVAL); 230 } 231 232 /* Dup the list */ 233 if (nvlist_dup(zfs_props, &bt.nbe_zfs_props, 0) != 0) { 234 be_print_err(gettext("be_init: failed to dup ZFS " 235 "property list\n")); 236 return (BE_ERR_NOMEM); 237 } 238 } else { 239 /* Initialize new nvlist */ 240 if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) { 241 be_print_err(gettext("be_init: internal " 242 "error: out of memory\n")); 243 return (BE_ERR_NOMEM); 244 } 245 } 246 247 /* Set the mountpoint property for the root dataset */ 248 if (nvlist_add_string(bt.nbe_zfs_props, 249 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), "/") != 0) { 250 be_print_err(gettext("be_init: internal error " 251 "out of memory\n")); 252 ret = BE_ERR_NOMEM; 253 goto done; 254 } 255 256 /* Set the 'canmount' property */ 257 if (nvlist_add_string(bt.nbe_zfs_props, 258 zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto") != 0) { 259 be_print_err(gettext("be_init: internal error " 260 "out of memory\n")); 261 ret = BE_ERR_NOMEM; 262 goto done; 263 } 264 265 /* Create BE root dataset for the new BE */ 266 if (zfs_create(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM, 267 bt.nbe_zfs_props) != 0) { 268 be_print_err(gettext("be_init: failed to " 269 "create BE root dataset (%s): %s\n"), nbe_root_ds, 270 libzfs_error_description(g_zfs)); 271 ret = zfs_err_to_be_err(g_zfs); 272 goto done; 273 } 274 275 /* Set UUID for new BE */ 276 if ((ret = be_set_uuid(nbe_root_ds)) != BE_SUCCESS) { 277 be_print_err(gettext("be_init: failed to " 278 "set uuid for new BE\n")); 279 } 280 281 /* 282 * Clear the mountpoint property so that the non-shared 283 * file systems created below inherit their mountpoints. 284 */ 285 (void) nvlist_remove(bt.nbe_zfs_props, 286 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), DATA_TYPE_STRING); 287 288 /* Create the new BE's non-shared file systems */ 289 for (i = 0; i < fs_num && fs_names[i]; i++) { 290 /* 291 * If fs == "/", skip it; 292 * we already created the root dataset 293 */ 294 if (strcmp(fs_names[i], "/") == 0) 295 continue; 296 297 /* Generate string for file system */ 298 (void) snprintf(child_fs, sizeof (child_fs), "%s%s", 299 nbe_root_ds, fs_names[i]); 300 301 /* Create file system */ 302 if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM, 303 bt.nbe_zfs_props) != 0) { 304 be_print_err(gettext("be_init: failed to create " 305 "BE's child dataset (%s): %s\n"), child_fs, 306 libzfs_error_description(g_zfs)); 307 ret = zfs_err_to_be_err(g_zfs); 308 goto done; 309 } 310 } 311 312 /* Create the new BE's shared file systems */ 313 if (shared_fs_num > 0) { 314 nvlist_t *props = NULL; 315 316 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 317 be_print_err(gettext("be_init: nvlist_alloc failed\n")); 318 ret = BE_ERR_NOMEM; 319 goto done; 320 } 321 322 for (i = 0; i < shared_fs_num; i++) { 323 /* Generate string for shared file system */ 324 (void) snprintf(child_fs, sizeof (child_fs), "%s%s", 325 bt.nbe_zpool, shared_fs_names[i]); 326 327 if (nvlist_add_string(props, 328 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 329 shared_fs_names[i]) != 0) { 330 be_print_err(gettext("be_init: " 331 "internal error: out of memory\n")); 332 nvlist_free(props); 333 ret = BE_ERR_NOMEM; 334 goto done; 335 } 336 337 /* Create file system if it doesn't already exist */ 338 if (zfs_dataset_exists(g_zfs, child_fs, 339 ZFS_TYPE_FILESYSTEM)) { 340 continue; 341 } 342 if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM, 343 props) != 0) { 344 be_print_err(gettext("be_init: failed to " 345 "create BE's shared dataset (%s): %s\n"), 346 child_fs, libzfs_error_description(g_zfs)); 347 ret = zfs_err_to_be_err(g_zfs); 348 nvlist_free(props); 349 goto done; 350 } 351 } 352 353 nvlist_free(props); 354 } 355 356 done: 357 if (bt.nbe_zfs_props != NULL) 358 nvlist_free(bt.nbe_zfs_props); 359 360 be_zfs_fini(); 361 362 return (ret); 363 } 364 365 /* 366 * Function: be_destroy 367 * Description: Destroy a BE and all of its children datasets, snapshots and 368 * zones that belong to the parent BE. 369 * Parameters: 370 * be_attrs - pointer to nvlist_t of attributes being passed in. 371 * The following attributes are used by this function: 372 * 373 * BE_ATTR_ORIG_BE_NAME *required 374 * BE_ATTR_DESTROY_FLAGS *optional 375 * Return: 376 * BE_SUCCESS - Success 377 * be_errno_t - Failure 378 * Scope: 379 * Public 380 */ 381 int 382 be_destroy(nvlist_t *be_attrs) 383 { 384 zfs_handle_t *zhp = NULL; 385 be_transaction_data_t bt = { 0 }; 386 be_transaction_data_t cur_bt = { 0 }; 387 be_destroy_data_t dd = { 0 }; 388 int ret = BE_SUCCESS; 389 uint16_t flags = 0; 390 boolean_t bs_found = B_FALSE; 391 int zret; 392 char obe_root_ds[MAXPATHLEN]; 393 char *mp = NULL; 394 395 /* Initialize libzfs handle */ 396 if (!be_zfs_init()) 397 return (BE_ERR_INIT); 398 399 /* Get name of BE to delete */ 400 if (nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, &bt.obe_name) 401 != 0) { 402 be_print_err(gettext("be_destroy: failed to lookup " 403 "BE_ATTR_ORIG_BE_NAME attribute\n")); 404 return (BE_ERR_INVAL); 405 } 406 407 /* 408 * Validate BE name. If valid, then check that the original BE is not 409 * the active BE. If it is the 'active' BE then return an error code 410 * since we can't destroy the active BE. 411 */ 412 if (!be_valid_be_name(bt.obe_name)) { 413 be_print_err(gettext("be_destroy: invalid BE name %s\n"), 414 bt.obe_name); 415 return (BE_ERR_INVAL); 416 } else if (bt.obe_name != NULL) { 417 if ((ret = be_find_current_be(&cur_bt)) != BE_SUCCESS) { 418 return (ret); 419 } 420 if (strcmp(cur_bt.obe_name, bt.obe_name) == 0) { 421 return (BE_ERR_DESTROY_CURR_BE); 422 } 423 } 424 425 /* Get destroy flags if provided */ 426 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 427 BE_ATTR_DESTROY_FLAGS, DATA_TYPE_UINT16, &flags, NULL) 428 != 0) { 429 be_print_err(gettext("be_destroy: failed to lookup " 430 "BE_ATTR_DESTROY_FLAGS attribute\n")); 431 return (BE_ERR_INVAL); 432 } 433 434 dd.destroy_snaps = flags & BE_DESTROY_FLAG_SNAPSHOTS; 435 dd.force_unmount = flags & BE_DESTROY_FLAG_FORCE_UNMOUNT; 436 437 /* Find which zpool obe_name lives in */ 438 if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) { 439 be_print_err(gettext("be_destroy: failed to find zpool " 440 "for BE (%s)\n"), bt.obe_name); 441 return (BE_ERR_BE_NOENT); 442 } else if (zret < 0) { 443 be_print_err(gettext("be_destroy: zpool_iter failed: %s\n"), 444 libzfs_error_description(g_zfs)); 445 return (zfs_err_to_be_err(g_zfs)); 446 } 447 448 /* Generate string for obe_name's root dataset */ 449 be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds, 450 sizeof (obe_root_ds)); 451 bt.obe_root_ds = obe_root_ds; 452 453 /* 454 * Detect if the BE to destroy has the 'active on boot' property set. 455 * If so, set the 'active on boot' property on the the 'active' BE. 456 */ 457 if (be_is_active_on_boot(bt.obe_name)) { 458 if ((ret = be_activate_current_be()) != BE_SUCCESS) { 459 be_print_err(gettext("be_destroy: failed to " 460 "make the current BE 'active on boot'\n")); 461 return (ret); 462 } 463 } 464 465 /* Get handle to BE's root dataset */ 466 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM)) == 467 NULL) { 468 be_print_err(gettext("be_destroy: failed to " 469 "open BE root dataset (%s): %s\n"), bt.obe_root_ds, 470 libzfs_error_description(g_zfs)); 471 return (zfs_err_to_be_err(g_zfs)); 472 } 473 474 /* 475 * Check if BE has snapshots and BE_DESTROY_FLAG_SNAPSHOTS 476 * is not set. 477 */ 478 (void) zfs_iter_snapshots(zhp, be_has_snapshot_callback, &bs_found); 479 if (!dd.destroy_snaps && bs_found) { 480 ZFS_CLOSE(zhp); 481 return (BE_ERR_SS_EXISTS); 482 } 483 484 /* Get the UUID of the global BE */ 485 if (be_get_uuid(zfs_get_name(zhp), &dd.gz_be_uuid) != BE_SUCCESS) { 486 be_print_err(gettext("be_destroy: BE has no UUID (%s)\n"), 487 zfs_get_name(zhp)); 488 } 489 490 /* 491 * If the global BE is mounted, make sure we've been given the 492 * flag to forcibly unmount it. 493 */ 494 if (zfs_is_mounted(zhp, &mp)) { 495 if (!(dd.force_unmount)) { 496 be_print_err(gettext("be_destroy: " 497 "%s is currently mounted at %s, cannot destroy\n"), 498 bt.obe_name, mp != NULL ? mp : "<unknown>"); 499 500 free(mp); 501 ZFS_CLOSE(zhp); 502 return (BE_ERR_MOUNTED); 503 } 504 free(mp); 505 } 506 507 /* 508 * Destroy the non-global zone BE's if we are in the global zone 509 * and there is a UUID associated with the global zone BE 510 */ 511 if (getzoneid() == GLOBAL_ZONEID && !uuid_is_null(dd.gz_be_uuid)) { 512 if ((ret = be_destroy_zones(bt.obe_name, bt.obe_root_ds, &dd)) 513 != BE_SUCCESS) { 514 be_print_err(gettext("be_destroy: failed to " 515 "destroy one or more zones for BE %s\n"), 516 bt.obe_name); 517 goto done; 518 } 519 } 520 521 /* Unmount the BE if it was mounted */ 522 if (zfs_is_mounted(zhp, NULL)) { 523 if ((ret = _be_unmount(bt.obe_name, BE_UNMOUNT_FLAG_FORCE)) 524 != BE_SUCCESS) { 525 be_print_err(gettext("be_destroy: " 526 "failed to unmount %s\n"), bt.obe_name); 527 ZFS_CLOSE(zhp); 528 return (ret); 529 } 530 } 531 ZFS_CLOSE(zhp); 532 533 /* Destroy this BE */ 534 if ((ret = _be_destroy((const char *)bt.obe_root_ds, &dd)) 535 != BE_SUCCESS) { 536 goto done; 537 } 538 539 /* Remove BE's entry from the boot menu */ 540 if (getzoneid() == GLOBAL_ZONEID) { 541 if ((ret = be_remove_menu(bt.obe_name, bt.obe_zpool, NULL)) 542 != BE_SUCCESS) { 543 be_print_err(gettext("be_destroy: failed to " 544 "remove BE %s from the boot menu\n"), 545 bt.obe_root_ds); 546 goto done; 547 } 548 } 549 550 done: 551 be_zfs_fini(); 552 553 return (ret); 554 } 555 556 /* 557 * Function: be_copy 558 * Description: This function makes a copy of an existing BE. If the original 559 * BE and the new BE are in the same pool, it uses zfs cloning to 560 * create the new BE, otherwise it does a physical copy. 561 * If the original BE name isn't provided, it uses the currently 562 * booted BE. If the new BE name isn't provided, it creates an 563 * auto named BE and returns that name to the caller. 564 * Parameters: 565 * be_attrs - pointer to nvlist_t of attributes being passed in. 566 * The following attributes are used by this function: 567 * 568 * BE_ATTR_ORIG_BE_NAME *optional 569 * BE_ATTR_SNAP_NAME *optional 570 * BE_ATTR_NEW_BE_NAME *optional 571 * BE_ATTR_NEW_BE_POOL *optional 572 * BE_ATTR_NEW_BE_DESC *optional 573 * BE_ATTR_ZFS_PROPERTIES *optional 574 * BE_ATTR_POLICY *optional 575 * 576 * If the BE_ATTR_NEW_BE_NAME was not passed in, upon 577 * successful BE creation, the following attribute values 578 * will be returned to the caller by setting them in the 579 * be_attrs parameter passed in: 580 * 581 * BE_ATTR_SNAP_NAME 582 * BE_ATTR_NEW_BE_NAME 583 * Return: 584 * BE_SUCCESS - Success 585 * be_errno_t - Failure 586 * Scope: 587 * Public 588 */ 589 int 590 be_copy(nvlist_t *be_attrs) 591 { 592 be_transaction_data_t bt = { 0 }; 593 be_fs_list_data_t fld = { 0 }; 594 zfs_handle_t *zhp = NULL; 595 zpool_handle_t *zphp = NULL; 596 nvlist_t *zfs_props = NULL; 597 uuid_t uu = { 0 }; 598 char obe_root_ds[MAXPATHLEN]; 599 char nbe_root_ds[MAXPATHLEN]; 600 char ss[MAXPATHLEN]; 601 char *new_mp = NULL; 602 char *obe_name = NULL; 603 boolean_t autoname = B_FALSE; 604 boolean_t be_created = B_FALSE; 605 int i; 606 int zret; 607 int ret = BE_SUCCESS; 608 struct be_defaults be_defaults; 609 610 /* Initialize libzfs handle */ 611 if (!be_zfs_init()) 612 return (BE_ERR_INIT); 613 614 /* Get original BE name */ 615 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 616 BE_ATTR_ORIG_BE_NAME, DATA_TYPE_STRING, &obe_name, NULL) != 0) { 617 be_print_err(gettext("be_copy: failed to lookup " 618 "BE_ATTR_ORIG_BE_NAME attribute\n")); 619 return (BE_ERR_INVAL); 620 } 621 622 if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) { 623 return (ret); 624 } 625 626 be_get_defaults(&be_defaults); 627 628 /* If original BE name not provided, use current BE */ 629 if (obe_name != NULL) { 630 bt.obe_name = obe_name; 631 /* Validate original BE name */ 632 if (!be_valid_be_name(bt.obe_name)) { 633 be_print_err(gettext("be_copy: " 634 "invalid BE name %s\n"), bt.obe_name); 635 return (BE_ERR_INVAL); 636 } 637 } 638 639 if (be_defaults.be_deflt_rpool_container) { 640 if ((zphp = zpool_open(g_zfs, bt.obe_zpool)) == NULL) { 641 be_print_err(gettext("be_get_node_data: failed to " 642 "open rpool (%s): %s\n"), bt.obe_zpool, 643 libzfs_error_description(g_zfs)); 644 return (zfs_err_to_be_err(g_zfs)); 645 } 646 if (be_find_zpool_callback(zphp, &bt) == 0) { 647 return (BE_ERR_BE_NOENT); 648 } 649 } else { 650 /* Find which zpool obe_name lives in */ 651 if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 652 0) { 653 be_print_err(gettext("be_copy: failed to " 654 "find zpool for BE (%s)\n"), bt.obe_name); 655 return (BE_ERR_BE_NOENT); 656 } else if (zret < 0) { 657 be_print_err(gettext("be_copy: " 658 "zpool_iter failed: %s\n"), 659 libzfs_error_description(g_zfs)); 660 return (zfs_err_to_be_err(g_zfs)); 661 } 662 } 663 664 /* Get snapshot name of original BE if one was provided */ 665 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 666 BE_ATTR_SNAP_NAME, DATA_TYPE_STRING, &bt.obe_snap_name, NULL) 667 != 0) { 668 be_print_err(gettext("be_copy: failed to lookup " 669 "BE_ATTR_SNAP_NAME attribute\n")); 670 return (BE_ERR_INVAL); 671 } 672 673 /* Get new BE name */ 674 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 675 BE_ATTR_NEW_BE_NAME, DATA_TYPE_STRING, &bt.nbe_name, NULL) 676 != 0) { 677 be_print_err(gettext("be_copy: failed to lookup " 678 "BE_ATTR_NEW_BE_NAME attribute\n")); 679 return (BE_ERR_INVAL); 680 } 681 682 /* Get zpool name to create new BE in */ 683 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 684 BE_ATTR_NEW_BE_POOL, DATA_TYPE_STRING, &bt.nbe_zpool, NULL) != 0) { 685 be_print_err(gettext("be_copy: failed to lookup " 686 "BE_ATTR_NEW_BE_POOL attribute\n")); 687 return (BE_ERR_INVAL); 688 } 689 690 /* Get new BE's description if one was provided */ 691 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 692 BE_ATTR_NEW_BE_DESC, DATA_TYPE_STRING, &bt.nbe_desc, NULL) != 0) { 693 be_print_err(gettext("be_copy: failed to lookup " 694 "BE_ATTR_NEW_BE_DESC attribute\n")); 695 return (BE_ERR_INVAL); 696 } 697 698 /* Get BE policy to create this snapshot under */ 699 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 700 BE_ATTR_POLICY, DATA_TYPE_STRING, &bt.policy, NULL) != 0) { 701 be_print_err(gettext("be_copy: failed to lookup " 702 "BE_ATTR_POLICY attribute\n")); 703 return (BE_ERR_INVAL); 704 } 705 706 /* 707 * Create property list for new BE root dataset. If some 708 * zfs properties were already provided by the caller, dup 709 * that list. Otherwise initialize a new property list. 710 */ 711 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 712 BE_ATTR_ZFS_PROPERTIES, DATA_TYPE_NVLIST, &zfs_props, NULL) 713 != 0) { 714 be_print_err(gettext("be_copy: failed to lookup " 715 "BE_ATTR_ZFS_PROPERTIES attribute\n")); 716 return (BE_ERR_INVAL); 717 } 718 if (zfs_props != NULL) { 719 /* Make sure its a unique nvlist */ 720 if (!(zfs_props->nvl_nvflag & NV_UNIQUE_NAME) && 721 !(zfs_props->nvl_nvflag & NV_UNIQUE_NAME_TYPE)) { 722 be_print_err(gettext("be_copy: ZFS property list " 723 "not unique\n")); 724 return (BE_ERR_INVAL); 725 } 726 727 /* Dup the list */ 728 if (nvlist_dup(zfs_props, &bt.nbe_zfs_props, 0) != 0) { 729 be_print_err(gettext("be_copy: " 730 "failed to dup ZFS property list\n")); 731 return (BE_ERR_NOMEM); 732 } 733 } else { 734 /* Initialize new nvlist */ 735 if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) { 736 be_print_err(gettext("be_copy: internal " 737 "error: out of memory\n")); 738 return (BE_ERR_NOMEM); 739 } 740 } 741 742 /* 743 * If new BE name provided, validate the BE name and then verify 744 * that new BE name doesn't already exist in some pool. 745 */ 746 if (bt.nbe_name) { 747 /* Validate original BE name */ 748 if (!be_valid_be_name(bt.nbe_name)) { 749 be_print_err(gettext("be_copy: " 750 "invalid BE name %s\n"), bt.nbe_name); 751 ret = BE_ERR_INVAL; 752 goto done; 753 } 754 755 /* Verify it doesn't already exist */ 756 if ((zret = zpool_iter(g_zfs, be_exists_callback, bt.nbe_name)) 757 > 0) { 758 be_print_err(gettext("be_copy: BE (%s) already " 759 "exists\n"), bt.nbe_name); 760 ret = BE_ERR_BE_EXISTS; 761 goto done; 762 } else if (zret < 0) { 763 be_print_err(gettext("be_copy: zpool_iter failed: " 764 "%s\n"), libzfs_error_description(g_zfs)); 765 ret = zfs_err_to_be_err(g_zfs); 766 goto done; 767 } 768 } else { 769 /* 770 * If an auto named BE is desired, it must be in the same 771 * pool is the original BE. 772 */ 773 if (bt.nbe_zpool != NULL) { 774 be_print_err(gettext("be_copy: cannot specify pool " 775 "name when creating an auto named BE\n")); 776 ret = BE_ERR_INVAL; 777 goto done; 778 } 779 780 /* 781 * Generate auto named BE 782 */ 783 if ((bt.nbe_name = be_auto_be_name(bt.obe_name)) 784 == NULL) { 785 be_print_err(gettext("be_copy: " 786 "failed to generate auto BE name\n")); 787 ret = BE_ERR_AUTONAME; 788 goto done; 789 } 790 791 autoname = B_TRUE; 792 } 793 794 /* 795 * If zpool name to create new BE in is not provided, 796 * create new BE in original BE's pool. 797 */ 798 if (bt.nbe_zpool == NULL) { 799 bt.nbe_zpool = bt.obe_zpool; 800 } 801 802 /* Get root dataset names for obe_name and nbe_name */ 803 be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds, 804 sizeof (obe_root_ds)); 805 be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds, 806 sizeof (nbe_root_ds)); 807 808 bt.obe_root_ds = obe_root_ds; 809 bt.nbe_root_ds = nbe_root_ds; 810 811 /* 812 * If an existing snapshot name has been provided to create from, 813 * verify that it exists for the original BE's root dataset. 814 */ 815 if (bt.obe_snap_name != NULL) { 816 817 /* Generate dataset name for snapshot to use. */ 818 (void) snprintf(ss, sizeof (ss), "%s@%s", bt.obe_root_ds, 819 bt.obe_snap_name); 820 821 /* Verify snapshot exists */ 822 if (!zfs_dataset_exists(g_zfs, ss, ZFS_TYPE_SNAPSHOT)) { 823 be_print_err(gettext("be_copy: " 824 "snapshot does not exist (%s): %s\n"), ss, 825 libzfs_error_description(g_zfs)); 826 ret = BE_ERR_SS_NOENT; 827 goto done; 828 } 829 } else { 830 /* 831 * Else snapshot name was not provided, generate an 832 * auto named snapshot to use as its origin. 833 */ 834 if ((ret = _be_create_snapshot(bt.obe_name, 835 &bt.obe_snap_name, bt.policy)) != BE_SUCCESS) { 836 be_print_err(gettext("be_copy: " 837 "failed to create auto named snapshot\n")); 838 goto done; 839 } 840 841 if (nvlist_add_string(be_attrs, BE_ATTR_SNAP_NAME, 842 bt.obe_snap_name) != 0) { 843 be_print_err(gettext("be_copy: " 844 "failed to add snap name to be_attrs\n")); 845 ret = BE_ERR_NOMEM; 846 goto done; 847 } 848 } 849 850 /* Get handle to original BE's root dataset. */ 851 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM)) 852 == NULL) { 853 be_print_err(gettext("be_copy: failed to " 854 "open BE root dataset (%s): %s\n"), bt.obe_root_ds, 855 libzfs_error_description(g_zfs)); 856 ret = zfs_err_to_be_err(g_zfs); 857 goto done; 858 } 859 860 /* If original BE is currently mounted, record its altroot. */ 861 if (zfs_is_mounted(zhp, &bt.obe_altroot) && bt.obe_altroot == NULL) { 862 be_print_err(gettext("be_copy: failed to " 863 "get altroot of mounted BE %s: %s\n"), 864 bt.obe_name, libzfs_error_description(g_zfs)); 865 ret = zfs_err_to_be_err(g_zfs); 866 goto done; 867 } 868 869 if (strcmp(bt.obe_zpool, bt.nbe_zpool) == 0) { 870 871 /* Do clone */ 872 873 /* 874 * Iterate through original BE's datasets and clone 875 * them to create new BE. This call will end up closing 876 * the zfs handle passed in whether it succeeds for fails. 877 */ 878 if ((ret = be_clone_fs_callback(zhp, &bt)) != 0) { 879 zhp = NULL; 880 /* Creating clone BE failed */ 881 if (!autoname || ret != BE_ERR_BE_EXISTS) { 882 be_print_err(gettext("be_copy: " 883 "failed to clone new BE (%s) from " 884 "orig BE (%s)\n"), 885 bt.nbe_name, bt.obe_name); 886 ret = BE_ERR_CLONE; 887 goto done; 888 } 889 890 /* 891 * We failed to create the new BE because a BE with 892 * the auto-name we generated above has since come 893 * into existence. Regenerate a new auto-name 894 * and retry. 895 */ 896 for (i = 1; i < BE_AUTO_NAME_MAX_TRY; i++) { 897 898 /* Sleep 1 before retrying */ 899 (void) sleep(1); 900 901 /* Generate new auto BE name */ 902 free(bt.nbe_name); 903 if ((bt.nbe_name = be_auto_be_name(bt.obe_name)) 904 == NULL) { 905 be_print_err(gettext("be_copy: " 906 "failed to generate auto " 907 "BE name\n")); 908 ret = BE_ERR_AUTONAME; 909 goto done; 910 } 911 912 /* 913 * Regenerate string for new BE's 914 * root dataset name 915 */ 916 be_make_root_ds(bt.nbe_zpool, bt.nbe_name, 917 nbe_root_ds, sizeof (nbe_root_ds)); 918 bt.nbe_root_ds = nbe_root_ds; 919 920 /* 921 * Get handle to original BE's root dataset. 922 */ 923 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, 924 ZFS_TYPE_FILESYSTEM)) == NULL) { 925 be_print_err(gettext("be_copy: " 926 "failed to open BE root dataset " 927 "(%s): %s\n"), bt.obe_root_ds, 928 libzfs_error_description(g_zfs)); 929 ret = zfs_err_to_be_err(g_zfs); 930 goto done; 931 } 932 933 /* 934 * Try to clone the BE again. This 935 * call will end up closing the zfs 936 * handle passed in whether it 937 * succeeds or fails. 938 */ 939 ret = be_clone_fs_callback(zhp, &bt); 940 zhp = NULL; 941 if (ret == 0) { 942 break; 943 } else if (ret != BE_ERR_BE_EXISTS) { 944 be_print_err(gettext("be_copy: " 945 "failed to clone new BE " 946 "(%s) from orig BE (%s)\n"), 947 bt.nbe_name, bt.obe_name); 948 ret = BE_ERR_CLONE; 949 goto done; 950 } 951 } 952 953 /* 954 * If we've exhausted the maximum number of 955 * tries, free the auto BE name and return 956 * error. 957 */ 958 if (i == BE_AUTO_NAME_MAX_TRY) { 959 be_print_err(gettext("be_copy: failed " 960 "to create unique auto BE name\n")); 961 free(bt.nbe_name); 962 bt.nbe_name = NULL; 963 ret = BE_ERR_AUTONAME; 964 goto done; 965 } 966 } 967 zhp = NULL; 968 969 } else { 970 971 /* Do copy (i.e. send BE datasets via zfs_send/recv) */ 972 973 /* 974 * Verify BE container dataset in nbe_zpool exists. 975 * If not, create it. 976 */ 977 if (!be_create_container_ds(bt.nbe_zpool)) { 978 ret = BE_ERR_CREATDS; 979 goto done; 980 } 981 982 /* 983 * Iterate through original BE's datasets and send 984 * them to the other pool. This call will end up closing 985 * the zfs handle passed in whether it succeeds or fails. 986 */ 987 if ((ret = be_send_fs_callback(zhp, &bt)) != 0) { 988 be_print_err(gettext("be_copy: failed to " 989 "send BE (%s) to pool (%s)\n"), bt.obe_name, 990 bt.nbe_zpool); 991 ret = BE_ERR_COPY; 992 zhp = NULL; 993 goto done; 994 } 995 zhp = NULL; 996 } 997 998 /* 999 * Set flag to note that the dataset(s) for the new BE have been 1000 * successfully created so that if a failure happens from this point 1001 * on, we know to cleanup these datasets. 1002 */ 1003 be_created = B_TRUE; 1004 1005 /* 1006 * Validate that the new BE is mountable. 1007 * Do not attempt to mount non-global zone datasets 1008 * since they are not cloned yet. 1009 */ 1010 if ((ret = _be_mount(bt.nbe_name, &new_mp, BE_MOUNT_FLAG_NO_ZONES)) 1011 != BE_SUCCESS) { 1012 be_print_err(gettext("be_copy: failed to " 1013 "mount newly created BE\n")); 1014 (void) _be_unmount(bt.nbe_name, 0); 1015 goto done; 1016 } 1017 1018 /* Set UUID for new BE */ 1019 if (be_set_uuid(bt.nbe_root_ds) != BE_SUCCESS) { 1020 be_print_err(gettext("be_copy: failed to " 1021 "set uuid for new BE\n")); 1022 } 1023 1024 /* 1025 * Process zones outside of the private BE namespace. 1026 * This has to be done here because we need the uuid set in the 1027 * root dataset of the new BE. The uuid is use to set the parentbe 1028 * property for the new zones datasets. 1029 */ 1030 if (getzoneid() == GLOBAL_ZONEID && 1031 be_get_uuid(bt.obe_root_ds, &uu) == BE_SUCCESS) { 1032 if ((ret = be_copy_zones(bt.obe_name, bt.obe_root_ds, 1033 bt.nbe_root_ds)) != BE_SUCCESS) { 1034 be_print_err(gettext("be_copy: failed to process " 1035 "zones\n")); 1036 goto done; 1037 } 1038 } 1039 1040 /* 1041 * Generate a list of file systems from the original BE that are 1042 * legacy mounted. We use this list to determine which entries in 1043 * vfstab we need to update for the new BE we've just created. 1044 */ 1045 if ((ret = be_get_legacy_fs(bt.obe_name, bt.obe_root_ds, NULL, NULL, 1046 &fld)) != BE_SUCCESS) { 1047 be_print_err(gettext("be_copy: failed to " 1048 "get legacy mounted file system list for %s\n"), 1049 bt.obe_name); 1050 goto done; 1051 } 1052 1053 /* 1054 * Update new BE's vfstab. 1055 */ 1056 if ((ret = be_update_vfstab(bt.nbe_name, bt.obe_zpool, bt.nbe_zpool, 1057 &fld, new_mp)) != BE_SUCCESS) { 1058 be_print_err(gettext("be_copy: failed to " 1059 "update new BE's vfstab (%s)\n"), bt.nbe_name); 1060 goto done; 1061 } 1062 1063 /* Unmount the new BE */ 1064 if ((ret = _be_unmount(bt.nbe_name, 0)) != BE_SUCCESS) { 1065 be_print_err(gettext("be_copy: failed to " 1066 "unmount newly created BE\n")); 1067 goto done; 1068 } 1069 1070 /* 1071 * Add boot menu entry for newly created clone 1072 */ 1073 if (getzoneid() == GLOBAL_ZONEID && 1074 (ret = be_append_menu(bt.nbe_name, bt.nbe_zpool, 1075 NULL, bt.obe_root_ds, bt.nbe_desc)) != BE_SUCCESS) { 1076 be_print_err(gettext("be_copy: failed to " 1077 "add BE (%s) to boot menu\n"), bt.nbe_name); 1078 goto done; 1079 } 1080 1081 /* 1082 * If we succeeded in creating an auto named BE, set its policy 1083 * type and return the auto generated name to the caller by storing 1084 * it in the nvlist passed in by the caller. 1085 */ 1086 if (autoname) { 1087 /* Get handle to new BE's root dataset. */ 1088 if ((zhp = zfs_open(g_zfs, bt.nbe_root_ds, 1089 ZFS_TYPE_FILESYSTEM)) == NULL) { 1090 be_print_err(gettext("be_copy: failed to " 1091 "open BE root dataset (%s): %s\n"), bt.nbe_root_ds, 1092 libzfs_error_description(g_zfs)); 1093 ret = zfs_err_to_be_err(g_zfs); 1094 goto done; 1095 } 1096 1097 /* 1098 * Set the policy type property into the new BE's root dataset 1099 */ 1100 if (bt.policy == NULL) { 1101 /* If no policy type provided, use default type */ 1102 bt.policy = be_default_policy(); 1103 } 1104 1105 if (zfs_prop_set(zhp, BE_POLICY_PROPERTY, bt.policy) != 0) { 1106 be_print_err(gettext("be_copy: failed to " 1107 "set BE policy for %s: %s\n"), bt.nbe_name, 1108 libzfs_error_description(g_zfs)); 1109 ret = zfs_err_to_be_err(g_zfs); 1110 goto done; 1111 } 1112 1113 /* 1114 * Return the auto generated name to the caller 1115 */ 1116 if (bt.nbe_name) { 1117 if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_NAME, 1118 bt.nbe_name) != 0) { 1119 be_print_err(gettext("be_copy: failed to " 1120 "add snap name to be_attrs\n")); 1121 } 1122 } 1123 } 1124 1125 done: 1126 ZFS_CLOSE(zhp); 1127 be_free_fs_list(&fld); 1128 1129 if (bt.nbe_zfs_props != NULL) 1130 nvlist_free(bt.nbe_zfs_props); 1131 1132 free(bt.obe_altroot); 1133 free(new_mp); 1134 1135 /* 1136 * If a failure occurred and we already created the datasets for 1137 * the new boot environment, destroy them. 1138 */ 1139 if (ret != BE_SUCCESS && be_created) { 1140 be_destroy_data_t cdd = { 0 }; 1141 1142 cdd.force_unmount = B_TRUE; 1143 1144 be_print_err(gettext("be_copy: " 1145 "destroying partially created boot environment\n")); 1146 1147 if (getzoneid() == GLOBAL_ZONEID && be_get_uuid(bt.nbe_root_ds, 1148 &cdd.gz_be_uuid) == 0) 1149 (void) be_destroy_zones(bt.nbe_name, bt.nbe_root_ds, 1150 &cdd); 1151 1152 (void) _be_destroy(bt.nbe_root_ds, &cdd); 1153 } 1154 1155 be_zfs_fini(); 1156 1157 return (ret); 1158 } 1159 1160 /* ******************************************************************** */ 1161 /* Semi-Private Functions */ 1162 /* ******************************************************************** */ 1163 1164 /* 1165 * Function: be_find_zpool_callback 1166 * Description: Callback function used to find the pool that a BE lives in. 1167 * Parameters: 1168 * zlp - zpool_handle_t pointer for the current pool being 1169 * looked at. 1170 * data - be_transaction_data_t pointer providing information 1171 * about the BE that's being searched for. 1172 * This function uses the obe_name member of this 1173 * parameter to use as the BE name to search for. 1174 * Upon successfully locating the BE, it populates 1175 * obe_zpool with the pool name that the BE is found in. 1176 * Returns: 1177 * 1 - BE exists in this pool. 1178 * 0 - BE does not exist in this pool. 1179 * Scope: 1180 * Semi-private (library wide use only) 1181 */ 1182 int 1183 be_find_zpool_callback(zpool_handle_t *zlp, void *data) 1184 { 1185 be_transaction_data_t *bt = data; 1186 const char *zpool = zpool_get_name(zlp); 1187 char be_root_ds[MAXPATHLEN]; 1188 1189 /* 1190 * Generate string for the BE's root dataset 1191 */ 1192 be_make_root_ds(zpool, bt->obe_name, be_root_ds, sizeof (be_root_ds)); 1193 1194 /* 1195 * Check if dataset exists 1196 */ 1197 if (zfs_dataset_exists(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) { 1198 /* BE's root dataset exists in zpool */ 1199 bt->obe_zpool = strdup(zpool); 1200 zpool_close(zlp); 1201 return (1); 1202 } 1203 1204 zpool_close(zlp); 1205 return (0); 1206 } 1207 1208 /* 1209 * Function: be_exists_callback 1210 * Description: Callback function used to find out if a BE exists. 1211 * Parameters: 1212 * zlp - zpool_handle_t pointer to the current pool being 1213 * looked at. 1214 * data - BE name to look for. 1215 * Return: 1216 * 1 - BE exists in this pool. 1217 * 0 - BE does not exist in this pool. 1218 * Scope: 1219 * Semi-private (library wide use only) 1220 */ 1221 int 1222 be_exists_callback(zpool_handle_t *zlp, void *data) 1223 { 1224 const char *zpool = zpool_get_name(zlp); 1225 char *be_name = data; 1226 char be_root_ds[MAXPATHLEN]; 1227 1228 /* 1229 * Generate string for the BE's root dataset 1230 */ 1231 be_make_root_ds(zpool, be_name, be_root_ds, sizeof (be_root_ds)); 1232 1233 /* 1234 * Check if dataset exists 1235 */ 1236 if (zfs_dataset_exists(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) { 1237 /* BE's root dataset exists in zpool */ 1238 zpool_close(zlp); 1239 return (1); 1240 } 1241 1242 zpool_close(zlp); 1243 return (0); 1244 } 1245 1246 /* 1247 * Function: be_has_snapshots_callback 1248 * Description: Callback function used to find out if a BE has snapshots. 1249 * Parameters: 1250 * zlp - zpool_handle_t pointer to the current pool being 1251 * looked at. 1252 * data - be_snap_found_t pointer. 1253 * Return: 1254 * 1 - BE has no snapshots. 1255 * 0 - BE has snapshots. 1256 * Scope: 1257 * Private 1258 */ 1259 static int 1260 be_has_snapshot_callback(zfs_handle_t *zhp, void *data) 1261 { 1262 boolean_t *bs = data; 1263 if (zfs_get_name(zhp) == NULL) { 1264 zfs_close(zhp); 1265 return (1); 1266 } 1267 *bs = B_TRUE; 1268 zfs_close(zhp); 1269 return (0); 1270 } 1271 1272 /* 1273 * Function: be_set_uuid 1274 * Description: This function generates a uuid, unparses it into 1275 * string representation, and sets that string into 1276 * a zfs user property for a root dataset of a BE. 1277 * The name of the user property used to store the 1278 * uuid is org.opensolaris.libbe:uuid 1279 * 1280 * Parameters: 1281 * root_ds - Root dataset of the BE to set a uuid on. 1282 * Return: 1283 * be_errno_t - Failure 1284 * BE_SUCCESS - Success 1285 * Scope: 1286 * Semi-private (library wide ues only) 1287 */ 1288 int 1289 be_set_uuid(char *root_ds) 1290 { 1291 zfs_handle_t *zhp = NULL; 1292 uuid_t uu = { 0 }; 1293 char uu_string[UUID_PRINTABLE_STRING_LENGTH] = { 0 }; 1294 int ret = BE_SUCCESS; 1295 1296 /* Generate a UUID and unparse it into string form */ 1297 uuid_generate(uu); 1298 if (uuid_is_null(uu) != 0) { 1299 be_print_err(gettext("be_set_uuid: failed to " 1300 "generate uuid\n")); 1301 return (BE_ERR_GEN_UUID); 1302 } 1303 uuid_unparse(uu, uu_string); 1304 1305 /* Get handle to the BE's root dataset. */ 1306 if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) { 1307 be_print_err(gettext("be_set_uuid: failed to " 1308 "open BE root dataset (%s): %s\n"), root_ds, 1309 libzfs_error_description(g_zfs)); 1310 return (zfs_err_to_be_err(g_zfs)); 1311 } 1312 1313 /* Set uuid property for the BE */ 1314 if (zfs_prop_set(zhp, BE_UUID_PROPERTY, uu_string) != 0) { 1315 be_print_err(gettext("be_set_uuid: failed to " 1316 "set uuid property for BE: %s\n"), 1317 libzfs_error_description(g_zfs)); 1318 ret = zfs_err_to_be_err(g_zfs); 1319 } 1320 1321 ZFS_CLOSE(zhp); 1322 1323 return (ret); 1324 } 1325 1326 /* 1327 * Function: be_get_uuid 1328 * Description: This function gets the uuid string from a BE root 1329 * dataset, parses it into internal format, and returns 1330 * it the caller via a reference pointer passed in. 1331 * 1332 * Parameters: 1333 * rootds - Root dataset of the BE to get the uuid from. 1334 * uu - reference pointer to a uuid_t to return uuid in. 1335 * Return: 1336 * be_errno_t - Failure 1337 * BE_SUCCESS - Success 1338 * Scope: 1339 * Semi-private (library wide use only) 1340 */ 1341 int 1342 be_get_uuid(const char *root_ds, uuid_t *uu) 1343 { 1344 zfs_handle_t *zhp = NULL; 1345 nvlist_t *userprops = NULL; 1346 nvlist_t *propname = NULL; 1347 char *uu_string = NULL; 1348 int ret = BE_SUCCESS; 1349 1350 /* Get handle to the BE's root dataset. */ 1351 if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) { 1352 be_print_err(gettext("be_get_uuid: failed to " 1353 "open BE root dataset (%s): %s\n"), root_ds, 1354 libzfs_error_description(g_zfs)); 1355 return (zfs_err_to_be_err(g_zfs)); 1356 } 1357 1358 /* Get user properties for BE's root dataset */ 1359 if ((userprops = zfs_get_user_props(zhp)) == NULL) { 1360 be_print_err(gettext("be_get_uuid: failed to " 1361 "get user properties for BE root dataset (%s): %s\n"), 1362 root_ds, libzfs_error_description(g_zfs)); 1363 ret = zfs_err_to_be_err(g_zfs); 1364 goto done; 1365 } 1366 1367 /* Get UUID string from BE's root dataset user properties */ 1368 if (nvlist_lookup_nvlist(userprops, BE_UUID_PROPERTY, &propname) != 0 || 1369 nvlist_lookup_string(propname, ZPROP_VALUE, &uu_string) != 0) { 1370 /* 1371 * This probably just means that the BE is simply too old 1372 * to have a uuid or that we haven't created a uuid for 1373 * this BE yet. 1374 */ 1375 be_print_err(gettext("be_get_uuid: failed to " 1376 "get uuid property from BE root dataset user " 1377 "properties.\n")); 1378 ret = BE_ERR_NO_UUID; 1379 goto done; 1380 } 1381 /* Parse uuid string into internal format */ 1382 if (uuid_parse(uu_string, *uu) != 0 || uuid_is_null(*uu)) { 1383 be_print_err(gettext("be_get_uuid: failed to " 1384 "parse uuid\n")); 1385 ret = BE_ERR_PARSE_UUID; 1386 goto done; 1387 } 1388 1389 done: 1390 ZFS_CLOSE(zhp); 1391 return (ret); 1392 } 1393 1394 /* ******************************************************************** */ 1395 /* Private Functions */ 1396 /* ******************************************************************** */ 1397 1398 /* 1399 * Function: _be_destroy 1400 * Description: Destroy a BE and all of its children datasets and snapshots. 1401 * This function is called for both global BEs and non-global BEs. 1402 * The root dataset of either the global BE or non-global BE to be 1403 * destroyed is passed in. 1404 * Parameters: 1405 * root_ds - pointer to the name of the root dataset of the 1406 * BE to destroy. 1407 * dd - pointer to a be_destroy_data_t structure. 1408 * 1409 * Return: 1410 * BE_SUCCESS - Success 1411 * be_errno_t - Failure 1412 * Scope: 1413 * Private 1414 */ 1415 static int 1416 _be_destroy(const char *root_ds, be_destroy_data_t *dd) 1417 { 1418 zfs_handle_t *zhp = NULL; 1419 char origin[MAXPATHLEN]; 1420 char parent[MAXPATHLEN]; 1421 char *snap = NULL; 1422 boolean_t has_origin = B_FALSE; 1423 int ret = BE_SUCCESS; 1424 1425 /* Get handle to BE's root dataset */ 1426 if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == 1427 NULL) { 1428 be_print_err(gettext("be_destroy: failed to " 1429 "open BE root dataset (%s): %s\n"), root_ds, 1430 libzfs_error_description(g_zfs)); 1431 return (zfs_err_to_be_err(g_zfs)); 1432 } 1433 1434 /* 1435 * Demote this BE in case it has dependent clones. This call 1436 * will end up closing the zfs handle passed in whether it 1437 * succeeds or fails. 1438 */ 1439 if (be_demote_callback(zhp, NULL) != 0) { 1440 be_print_err(gettext("be_destroy: " 1441 "failed to demote BE %s\n"), root_ds); 1442 return (BE_ERR_DEMOTE); 1443 } 1444 1445 /* Get handle to BE's root dataset */ 1446 if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == 1447 NULL) { 1448 be_print_err(gettext("be_destroy: failed to " 1449 "open BE root dataset (%s): %s\n"), root_ds, 1450 libzfs_error_description(g_zfs)); 1451 return (zfs_err_to_be_err(g_zfs)); 1452 } 1453 1454 /* 1455 * Get the origin of this BE's root dataset. This will be used 1456 * later to destroy the snapshots originally used to create this BE. 1457 */ 1458 if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL, 1459 NULL, 0, B_FALSE) == 0) { 1460 (void) strlcpy(parent, origin, sizeof (parent)); 1461 if (be_get_snap(parent, &snap) != BE_SUCCESS) { 1462 ZFS_CLOSE(zhp); 1463 be_print_err(gettext("be_destroy: failed to " 1464 "get snapshot name from origin %s\n"), origin); 1465 return (BE_ERR_INVAL); 1466 } 1467 has_origin = B_TRUE; 1468 } 1469 1470 /* 1471 * Destroy the BE's root and its hierarchical children. This call 1472 * will end up closing the zfs handle passed in whether it succeeds 1473 * or fails. 1474 */ 1475 if (be_destroy_callback(zhp, dd) != 0) { 1476 be_print_err(gettext("be_destroy: failed to " 1477 "destroy BE %s\n"), root_ds); 1478 ret = zfs_err_to_be_err(g_zfs); 1479 return (ret); 1480 } 1481 1482 /* If BE has an origin */ 1483 if (has_origin) { 1484 1485 /* 1486 * If origin snapshot doesn't have any other 1487 * dependents, delete the origin. 1488 */ 1489 if ((zhp = zfs_open(g_zfs, origin, ZFS_TYPE_SNAPSHOT)) == 1490 NULL) { 1491 be_print_err(gettext("be_destroy: failed to " 1492 "open BE's origin (%s): %s\n"), origin, 1493 libzfs_error_description(g_zfs)); 1494 ret = zfs_err_to_be_err(g_zfs); 1495 return (ret); 1496 } 1497 1498 /* If origin has dependents, don't delete it. */ 1499 if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) != 0) { 1500 ZFS_CLOSE(zhp); 1501 return (ret); 1502 } 1503 ZFS_CLOSE(zhp); 1504 1505 /* Get handle to BE's parent's root dataset */ 1506 if ((zhp = zfs_open(g_zfs, parent, ZFS_TYPE_FILESYSTEM)) == 1507 NULL) { 1508 be_print_err(gettext("be_destroy: failed to " 1509 "open BE's parent root dataset (%s): %s\n"), parent, 1510 libzfs_error_description(g_zfs)); 1511 ret = zfs_err_to_be_err(g_zfs); 1512 return (ret); 1513 } 1514 1515 /* Destroy the snapshot origin used to create this BE. */ 1516 /* 1517 * The boolean set to B_FALSE and passed to zfs_destroy_snaps() 1518 * tells zfs to process and destroy the snapshots now. 1519 * Otherwise the call will potentially return where the 1520 * snapshot isn't actually destroyed yet, and ZFS is waiting 1521 * until all the references to the snapshot have been 1522 * released before actually destroying the snapshot. 1523 */ 1524 if (zfs_destroy_snaps(zhp, snap, B_FALSE) != 0) { 1525 be_print_err(gettext("be_destroy: failed to " 1526 "destroy original snapshots used to create " 1527 "BE: %s\n"), libzfs_error_description(g_zfs)); 1528 1529 /* 1530 * If a failure happened because a clone exists, 1531 * don't return a failure to the user. Above, we're 1532 * only checking that the root dataset's origin 1533 * snapshot doesn't have dependent clones, but its 1534 * possible that a subordinate dataset origin snapshot 1535 * has a clone. We really need to check for that 1536 * before trying to destroy the origin snapshot. 1537 */ 1538 if (libzfs_errno(g_zfs) != EZFS_EXISTS) { 1539 ret = zfs_err_to_be_err(g_zfs); 1540 ZFS_CLOSE(zhp); 1541 return (ret); 1542 } 1543 } 1544 ZFS_CLOSE(zhp); 1545 } 1546 1547 return (ret); 1548 } 1549 1550 /* 1551 * Function: be_destroy_zones 1552 * Description: Find valid zone's and call be_destroy_zone_roots to destroy its 1553 * corresponding dataset and all of its children datasets 1554 * and snapshots. 1555 * Parameters: 1556 * be_name - name of global boot environment being destroyed 1557 * be_root_ds - root dataset of global boot environment being 1558 * destroyed. 1559 * dd - be_destroy_data_t pointer 1560 * Return: 1561 * BE_SUCCESS - Success 1562 * be_errno_t - Failure 1563 * Scope: 1564 * Private 1565 * 1566 * NOTES - Requires that the BE being deleted has no dependent BEs. If it 1567 * does, the destroy will fail. 1568 */ 1569 static int 1570 be_destroy_zones(char *be_name, char *be_root_ds, be_destroy_data_t *dd) 1571 { 1572 int i; 1573 int ret = BE_SUCCESS; 1574 int force_umnt = BE_UNMOUNT_FLAG_NULL; 1575 char *zonepath = NULL; 1576 char *zonename = NULL; 1577 char *zonepath_ds = NULL; 1578 char *mp = NULL; 1579 zoneList_t zlist = NULL; 1580 zoneBrandList_t *brands = NULL; 1581 zfs_handle_t *zhp = NULL; 1582 1583 /* If zones are not implemented, then get out. */ 1584 if (!z_zones_are_implemented()) { 1585 return (BE_SUCCESS); 1586 } 1587 1588 /* Get list of supported brands */ 1589 if ((brands = be_get_supported_brandlist()) == NULL) { 1590 be_print_err(gettext("be_destroy_zones: " 1591 "no supported brands\n")); 1592 return (BE_SUCCESS); 1593 } 1594 1595 /* Get handle to BE's root dataset */ 1596 if ((zhp = zfs_open(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) == 1597 NULL) { 1598 be_print_err(gettext("be_destroy_zones: failed to " 1599 "open BE root dataset (%s): %s\n"), be_root_ds, 1600 libzfs_error_description(g_zfs)); 1601 z_free_brand_list(brands); 1602 return (zfs_err_to_be_err(g_zfs)); 1603 } 1604 1605 /* 1606 * If the global BE is not mounted, we must mount it here to 1607 * gather data about the non-global zones in it. 1608 */ 1609 if (!zfs_is_mounted(zhp, &mp)) { 1610 if ((ret = _be_mount(be_name, &mp, 1611 BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) { 1612 be_print_err(gettext("be_destroy_zones: failed to " 1613 "mount the BE (%s) for zones processing.\n"), 1614 be_name); 1615 ZFS_CLOSE(zhp); 1616 z_free_brand_list(brands); 1617 return (ret); 1618 } 1619 } 1620 ZFS_CLOSE(zhp); 1621 1622 z_set_zone_root(mp); 1623 free(mp); 1624 1625 /* Get list of supported zones. */ 1626 if ((zlist = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) { 1627 z_free_brand_list(brands); 1628 return (BE_SUCCESS); 1629 } 1630 1631 /* Unmount the BE before destroying the zones in it. */ 1632 if (dd->force_unmount) 1633 force_umnt = BE_UNMOUNT_FLAG_FORCE; 1634 if ((ret = _be_unmount(be_name, force_umnt)) != BE_SUCCESS) { 1635 be_print_err(gettext("be_destroy_zones: failed to " 1636 "unmount the BE (%s)\n"), be_name); 1637 goto done; 1638 } 1639 1640 /* Iterate through the zones and destroy them. */ 1641 for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) { 1642 1643 /* Skip zones that aren't at least installed */ 1644 if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED) 1645 continue; 1646 1647 zonepath = z_zlist_get_zonepath(zlist, i); 1648 1649 /* 1650 * Get the dataset of this zonepath. If its not 1651 * a dataset, skip it. 1652 */ 1653 if ((zonepath_ds = be_get_ds_from_dir(zonepath)) == NULL) 1654 continue; 1655 1656 /* 1657 * Check if this zone is supported based on the 1658 * dataset of its zonepath. 1659 */ 1660 if (!be_zone_supported(zonepath_ds)) { 1661 free(zonepath_ds); 1662 continue; 1663 } 1664 1665 /* Find the zone BE root datasets for this zone. */ 1666 if ((ret = be_destroy_zone_roots(zonepath_ds, dd)) 1667 != BE_SUCCESS) { 1668 be_print_err(gettext("be_destroy_zones: failed to " 1669 "find and destroy zone roots for zone %s\n"), 1670 zonename); 1671 free(zonepath_ds); 1672 goto done; 1673 } 1674 free(zonepath_ds); 1675 } 1676 1677 done: 1678 z_free_brand_list(brands); 1679 z_free_zone_list(zlist); 1680 1681 return (ret); 1682 } 1683 1684 /* 1685 * Function: be_destroy_zone_roots 1686 * Description: This function will open the zone's root container dataset 1687 * and iterate the datasets within, looking for roots that 1688 * belong to the given global BE and destroying them. 1689 * If no other zone roots remain in the zone's root container 1690 * dataset, the function will destroy it and the zone's 1691 * zonepath dataset as well. 1692 * Parameters: 1693 * zonepath_ds - pointer to zone's zonepath dataset. 1694 * dd - pointer to a linked destroy data. 1695 * Returns: 1696 * BE_SUCCESS - Success 1697 * be_errno_t - Failure 1698 * Scope: 1699 * Private 1700 */ 1701 static int 1702 be_destroy_zone_roots(char *zonepath_ds, be_destroy_data_t *dd) 1703 { 1704 zfs_handle_t *zhp; 1705 char zone_container_ds[MAXPATHLEN]; 1706 int ret = BE_SUCCESS; 1707 1708 /* Generate string for the root container dataset for this zone. */ 1709 be_make_container_ds(zonepath_ds, zone_container_ds, 1710 sizeof (zone_container_ds)); 1711 1712 /* Get handle to this zone's root container dataset. */ 1713 if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM)) 1714 == NULL) { 1715 be_print_err(gettext("be_destroy_zone_roots: failed to " 1716 "open zone root container dataset (%s): %s\n"), 1717 zone_container_ds, libzfs_error_description(g_zfs)); 1718 return (zfs_err_to_be_err(g_zfs)); 1719 } 1720 1721 /* 1722 * Iterate through all of this zone's BEs, destroying the ones 1723 * that belong to the parent global BE. 1724 */ 1725 if ((ret = zfs_iter_filesystems(zhp, be_destroy_zone_roots_callback, 1726 dd)) != 0) { 1727 be_print_err(gettext("be_destroy_zone_roots: failed to " 1728 "destroy zone roots under zonepath dataset %s: %s\n"), 1729 zonepath_ds, libzfs_error_description(g_zfs)); 1730 ZFS_CLOSE(zhp); 1731 return (ret); 1732 } 1733 ZFS_CLOSE(zhp); 1734 1735 /* Get handle to this zone's root container dataset. */ 1736 if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM)) 1737 == NULL) { 1738 be_print_err(gettext("be_destroy_zone_roots: failed to " 1739 "open zone root container dataset (%s): %s\n"), 1740 zone_container_ds, libzfs_error_description(g_zfs)); 1741 return (zfs_err_to_be_err(g_zfs)); 1742 } 1743 1744 /* 1745 * If there are no more zone roots in this zone's root container, 1746 * dataset, destroy it and the zonepath dataset as well. 1747 */ 1748 if (zfs_iter_filesystems(zhp, be_zone_root_exists_callback, NULL) 1749 == 0) { 1750 /* Destroy the zone root container dataset */ 1751 if (zfs_unmount(zhp, NULL, MS_FORCE) != 0 || 1752 zfs_destroy(zhp, B_FALSE) != 0) { 1753 be_print_err(gettext("be_destroy_zone_roots: failed to " 1754 "destroy zone root container dataset (%s): %s\n"), 1755 zone_container_ds, libzfs_error_description(g_zfs)); 1756 goto done; 1757 } 1758 ZFS_CLOSE(zhp); 1759 1760 /* Get handle to zonepath dataset */ 1761 if ((zhp = zfs_open(g_zfs, zonepath_ds, ZFS_TYPE_FILESYSTEM)) 1762 == NULL) { 1763 be_print_err(gettext("be_destroy_zone_roots: failed to " 1764 "open zonepath dataset (%s): %s\n"), 1765 zonepath_ds, libzfs_error_description(g_zfs)); 1766 goto done; 1767 } 1768 1769 /* Destroy zonepath dataset */ 1770 if (zfs_unmount(zhp, NULL, MS_FORCE) != 0 || 1771 zfs_destroy(zhp, B_FALSE) != 0) { 1772 be_print_err(gettext("be_destroy_zone_roots: " 1773 "failed to destroy zonepath dataest %s: %s\n"), 1774 zonepath_ds, libzfs_error_description(g_zfs)); 1775 goto done; 1776 } 1777 } 1778 1779 done: 1780 ZFS_CLOSE(zhp); 1781 return (ret); 1782 } 1783 1784 /* 1785 * Function: be_destroy_zone_roots_callback 1786 * Description: This function is used as a callback to iterate over all of 1787 * a zone's root datasets, finding the one's that 1788 * correspond to the current BE. The name's 1789 * of the zone root datasets are then destroyed by _be_destroy(). 1790 * Parameters: 1791 * zhp - zfs_handle_t pointer to current dataset being processed 1792 * data - be_destroy_data_t pointer 1793 * Returns: 1794 * 0 - Success 1795 * be_errno_t - Failure 1796 * Scope: 1797 * Private 1798 */ 1799 static int 1800 be_destroy_zone_roots_callback(zfs_handle_t *zhp, void *data) 1801 { 1802 be_destroy_data_t *dd = data; 1803 uuid_t parent_uuid = { 0 }; 1804 int ret = 0; 1805 1806 if (be_zone_get_parent_uuid(zfs_get_name(zhp), &parent_uuid) 1807 != BE_SUCCESS) { 1808 be_print_err(gettext("be_destroy_zone_roots_callback: " 1809 "could not get parentuuid for zone root dataset %s\n"), 1810 zfs_get_name(zhp)); 1811 ZFS_CLOSE(zhp); 1812 return (0); 1813 } 1814 1815 if (uuid_compare(dd->gz_be_uuid, parent_uuid) == 0) { 1816 /* 1817 * Found a zone root dataset belonging to the parent 1818 * BE being destroyed. Destroy this zone BE. 1819 */ 1820 if ((ret = _be_destroy(zfs_get_name(zhp), dd)) != BE_SUCCESS) { 1821 be_print_err(gettext("be_destroy_zone_root_callback: " 1822 "failed to destroy zone root %s\n"), 1823 zfs_get_name(zhp)); 1824 ZFS_CLOSE(zhp); 1825 return (ret); 1826 } 1827 } 1828 ZFS_CLOSE(zhp); 1829 1830 return (ret); 1831 } 1832 1833 /* 1834 * Function: be_copy_zones 1835 * Description: Find valid zones and clone them to create their 1836 * corresponding datasets for the BE being created. 1837 * Parameters: 1838 * obe_name - name of source global BE being copied. 1839 * obe_root_ds - root dataset of source global BE being copied. 1840 * nbe_root_ds - root dataset of target global BE. 1841 * Return: 1842 * BE_SUCCESS - Success 1843 * be_errno_t - Failure 1844 * Scope: 1845 * Private 1846 */ 1847 static int 1848 be_copy_zones(char *obe_name, char *obe_root_ds, char *nbe_root_ds) 1849 { 1850 int i, num_retries; 1851 int ret = BE_SUCCESS; 1852 int iret = 0; 1853 char *zonename = NULL; 1854 char *zonepath = NULL; 1855 char *zone_be_name = NULL; 1856 char *temp_mntpt = NULL; 1857 char *new_zone_be_name = NULL; 1858 char zoneroot[MAXPATHLEN]; 1859 char zoneroot_ds[MAXPATHLEN]; 1860 char zone_container_ds[MAXPATHLEN]; 1861 char new_zoneroot_ds[MAXPATHLEN]; 1862 char ss[MAXPATHLEN]; 1863 uuid_t uu = { 0 }; 1864 char uu_string[UUID_PRINTABLE_STRING_LENGTH] = { 0 }; 1865 be_transaction_data_t bt = { 0 }; 1866 zfs_handle_t *obe_zhp = NULL; 1867 zfs_handle_t *nbe_zhp = NULL; 1868 zfs_handle_t *z_zhp = NULL; 1869 zoneList_t zlist = NULL; 1870 zoneBrandList_t *brands = NULL; 1871 boolean_t mounted_here = B_FALSE; 1872 char *snap_name = NULL; 1873 1874 /* If zones are not implemented, then get out. */ 1875 if (!z_zones_are_implemented()) { 1876 return (BE_SUCCESS); 1877 } 1878 1879 /* Get list of supported brands */ 1880 if ((brands = be_get_supported_brandlist()) == NULL) { 1881 be_print_err(gettext("be_copy_zones: " 1882 "no supported brands\n")); 1883 return (BE_SUCCESS); 1884 } 1885 1886 /* Get handle to origin BE's root dataset */ 1887 if ((obe_zhp = zfs_open(g_zfs, obe_root_ds, ZFS_TYPE_FILESYSTEM)) 1888 == NULL) { 1889 be_print_err(gettext("be_copy_zones: failed to open " 1890 "the origin BE root dataset (%s) for zones processing: " 1891 "%s\n"), obe_root_ds, libzfs_error_description(g_zfs)); 1892 return (zfs_err_to_be_err(g_zfs)); 1893 } 1894 1895 /* Get handle to newly cloned BE's root dataset */ 1896 if ((nbe_zhp = zfs_open(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM)) 1897 == NULL) { 1898 be_print_err(gettext("be_copy_zones: failed to open " 1899 "the new BE root dataset (%s): %s\n"), nbe_root_ds, 1900 libzfs_error_description(g_zfs)); 1901 ZFS_CLOSE(obe_zhp); 1902 return (zfs_err_to_be_err(g_zfs)); 1903 } 1904 1905 /* Get the uuid of the newly cloned parent BE. */ 1906 if (be_get_uuid(zfs_get_name(nbe_zhp), &uu) != BE_SUCCESS) { 1907 be_print_err(gettext("be_copy_zones: " 1908 "failed to get uuid for BE root " 1909 "dataset %s\n"), zfs_get_name(nbe_zhp)); 1910 ZFS_CLOSE(nbe_zhp); 1911 goto done; 1912 } 1913 ZFS_CLOSE(nbe_zhp); 1914 uuid_unparse(uu, uu_string); 1915 1916 /* 1917 * If the origin BE is not mounted, we must mount it here to 1918 * gather data about the non-global zones in it. 1919 */ 1920 if (!zfs_is_mounted(obe_zhp, &temp_mntpt)) { 1921 if ((ret = _be_mount(obe_name, &temp_mntpt, 1922 BE_MOUNT_FLAG_NULL)) != BE_SUCCESS) { 1923 be_print_err(gettext("be_copy_zones: failed to " 1924 "mount the BE (%s) for zones procesing.\n"), 1925 obe_name); 1926 goto done; 1927 } 1928 mounted_here = B_TRUE; 1929 } 1930 1931 z_set_zone_root(temp_mntpt); 1932 1933 /* Get list of supported zones. */ 1934 if ((zlist = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) { 1935 ret = BE_SUCCESS; 1936 goto done; 1937 } 1938 1939 for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) { 1940 1941 be_fs_list_data_t fld = { 0 }; 1942 char zonepath_ds[MAXPATHLEN]; 1943 char *ds = NULL; 1944 1945 /* Get zonepath of zone */ 1946 zonepath = z_zlist_get_zonepath(zlist, i); 1947 1948 /* Skip zones that aren't at least installed */ 1949 if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED) 1950 continue; 1951 1952 /* 1953 * Get the dataset of this zonepath. If its not 1954 * a dataset, skip it. 1955 */ 1956 if ((ds = be_get_ds_from_dir(zonepath)) == NULL) 1957 continue; 1958 1959 (void) strlcpy(zonepath_ds, ds, sizeof (zonepath_ds)); 1960 free(ds); 1961 ds = NULL; 1962 1963 /* Get zoneroot directory */ 1964 be_make_zoneroot(zonepath, zoneroot, sizeof (zoneroot)); 1965 1966 /* If zonepath dataset not supported, skip it. */ 1967 if (!be_zone_supported(zonepath_ds)) { 1968 continue; 1969 } 1970 1971 if ((ret = be_find_active_zone_root(obe_zhp, zonepath_ds, 1972 zoneroot_ds, sizeof (zoneroot_ds))) != BE_SUCCESS) { 1973 be_print_err(gettext("be_copy_zones: " 1974 "failed to find active zone root for zone %s " 1975 "in BE %s\n"), zonename, obe_name); 1976 goto done; 1977 } 1978 1979 be_make_container_ds(zonepath_ds, zone_container_ds, 1980 sizeof (zone_container_ds)); 1981 1982 if ((z_zhp = zfs_open(g_zfs, zoneroot_ds, 1983 ZFS_TYPE_FILESYSTEM)) == NULL) { 1984 be_print_err(gettext("be_copy_zones: " 1985 "failed to open zone root dataset (%s): %s\n"), 1986 zoneroot_ds, libzfs_error_description(g_zfs)); 1987 ret = zfs_err_to_be_err(g_zfs); 1988 goto done; 1989 } 1990 1991 zone_be_name = 1992 be_get_zone_be_name(zoneroot_ds, zone_container_ds); 1993 1994 if ((new_zone_be_name = be_auto_zone_be_name(zone_container_ds, 1995 zone_be_name)) == NULL) { 1996 be_print_err(gettext("be_copy_zones: failed " 1997 "to generate auto name for zone BE.\n")); 1998 ret = BE_ERR_AUTONAME; 1999 goto done; 2000 } 2001 2002 if ((snap_name = be_auto_snap_name()) == NULL) { 2003 be_print_err(gettext("be_copy_zones: failed to " 2004 "generate snapshot name for zone BE.\n")); 2005 ret = BE_ERR_AUTONAME; 2006 goto done; 2007 } 2008 2009 (void) snprintf(ss, sizeof (ss), "%s@%s", zoneroot_ds, 2010 snap_name); 2011 2012 if (zfs_snapshot(g_zfs, ss, B_TRUE, NULL) != 0) { 2013 be_print_err(gettext("be_copy_zones: " 2014 "failed to snapshot zone BE (%s): %s\n"), 2015 ss, libzfs_error_description(g_zfs)); 2016 if (libzfs_errno(g_zfs) == EZFS_EXISTS) 2017 ret = BE_ERR_ZONE_SS_EXISTS; 2018 else 2019 ret = zfs_err_to_be_err(g_zfs); 2020 2021 goto done; 2022 } 2023 2024 (void) snprintf(new_zoneroot_ds, sizeof (new_zoneroot_ds), 2025 "%s/%s", zone_container_ds, new_zone_be_name); 2026 2027 bt.obe_name = zone_be_name; 2028 bt.obe_root_ds = zoneroot_ds; 2029 bt.obe_snap_name = snap_name; 2030 bt.obe_altroot = temp_mntpt; 2031 bt.nbe_name = new_zone_be_name; 2032 bt.nbe_root_ds = new_zoneroot_ds; 2033 2034 if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) { 2035 be_print_err(gettext("be_copy_zones: " 2036 "internal error: out of memory\n")); 2037 ret = BE_ERR_NOMEM; 2038 goto done; 2039 } 2040 2041 /* 2042 * The call to be_clone_fs_callback always closes the 2043 * zfs_handle so there's no need to close z_zhp. 2044 */ 2045 if ((iret = be_clone_fs_callback(z_zhp, &bt)) != 0) { 2046 z_zhp = NULL; 2047 if (iret != BE_ERR_BE_EXISTS) { 2048 be_print_err(gettext("be_copy_zones: " 2049 "failed to create zone BE clone for new " 2050 "zone BE %s\n"), new_zone_be_name); 2051 ret = iret; 2052 if (bt.nbe_zfs_props != NULL) 2053 nvlist_free(bt.nbe_zfs_props); 2054 goto done; 2055 } 2056 /* 2057 * We failed to create the new zone BE because a zone 2058 * BE with the auto-name we generated above has since 2059 * come into existence. Regenerate a new auto-name 2060 * and retry. 2061 */ 2062 for (num_retries = 1; 2063 num_retries < BE_AUTO_NAME_MAX_TRY; 2064 num_retries++) { 2065 2066 /* Sleep 1 before retrying */ 2067 (void) sleep(1); 2068 2069 /* Generate new auto zone BE name */ 2070 free(new_zone_be_name); 2071 if ((new_zone_be_name = be_auto_zone_be_name( 2072 zone_container_ds, 2073 zone_be_name)) == NULL) { 2074 be_print_err(gettext("be_copy_zones: " 2075 "failed to generate auto name " 2076 "for zone BE.\n")); 2077 ret = BE_ERR_AUTONAME; 2078 if (bt.nbe_zfs_props != NULL) 2079 nvlist_free(bt.nbe_zfs_props); 2080 goto done; 2081 } 2082 2083 (void) snprintf(new_zoneroot_ds, 2084 sizeof (new_zoneroot_ds), 2085 "%s/%s", zone_container_ds, 2086 new_zone_be_name); 2087 bt.nbe_name = new_zone_be_name; 2088 bt.nbe_root_ds = new_zoneroot_ds; 2089 2090 /* 2091 * Get handle to original zone BE's root 2092 * dataset. 2093 */ 2094 if ((z_zhp = zfs_open(g_zfs, zoneroot_ds, 2095 ZFS_TYPE_FILESYSTEM)) == NULL) { 2096 be_print_err(gettext("be_copy_zones: " 2097 "failed to open zone root " 2098 "dataset (%s): %s\n"), 2099 zoneroot_ds, 2100 libzfs_error_description(g_zfs)); 2101 ret = zfs_err_to_be_err(g_zfs); 2102 if (bt.nbe_zfs_props != NULL) 2103 nvlist_free(bt.nbe_zfs_props); 2104 goto done; 2105 } 2106 2107 /* 2108 * Try to clone the zone BE again. This 2109 * call will end up closing the zfs 2110 * handle passed in whether it 2111 * succeeds or fails. 2112 */ 2113 iret = be_clone_fs_callback(z_zhp, &bt); 2114 z_zhp = NULL; 2115 if (iret == 0) { 2116 break; 2117 } else if (iret != BE_ERR_BE_EXISTS) { 2118 be_print_err(gettext("be_copy_zones: " 2119 "failed to create zone BE clone " 2120 "for new zone BE %s\n"), 2121 new_zone_be_name); 2122 ret = iret; 2123 if (bt.nbe_zfs_props != NULL) 2124 nvlist_free(bt.nbe_zfs_props); 2125 goto done; 2126 } 2127 } 2128 /* 2129 * If we've exhausted the maximum number of 2130 * tries, free the auto zone BE name and return 2131 * error. 2132 */ 2133 if (num_retries == BE_AUTO_NAME_MAX_TRY) { 2134 be_print_err(gettext("be_copy_zones: failed " 2135 "to create a unique auto zone BE name\n")); 2136 free(bt.nbe_name); 2137 bt.nbe_name = NULL; 2138 ret = BE_ERR_AUTONAME; 2139 if (bt.nbe_zfs_props != NULL) 2140 nvlist_free(bt.nbe_zfs_props); 2141 goto done; 2142 } 2143 } 2144 2145 if (bt.nbe_zfs_props != NULL) 2146 nvlist_free(bt.nbe_zfs_props); 2147 2148 z_zhp = NULL; 2149 2150 if ((z_zhp = zfs_open(g_zfs, new_zoneroot_ds, 2151 ZFS_TYPE_FILESYSTEM)) == NULL) { 2152 be_print_err(gettext("be_copy_zones: " 2153 "failed to open the new zone BE root dataset " 2154 "(%s): %s\n"), new_zoneroot_ds, 2155 libzfs_error_description(g_zfs)); 2156 ret = zfs_err_to_be_err(g_zfs); 2157 goto done; 2158 } 2159 2160 if (zfs_prop_set(z_zhp, BE_ZONE_PARENTBE_PROPERTY, 2161 uu_string) != 0) { 2162 be_print_err(gettext("be_copy_zones: " 2163 "failed to set parentbe property\n")); 2164 ZFS_CLOSE(z_zhp); 2165 ret = zfs_err_to_be_err(g_zfs); 2166 goto done; 2167 } 2168 2169 if (zfs_prop_set(z_zhp, BE_ZONE_ACTIVE_PROPERTY, "on") != 0) { 2170 be_print_err(gettext("be_copy_zones: " 2171 "failed to set active property\n")); 2172 ZFS_CLOSE(z_zhp); 2173 ret = zfs_err_to_be_err(g_zfs); 2174 goto done; 2175 } 2176 2177 /* 2178 * Generate a list of file systems from the original 2179 * zone BE that are legacy mounted. We use this list 2180 * to determine which entries in the vfstab we need to 2181 * update for the new zone BE we've just created. 2182 */ 2183 if ((ret = be_get_legacy_fs(obe_name, obe_root_ds, 2184 zoneroot_ds, zoneroot, &fld)) != BE_SUCCESS) { 2185 be_print_err(gettext("be_copy_zones: " 2186 "failed to get legacy mounted file system " 2187 "list for zone %s\n"), zonename); 2188 ZFS_CLOSE(z_zhp); 2189 goto done; 2190 } 2191 2192 /* 2193 * Update new zone BE's vfstab. 2194 */ 2195 if ((ret = be_update_zone_vfstab(z_zhp, bt.nbe_name, 2196 zonepath_ds, zonepath_ds, &fld)) != BE_SUCCESS) { 2197 be_print_err(gettext("be_copy_zones: " 2198 "failed to update new BE's vfstab (%s)\n"), 2199 bt.nbe_name); 2200 ZFS_CLOSE(z_zhp); 2201 be_free_fs_list(&fld); 2202 goto done; 2203 } 2204 2205 be_free_fs_list(&fld); 2206 ZFS_CLOSE(z_zhp); 2207 } 2208 2209 done: 2210 free(snap_name); 2211 if (brands != NULL) 2212 z_free_brand_list(brands); 2213 if (zlist != NULL) 2214 z_free_zone_list(zlist); 2215 2216 if (mounted_here) 2217 (void) _be_unmount(obe_name, 0); 2218 2219 ZFS_CLOSE(obe_zhp); 2220 return (ret); 2221 } 2222 2223 /* 2224 * Function: be_clone_fs_callback 2225 * Description: Callback function used to iterate through a BE's filesystems 2226 * to clone them for the new BE. 2227 * Parameters: 2228 * zhp - zfs_handle_t pointer for the filesystem being processed. 2229 * data - be_transaction_data_t pointer providing information 2230 * about original BE and new BE. 2231 * Return: 2232 * 0 - Success 2233 * be_errno_t - Failure 2234 * Scope: 2235 * Private 2236 */ 2237 static int 2238 be_clone_fs_callback(zfs_handle_t *zhp, void *data) 2239 { 2240 be_transaction_data_t *bt = data; 2241 zfs_handle_t *zhp_ss = NULL; 2242 char prop_buf[MAXPATHLEN]; 2243 char zhp_name[ZFS_MAXNAMELEN]; 2244 char clone_ds[MAXPATHLEN]; 2245 char ss[MAXPATHLEN]; 2246 int ret = 0; 2247 2248 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop_buf, 2249 ZFS_MAXPROPLEN, NULL, NULL, 0, B_FALSE) != 0) { 2250 be_print_err(gettext("be_clone_fs_callback: " 2251 "failed to get dataset mountpoint (%s): %s\n"), 2252 zfs_get_name(zhp), libzfs_error_description(g_zfs)); 2253 ret = zfs_err_to_be_err(g_zfs); 2254 ZFS_CLOSE(zhp); 2255 return (ret); 2256 } 2257 2258 if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) != 0 && 2259 strcmp(prop_buf, "legacy") != 0) { 2260 /* 2261 * Since zfs can't currently handle setting the 2262 * mountpoint for a zoned dataset we'll have to skip 2263 * this dataset. This is because the mountpoint is not 2264 * set to "legacy". 2265 */ 2266 goto zoned; 2267 } 2268 /* 2269 * Get a copy of the dataset name from the zfs handle 2270 */ 2271 (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name)); 2272 2273 /* 2274 * Get the clone dataset name and prepare the zfs properties for it. 2275 */ 2276 if ((ret = be_prep_clone_send_fs(zhp, bt, clone_ds, 2277 sizeof (clone_ds))) != BE_SUCCESS) { 2278 ZFS_CLOSE(zhp); 2279 return (ret); 2280 } 2281 2282 /* 2283 * Generate the name of the snapshot to use. 2284 */ 2285 (void) snprintf(ss, sizeof (ss), "%s@%s", zhp_name, 2286 bt->obe_snap_name); 2287 2288 /* 2289 * Get handle to snapshot. 2290 */ 2291 if ((zhp_ss = zfs_open(g_zfs, ss, ZFS_TYPE_SNAPSHOT)) == NULL) { 2292 be_print_err(gettext("be_clone_fs_callback: " 2293 "failed to get handle to snapshot (%s): %s\n"), ss, 2294 libzfs_error_description(g_zfs)); 2295 ret = zfs_err_to_be_err(g_zfs); 2296 ZFS_CLOSE(zhp); 2297 return (ret); 2298 } 2299 2300 /* 2301 * Clone the dataset. 2302 */ 2303 if (zfs_clone(zhp_ss, clone_ds, bt->nbe_zfs_props) != 0) { 2304 be_print_err(gettext("be_clone_fs_callback: " 2305 "failed to create clone dataset (%s): %s\n"), 2306 clone_ds, libzfs_error_description(g_zfs)); 2307 2308 ZFS_CLOSE(zhp_ss); 2309 ZFS_CLOSE(zhp); 2310 2311 return (zfs_err_to_be_err(g_zfs)); 2312 } 2313 2314 ZFS_CLOSE(zhp_ss); 2315 2316 zoned: 2317 /* 2318 * Iterate through zhp's children datasets (if any) 2319 * and clone them accordingly. 2320 */ 2321 if ((ret = zfs_iter_filesystems(zhp, be_clone_fs_callback, bt)) != 0) { 2322 /* 2323 * Error occurred while processing a child dataset. 2324 * Destroy this dataset and return error. 2325 */ 2326 zfs_handle_t *d_zhp = NULL; 2327 2328 ZFS_CLOSE(zhp); 2329 2330 if ((d_zhp = zfs_open(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM)) 2331 == NULL) { 2332 return (ret); 2333 } 2334 2335 (void) zfs_destroy(d_zhp, B_FALSE); 2336 ZFS_CLOSE(d_zhp); 2337 return (ret); 2338 } 2339 2340 ZFS_CLOSE(zhp); 2341 return (0); 2342 } 2343 2344 /* 2345 * Function: be_send_fs_callback 2346 * Description: Callback function used to iterate through a BE's filesystems 2347 * to copy them for the new BE. 2348 * Parameters: 2349 * zhp - zfs_handle_t pointer for the filesystem being processed. 2350 * data - be_transaction_data_t pointer providing information 2351 * about original BE and new BE. 2352 * Return: 2353 * 0 - Success 2354 * be_errnot_t - Failure 2355 * Scope: 2356 * Private 2357 */ 2358 static int 2359 be_send_fs_callback(zfs_handle_t *zhp, void *data) 2360 { 2361 be_transaction_data_t *bt = data; 2362 recvflags_t flags = { 0 }; 2363 char zhp_name[ZFS_MAXNAMELEN]; 2364 char clone_ds[MAXPATHLEN]; 2365 sendflags_t send_flags = { 0 }; 2366 int pid, status, retval; 2367 int srpipe[2]; 2368 int ret = 0; 2369 2370 /* 2371 * Get a copy of the dataset name from the zfs handle 2372 */ 2373 (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name)); 2374 2375 /* 2376 * Get the clone dataset name and prepare the zfs properties for it. 2377 */ 2378 if ((ret = be_prep_clone_send_fs(zhp, bt, clone_ds, 2379 sizeof (clone_ds))) != BE_SUCCESS) { 2380 ZFS_CLOSE(zhp); 2381 return (ret); 2382 } 2383 2384 /* 2385 * Create the new dataset. 2386 */ 2387 if (zfs_create(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM, bt->nbe_zfs_props) 2388 != 0) { 2389 be_print_err(gettext("be_send_fs_callback: " 2390 "failed to create new dataset '%s': %s\n"), 2391 clone_ds, libzfs_error_description(g_zfs)); 2392 ret = zfs_err_to_be_err(g_zfs); 2393 ZFS_CLOSE(zhp); 2394 return (ret); 2395 } 2396 2397 /* 2398 * Destination file system is already created 2399 * hence we need to set the force flag on 2400 */ 2401 flags.force = B_TRUE; 2402 2403 /* 2404 * Initiate the pipe to be used for the send and recv 2405 */ 2406 if (pipe(srpipe) != 0) { 2407 int err = errno; 2408 be_print_err(gettext("be_send_fs_callback: failed to " 2409 "open pipe\n")); 2410 ZFS_CLOSE(zhp); 2411 return (errno_to_be_err(err)); 2412 } 2413 2414 /* 2415 * Fork off a child to send the dataset 2416 */ 2417 if ((pid = fork()) == -1) { 2418 int err = errno; 2419 be_print_err(gettext("be_send_fs_callback: failed to fork\n")); 2420 (void) close(srpipe[0]); 2421 (void) close(srpipe[1]); 2422 ZFS_CLOSE(zhp); 2423 return (errno_to_be_err(err)); 2424 } else if (pid == 0) { /* child process */ 2425 (void) close(srpipe[0]); 2426 2427 /* Send dataset */ 2428 if (zfs_send(zhp, NULL, bt->obe_snap_name, &send_flags, 2429 srpipe[1], NULL, NULL, NULL) != 0) { 2430 _exit(1); 2431 } 2432 ZFS_CLOSE(zhp); 2433 2434 _exit(0); 2435 } 2436 2437 (void) close(srpipe[1]); 2438 2439 /* Receive dataset */ 2440 if (zfs_receive(g_zfs, clone_ds, &flags, srpipe[0], NULL) != 0) { 2441 be_print_err(gettext("be_send_fs_callback: failed to " 2442 "recv dataset (%s)\n"), clone_ds); 2443 } 2444 (void) close(srpipe[0]); 2445 2446 /* wait for child to exit */ 2447 do { 2448 retval = waitpid(pid, &status, 0); 2449 if (retval == -1) { 2450 status = 0; 2451 } 2452 } while (retval != pid); 2453 2454 if (WEXITSTATUS(status) != 0) { 2455 be_print_err(gettext("be_send_fs_callback: failed to " 2456 "send dataset (%s)\n"), zhp_name); 2457 ZFS_CLOSE(zhp); 2458 return (BE_ERR_ZFS); 2459 } 2460 2461 2462 /* 2463 * Iterate through zhp's children datasets (if any) 2464 * and send them accordingly. 2465 */ 2466 if ((ret = zfs_iter_filesystems(zhp, be_send_fs_callback, bt)) != 0) { 2467 /* 2468 * Error occurred while processing a child dataset. 2469 * Destroy this dataset and return error. 2470 */ 2471 zfs_handle_t *d_zhp = NULL; 2472 2473 ZFS_CLOSE(zhp); 2474 2475 if ((d_zhp = zfs_open(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM)) 2476 == NULL) { 2477 return (ret); 2478 } 2479 2480 (void) zfs_destroy(d_zhp, B_FALSE); 2481 ZFS_CLOSE(d_zhp); 2482 return (ret); 2483 } 2484 2485 ZFS_CLOSE(zhp); 2486 return (0); 2487 } 2488 2489 /* 2490 * Function: be_destroy_callback 2491 * Description: Callback function used to destroy a BEs children datasets 2492 * and snapshots. 2493 * Parameters: 2494 * zhp - zfs_handle_t pointer to the filesystem being processed. 2495 * data - Not used. 2496 * Returns: 2497 * 0 - Success 2498 * be_errno_t - Failure 2499 * Scope: 2500 * Private 2501 */ 2502 static int 2503 be_destroy_callback(zfs_handle_t *zhp, void *data) 2504 { 2505 be_destroy_data_t *dd = data; 2506 int ret = 0; 2507 2508 /* 2509 * Iterate down this file system's hierarchical children 2510 * and destroy them first. 2511 */ 2512 if ((ret = zfs_iter_filesystems(zhp, be_destroy_callback, dd)) != 0) { 2513 ZFS_CLOSE(zhp); 2514 return (ret); 2515 } 2516 2517 if (dd->destroy_snaps) { 2518 /* 2519 * Iterate through this file system's snapshots and 2520 * destroy them before destroying the file system itself. 2521 */ 2522 if ((ret = zfs_iter_snapshots(zhp, be_destroy_callback, dd)) 2523 != 0) { 2524 ZFS_CLOSE(zhp); 2525 return (ret); 2526 } 2527 } 2528 2529 /* Attempt to unmount the dataset before destroying it */ 2530 if (dd->force_unmount) { 2531 if ((ret = zfs_unmount(zhp, NULL, MS_FORCE)) != 0) { 2532 be_print_err(gettext("be_destroy_callback: " 2533 "failed to unmount %s: %s\n"), zfs_get_name(zhp), 2534 libzfs_error_description(g_zfs)); 2535 ret = zfs_err_to_be_err(g_zfs); 2536 ZFS_CLOSE(zhp); 2537 return (ret); 2538 } 2539 } 2540 2541 if (zfs_destroy(zhp, B_FALSE) != 0) { 2542 be_print_err(gettext("be_destroy_callback: " 2543 "failed to destroy %s: %s\n"), zfs_get_name(zhp), 2544 libzfs_error_description(g_zfs)); 2545 ret = zfs_err_to_be_err(g_zfs); 2546 ZFS_CLOSE(zhp); 2547 return (ret); 2548 } 2549 2550 ZFS_CLOSE(zhp); 2551 return (0); 2552 } 2553 2554 /* 2555 * Function: be_demote_callback 2556 * Description: This callback function is used to iterate through the file 2557 * systems of a BE, looking for the right clone to promote such 2558 * that this file system is left without any dependent clones. 2559 * If the file system has no dependent clones, it doesn't need 2560 * to get demoted, and the function will return success. 2561 * 2562 * The demotion will be done in two passes. The first pass 2563 * will attempt to find the youngest snapshot that has a clone 2564 * that is part of some other BE. The second pass will attempt 2565 * to find the youngest snapshot that has a clone that is not 2566 * part of a BE. Doing this helps ensure the aggregated set of 2567 * file systems that compose a BE stay coordinated wrt BE 2568 * snapshots and BE dependents. It also prevents a random user 2569 * generated clone of a BE dataset to become the parent of other 2570 * BE datasets after demoting this dataset. 2571 * 2572 * Parameters: 2573 * zhp - zfs_handle_t pointer to the current file system being 2574 * processed. 2575 * data - not used. 2576 * Return: 2577 * 0 - Success 2578 * be_errno_t - Failure 2579 * Scope: 2580 * Private 2581 */ 2582 static int 2583 /* LINTED */ 2584 be_demote_callback(zfs_handle_t *zhp, void *data) 2585 { 2586 be_demote_data_t dd = { 0 }; 2587 int i, ret = 0; 2588 2589 /* 2590 * Initialize be_demote_data for the first pass - this will find a 2591 * clone in another BE, if one exists. 2592 */ 2593 dd.find_in_BE = B_TRUE; 2594 2595 for (i = 0; i < 2; i++) { 2596 2597 if (zfs_iter_snapshots(zhp, be_demote_find_clone_callback, &dd) 2598 != 0) { 2599 be_print_err(gettext("be_demote_callback: " 2600 "failed to iterate snapshots for %s: %s\n"), 2601 zfs_get_name(zhp), libzfs_error_description(g_zfs)); 2602 ret = zfs_err_to_be_err(g_zfs); 2603 ZFS_CLOSE(zhp); 2604 return (ret); 2605 } 2606 if (dd.clone_zhp != NULL) { 2607 /* Found the clone to promote. Promote it. */ 2608 if (zfs_promote(dd.clone_zhp) != 0) { 2609 be_print_err(gettext("be_demote_callback: " 2610 "failed to promote %s: %s\n"), 2611 zfs_get_name(dd.clone_zhp), 2612 libzfs_error_description(g_zfs)); 2613 ret = zfs_err_to_be_err(g_zfs); 2614 ZFS_CLOSE(dd.clone_zhp); 2615 ZFS_CLOSE(zhp); 2616 return (ret); 2617 } 2618 2619 ZFS_CLOSE(dd.clone_zhp); 2620 } 2621 2622 /* 2623 * Reinitialize be_demote_data for the second pass. 2624 * This will find a user created clone outside of any BE 2625 * namespace, if one exists. 2626 */ 2627 dd.clone_zhp = NULL; 2628 dd.origin_creation = 0; 2629 dd.snapshot = NULL; 2630 dd.find_in_BE = B_FALSE; 2631 } 2632 2633 /* Iterate down this file system's children and demote them */ 2634 if ((ret = zfs_iter_filesystems(zhp, be_demote_callback, NULL)) != 0) { 2635 ZFS_CLOSE(zhp); 2636 return (ret); 2637 } 2638 2639 ZFS_CLOSE(zhp); 2640 return (0); 2641 } 2642 2643 /* 2644 * Function: be_demote_find_clone_callback 2645 * Description: This callback function is used to iterate through the 2646 * snapshots of a dataset, looking for the youngest snapshot 2647 * that has a clone. If found, it returns a reference to the 2648 * clone back to the caller in the callback data. 2649 * Parameters: 2650 * zhp - zfs_handle_t pointer to current snapshot being looked at 2651 * data - be_demote_data_t pointer used to store the clone that 2652 * is found. 2653 * Returns: 2654 * 0 - Successfully iterated through all snapshots. 2655 * 1 - Failed to iterate through all snapshots. 2656 * Scope: 2657 * Private 2658 */ 2659 static int 2660 be_demote_find_clone_callback(zfs_handle_t *zhp, void *data) 2661 { 2662 be_demote_data_t *dd = data; 2663 time_t snap_creation; 2664 int zret = 0; 2665 2666 /* If snapshot has no clones, no need to look at it */ 2667 if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) == 0) { 2668 ZFS_CLOSE(zhp); 2669 return (0); 2670 } 2671 2672 dd->snapshot = zfs_get_name(zhp); 2673 2674 /* Get the creation time of this snapshot */ 2675 snap_creation = (time_t)zfs_prop_get_int(zhp, ZFS_PROP_CREATION); 2676 2677 /* 2678 * If this snapshot's creation time is greater than (or younger than) 2679 * the current youngest snapshot found, iterate this snapshot to 2680 * check if it has a clone that we're looking for. 2681 */ 2682 if (snap_creation >= dd->origin_creation) { 2683 /* 2684 * Iterate the dependents of this snapshot to find a 2685 * a clone that's a direct dependent. 2686 */ 2687 if ((zret = zfs_iter_dependents(zhp, B_FALSE, 2688 be_demote_get_one_clone, dd)) == -1) { 2689 be_print_err(gettext("be_demote_find_clone_callback: " 2690 "failed to iterate dependents of %s\n"), 2691 zfs_get_name(zhp)); 2692 ZFS_CLOSE(zhp); 2693 return (1); 2694 } else if (zret == 1) { 2695 /* 2696 * Found a clone, update the origin_creation time 2697 * in the callback data. 2698 */ 2699 dd->origin_creation = snap_creation; 2700 } 2701 } 2702 2703 ZFS_CLOSE(zhp); 2704 return (0); 2705 } 2706 2707 /* 2708 * Function: be_demote_get_one_clone 2709 * Description: This callback function is used to iterate through a 2710 * snapshot's dependencies to find a filesystem that is a 2711 * direct clone of the snapshot being iterated. 2712 * Parameters: 2713 * zhp - zfs_handle_t pointer to current dataset being looked at 2714 * data - be_demote_data_t pointer used to store the clone 2715 * that is found, and also provides flag to note 2716 * whether or not the clone filesystem being searched 2717 * for needs to be found in a BE dataset hierarchy. 2718 * Return: 2719 * 1 - Success, found clone and its also a BE's root dataset. 2720 * 0 - Failure, clone not found. 2721 * Scope: 2722 * Private 2723 */ 2724 static int 2725 be_demote_get_one_clone(zfs_handle_t *zhp, void *data) 2726 { 2727 be_demote_data_t *dd = data; 2728 char origin[ZFS_MAXNAMELEN]; 2729 char ds_path[ZFS_MAXNAMELEN]; 2730 2731 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 2732 ZFS_CLOSE(zhp); 2733 return (0); 2734 } 2735 2736 (void) strlcpy(ds_path, zfs_get_name(zhp), sizeof (ds_path)); 2737 2738 /* 2739 * Make sure this is a direct clone of the snapshot 2740 * we're iterating. 2741 */ 2742 if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL, 2743 NULL, 0, B_FALSE) != 0) { 2744 be_print_err(gettext("be_demote_get_one_clone: " 2745 "failed to get origin of %s: %s\n"), ds_path, 2746 libzfs_error_description(g_zfs)); 2747 ZFS_CLOSE(zhp); 2748 return (0); 2749 } 2750 if (strcmp(origin, dd->snapshot) != 0) { 2751 ZFS_CLOSE(zhp); 2752 return (0); 2753 } 2754 2755 if (dd->find_in_BE) { 2756 if ((zpool_iter(g_zfs, be_check_be_roots_callback, ds_path)) 2757 > 0) { 2758 if (dd->clone_zhp != NULL) 2759 ZFS_CLOSE(dd->clone_zhp); 2760 dd->clone_zhp = zhp; 2761 return (1); 2762 } 2763 2764 ZFS_CLOSE(zhp); 2765 return (0); 2766 } 2767 2768 if (dd->clone_zhp != NULL) 2769 ZFS_CLOSE(dd->clone_zhp); 2770 2771 dd->clone_zhp = zhp; 2772 return (1); 2773 } 2774 2775 /* 2776 * Function: be_get_snap 2777 * Description: This function takes a snapshot dataset name and separates 2778 * out the parent dataset portion from the snapshot name. 2779 * I.e. it finds the '@' in the snapshot dataset name and 2780 * replaces it with a '\0'. 2781 * Parameters: 2782 * origin - char pointer to a snapshot dataset name. Its 2783 * contents will be modified by this function. 2784 * *snap - pointer to a char pointer. Will be set to the 2785 * snapshot name portion upon success. 2786 * Return: 2787 * BE_SUCCESS - Success 2788 * 1 - Failure 2789 * Scope: 2790 * Private 2791 */ 2792 static int 2793 be_get_snap(char *origin, char **snap) 2794 { 2795 char *cp; 2796 2797 /* 2798 * Separate out the origin's dataset and snapshot portions by 2799 * replacing the @ with a '\0' 2800 */ 2801 cp = strrchr(origin, '@'); 2802 if (cp != NULL) { 2803 if (cp[1] != NULL && cp[1] != '\0') { 2804 cp[0] = '\0'; 2805 *snap = cp+1; 2806 } else { 2807 return (1); 2808 } 2809 } else { 2810 return (1); 2811 } 2812 2813 return (BE_SUCCESS); 2814 } 2815 2816 /* 2817 * Function: be_create_container_ds 2818 * Description: This function checks that the zpool passed has the BE 2819 * container dataset, and if not, then creates it. 2820 * Parameters: 2821 * zpool - name of pool to create BE container dataset in. 2822 * Return: 2823 * B_TRUE - Successfully created BE container dataset, or it 2824 * already existed. 2825 * B_FALSE - Failed to create container dataset. 2826 * Scope: 2827 * Private 2828 */ 2829 static boolean_t 2830 be_create_container_ds(char *zpool) 2831 { 2832 nvlist_t *props = NULL; 2833 char be_container_ds[MAXPATHLEN]; 2834 2835 /* Generate string for BE container dataset for this pool */ 2836 be_make_container_ds(zpool, be_container_ds, 2837 sizeof (be_container_ds)); 2838 2839 if (!zfs_dataset_exists(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM)) { 2840 2841 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 2842 be_print_err(gettext("be_create_container_ds: " 2843 "nvlist_alloc failed\n")); 2844 return (B_FALSE); 2845 } 2846 2847 if (nvlist_add_string(props, 2848 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 2849 ZFS_MOUNTPOINT_LEGACY) != 0) { 2850 be_print_err(gettext("be_create_container_ds: " 2851 "internal error: out of memory\n")); 2852 nvlist_free(props); 2853 return (B_FALSE); 2854 } 2855 2856 if (nvlist_add_string(props, 2857 zfs_prop_to_name(ZFS_PROP_CANMOUNT), "off") != 0) { 2858 be_print_err(gettext("be_create_container_ds: " 2859 "internal error: out of memory\n")); 2860 nvlist_free(props); 2861 return (B_FALSE); 2862 } 2863 2864 if (zfs_create(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM, 2865 props) != 0) { 2866 be_print_err(gettext("be_create_container_ds: " 2867 "failed to create container dataset (%s): %s\n"), 2868 be_container_ds, libzfs_error_description(g_zfs)); 2869 nvlist_free(props); 2870 return (B_FALSE); 2871 } 2872 2873 nvlist_free(props); 2874 } 2875 2876 return (B_TRUE); 2877 } 2878 2879 /* 2880 * Function: be_prep_clone_send_fs 2881 * Description: This function takes a zfs handle to a dataset from the 2882 * original BE, and generates the name of the clone dataset 2883 * to create for the new BE. It also prepares the zfs 2884 * properties to be used for the new BE. 2885 * Parameters: 2886 * zhp - pointer to zfs_handle_t of the file system being 2887 * cloned/copied. 2888 * bt - be_transaction_data pointer providing information 2889 * about the original BE and new BE. 2890 * clone_ds - buffer to store the name of the dataset 2891 * for the new BE. 2892 * clone_ds_len - length of clone_ds buffer 2893 * Return: 2894 * BE_SUCCESS - Success 2895 * be_errno_t - Failure 2896 * Scope: 2897 * Private 2898 */ 2899 static int 2900 be_prep_clone_send_fs(zfs_handle_t *zhp, be_transaction_data_t *bt, 2901 char *clone_ds, int clone_ds_len) 2902 { 2903 zprop_source_t sourcetype; 2904 char source[ZFS_MAXNAMELEN]; 2905 char zhp_name[ZFS_MAXNAMELEN]; 2906 char mountpoint[MAXPATHLEN]; 2907 char *child_fs = NULL; 2908 char *zhp_mountpoint = NULL; 2909 int err = 0; 2910 2911 /* 2912 * Get a copy of the dataset name zfs_name from zhp 2913 */ 2914 (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name)); 2915 2916 /* 2917 * Get file system name relative to the root. 2918 */ 2919 if (strncmp(zhp_name, bt->obe_root_ds, strlen(bt->obe_root_ds)) 2920 == 0) { 2921 child_fs = zhp_name + strlen(bt->obe_root_ds); 2922 2923 /* 2924 * if child_fs is NULL, this means we're processing the 2925 * root dataset itself; set child_fs to the empty string. 2926 */ 2927 if (child_fs == NULL) 2928 child_fs = ""; 2929 } else { 2930 return (BE_ERR_INVAL); 2931 } 2932 2933 /* 2934 * Generate the name of the clone file system. 2935 */ 2936 (void) snprintf(clone_ds, clone_ds_len, "%s%s", bt->nbe_root_ds, 2937 child_fs); 2938 2939 /* Get the mountpoint and source properties of the existing dataset */ 2940 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, 2941 sizeof (mountpoint), &sourcetype, source, sizeof (source), 2942 B_FALSE) != 0) { 2943 be_print_err(gettext("be_prep_clone_send_fs: " 2944 "failed to get mountpoint for (%s): %s\n"), 2945 zhp_name, libzfs_error_description(g_zfs)); 2946 return (zfs_err_to_be_err(g_zfs)); 2947 } 2948 2949 /* 2950 * Workaround for 6668667 where a mountpoint property of "/" comes 2951 * back as "". 2952 */ 2953 if (strcmp(mountpoint, "") == 0) { 2954 (void) snprintf(mountpoint, sizeof (mountpoint), "/"); 2955 } 2956 2957 /* 2958 * Figure out what to set as the mountpoint for the new dataset. 2959 * If the source of the mountpoint property is local, use the 2960 * mountpoint value itself. Otherwise, remove it from the 2961 * zfs properties list so that it gets inherited. 2962 */ 2963 if (sourcetype & ZPROP_SRC_LOCAL) { 2964 /* 2965 * If the BE that this file system is a part of is 2966 * currently mounted, strip off the BE altroot portion 2967 * from the mountpoint. 2968 */ 2969 zhp_mountpoint = mountpoint; 2970 2971 if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 2972 bt->obe_altroot != NULL && strcmp(bt->obe_altroot, 2973 "/") != 0 && zfs_is_mounted(zhp, NULL)) { 2974 2975 int altroot_len = strlen(bt->obe_altroot); 2976 2977 if (strncmp(bt->obe_altroot, mountpoint, altroot_len) 2978 == 0) { 2979 if (mountpoint[altroot_len] == '/') 2980 zhp_mountpoint = mountpoint + 2981 altroot_len; 2982 else if (mountpoint[altroot_len] == '\0') 2983 (void) snprintf(mountpoint, 2984 sizeof (mountpoint), "/"); 2985 } 2986 } 2987 2988 if (nvlist_add_string(bt->nbe_zfs_props, 2989 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 2990 zhp_mountpoint) != 0) { 2991 be_print_err(gettext("be_prep_clone_send_fs: " 2992 "internal error: out of memory\n")); 2993 return (BE_ERR_NOMEM); 2994 } 2995 } else { 2996 err = nvlist_remove_all(bt->nbe_zfs_props, 2997 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT)); 2998 if (err != 0 && err != ENOENT) { 2999 be_print_err(gettext("be_prep_clone_send_fs: " 3000 "failed to remove mountpoint from " 3001 "nvlist\n")); 3002 return (BE_ERR_INVAL); 3003 } 3004 } 3005 3006 /* 3007 * Set the 'canmount' property 3008 */ 3009 if (nvlist_add_string(bt->nbe_zfs_props, 3010 zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto") != 0) { 3011 be_print_err(gettext("be_prep_clone_send_fs: " 3012 "internal error: out of memory\n")); 3013 return (BE_ERR_NOMEM); 3014 } 3015 3016 return (BE_SUCCESS); 3017 } 3018 3019 /* 3020 * Function: be_get_zone_be_name 3021 * Description: This function takes the zones root dataset, the container 3022 * dataset and returns the zones BE name based on the zone 3023 * root dataset. 3024 * Parameters: 3025 * root_ds - the zones root dataset. 3026 * container_ds - the container dataset for the zone. 3027 * Returns: 3028 * char * - the BE name of this zone based on the root dataset. 3029 */ 3030 static char * 3031 be_get_zone_be_name(char *root_ds, char *container_ds) 3032 { 3033 return (root_ds + (strlen(container_ds) + 1)); 3034 } 3035 3036 /* 3037 * Function: be_zone_root_exists_callback 3038 * Description: This callback function is used to determine if a 3039 * zone root container dataset has any children. It always 3040 * returns 1, signifying a hierarchical child of the zone 3041 * root container dataset has been traversed and therefore 3042 * it has children. 3043 * Parameters: 3044 * zhp - zfs_handle_t pointer to current dataset being processed. 3045 * data - not used. 3046 * Returns: 3047 * 1 - dataset exists 3048 * Scope: 3049 * Private 3050 */ 3051 static int 3052 /* LINTED */ 3053 be_zone_root_exists_callback(zfs_handle_t *zhp, void *data) 3054 { 3055 ZFS_CLOSE(zhp); 3056 return (1); 3057 }