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