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