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