1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 25 * Copyright (c) 2014, 2015 by Delphix. All rights reserved. 26 * Copyright (c) 2016 Martin Matuska. All rights reserved. 27 */ 28 29 /* 30 * System includes 31 */ 32 33 #include <assert.h> 34 #include <ctype.h> 35 #include <errno.h> 36 #include <libgen.h> 37 #include <libintl.h> 38 #include <libnvpair.h> 39 #include <libzfs.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <sys/mnttab.h> 44 #include <sys/mount.h> 45 #include <sys/stat.h> 46 #include <sys/types.h> 47 #include <sys/wait.h> 48 #include <unistd.h> 49 50 #include <libbe.h> 51 #include <libbe_priv.h> 52 53 /* Library wide variables */ 54 libzfs_handle_t *g_zfs = NULL; 55 56 /* Private function prototypes */ 57 static int _be_destroy(const char *, be_destroy_data_t *); 58 static int be_destroy_zones(char *, char *, be_destroy_data_t *); 59 static int be_destroy_zone_roots(char *, be_destroy_data_t *); 60 static int be_destroy_zone_roots_callback(zfs_handle_t *, void *); 61 static int be_copy_zones(char *, char *, char *); 62 static int be_clone_fs_callback(zfs_handle_t *, void *); 63 static int be_destroy_callback(zfs_handle_t *, void *); 64 static int be_send_fs_callback(zfs_handle_t *, void *); 65 static int be_demote_callback(zfs_handle_t *, void *); 66 static int be_demote_find_clone_callback(zfs_handle_t *, void *); 67 static int be_has_snapshot_callback(zfs_handle_t *, void *); 68 static int be_demote_get_one_clone(zfs_handle_t *, void *); 69 static int be_get_snap(char *, char **); 70 static int be_prep_clone_send_fs(zfs_handle_t *, be_transaction_data_t *, 71 char *, int); 72 static boolean_t be_create_container_ds(char *); 73 static char *be_get_zone_be_name(char *root_ds, char *container_ds); 74 static int be_zone_root_exists_callback(zfs_handle_t *, void *); 75 76 /* ******************************************************************** */ 77 /* Public Functions */ 78 /* ******************************************************************** */ 79 80 /* 81 * Function: be_init 82 * Description: Creates the initial datasets for a BE and leaves them 83 * unpopulated. The resultant BE can be mounted but can't 84 * yet be activated or booted. 85 * Parameters: 86 * be_attrs - pointer to nvlist_t of attributes being passed in. 87 * The following attributes are used by this function: 88 * 89 * BE_ATTR_NEW_BE_NAME *required 90 * BE_ATTR_NEW_BE_POOL *required 91 * BE_ATTR_ZFS_PROPERTIES *optional 92 * BE_ATTR_FS_NAMES *optional 93 * BE_ATTR_FS_NUM *optional 94 * BE_ATTR_SHARED_FS_NAMES *optional 95 * BE_ATTR_SHARED_FS_NUM *optional 96 * Return: 97 * BE_SUCCESS - Success 98 * be_errno_t - Failure 99 * Scope: 100 * Public 101 */ 102 int 103 be_init(nvlist_t *be_attrs) 104 { 105 be_transaction_data_t bt = { 0 }; 106 zpool_handle_t *zlp; 107 nvlist_t *zfs_props = NULL; 108 char nbe_root_ds[MAXPATHLEN]; 109 char child_fs[MAXPATHLEN]; 110 char **fs_names = NULL; 111 char **shared_fs_names = NULL; 112 uint16_t fs_num = 0; 113 uint16_t shared_fs_num = 0; 114 int nelem; 115 int i; 116 int zret = 0, ret = BE_SUCCESS; 117 118 /* Initialize libzfs handle */ 119 if (!be_zfs_init()) 120 return (BE_ERR_INIT); 121 122 /* Get new BE name */ 123 if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME, &bt.nbe_name) 124 != 0) { 125 be_print_err(gettext("be_init: failed to lookup " 126 "BE_ATTR_NEW_BE_NAME attribute\n")); 127 return (BE_ERR_INVAL); 128 } 129 130 /* Validate new BE name */ 131 if (!be_valid_be_name(bt.nbe_name)) { 132 be_print_err(gettext("be_init: invalid BE name %s\n"), 133 bt.nbe_name); 134 return (BE_ERR_INVAL); 135 } 136 137 /* Get zpool name */ 138 if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_POOL, &bt.nbe_zpool) 139 != 0) { 140 be_print_err(gettext("be_init: failed to lookup " 141 "BE_ATTR_NEW_BE_POOL attribute\n")); 142 return (BE_ERR_INVAL); 143 } 144 145 /* Get file system attributes */ 146 nelem = 0; 147 if (nvlist_lookup_pairs(be_attrs, 0, 148 BE_ATTR_FS_NUM, DATA_TYPE_UINT16, &fs_num, 149 BE_ATTR_FS_NAMES, DATA_TYPE_STRING_ARRAY, &fs_names, &nelem, 150 NULL) != 0) { 151 be_print_err(gettext("be_init: failed to lookup fs " 152 "attributes\n")); 153 return (BE_ERR_INVAL); 154 } 155 if (nelem != fs_num) { 156 be_print_err(gettext("be_init: size of FS_NAMES array (%d) " 157 "does not match FS_NUM (%d)\n"), nelem, fs_num); 158 return (BE_ERR_INVAL); 159 } 160 161 /* Get shared file system attributes */ 162 nelem = 0; 163 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 164 BE_ATTR_SHARED_FS_NUM, DATA_TYPE_UINT16, &shared_fs_num, 165 BE_ATTR_SHARED_FS_NAMES, DATA_TYPE_STRING_ARRAY, &shared_fs_names, 166 &nelem, NULL) != 0) { 167 be_print_err(gettext("be_init: failed to lookup " 168 "shared fs attributes\n")); 169 return (BE_ERR_INVAL); 170 } 171 if (nelem != shared_fs_num) { 172 be_print_err(gettext("be_init: size of SHARED_FS_NAMES " 173 "array does not match SHARED_FS_NUM\n")); 174 return (BE_ERR_INVAL); 175 } 176 177 /* Verify that nbe_zpool exists */ 178 if ((zlp = zpool_open(g_zfs, bt.nbe_zpool)) == NULL) { 179 be_print_err(gettext("be_init: failed to " 180 "find existing zpool (%s): %s\n"), bt.nbe_zpool, 181 libzfs_error_description(g_zfs)); 182 return (zfs_err_to_be_err(g_zfs)); 183 } 184 zpool_close(zlp); 185 186 /* 187 * Verify BE container dataset in nbe_zpool exists. 188 * If not, create it. 189 */ 190 if (!be_create_container_ds(bt.nbe_zpool)) 191 return (BE_ERR_CREATDS); 192 193 /* 194 * Verify that nbe_name doesn't already exist in some pool. 195 */ 196 if ((zret = zpool_iter(g_zfs, be_exists_callback, bt.nbe_name)) > 0) { 197 be_print_err(gettext("be_init: BE (%s) already exists\n"), 198 bt.nbe_name); 199 return (BE_ERR_BE_EXISTS); 200 } else if (zret < 0) { 201 be_print_err(gettext("be_init: zpool_iter failed: %s\n"), 202 libzfs_error_description(g_zfs)); 203 return (zfs_err_to_be_err(g_zfs)); 204 } 205 206 /* Generate string for BE's root dataset */ 207 be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds, 208 sizeof (nbe_root_ds)); 209 210 /* 211 * Create property list for new BE root dataset. If some 212 * zfs properties were already provided by the caller, dup 213 * that list. Otherwise initialize a new property list. 214 */ 215 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 216 BE_ATTR_ZFS_PROPERTIES, DATA_TYPE_NVLIST, &zfs_props, NULL) 217 != 0) { 218 be_print_err(gettext("be_init: failed to lookup " 219 "BE_ATTR_ZFS_PROPERTIES attribute\n")); 220 return (BE_ERR_INVAL); 221 } 222 if (zfs_props != NULL) { 223 /* Make sure its a unique nvlist */ 224 if (!(zfs_props->nvl_nvflag & NV_UNIQUE_NAME) && 225 !(zfs_props->nvl_nvflag & NV_UNIQUE_NAME_TYPE)) { 226 be_print_err(gettext("be_init: ZFS property list " 227 "not unique\n")); 228 return (BE_ERR_INVAL); 229 } 230 231 /* Dup the list */ 232 if (nvlist_dup(zfs_props, &bt.nbe_zfs_props, 0) != 0) { 233 be_print_err(gettext("be_init: failed to dup ZFS " 234 "property list\n")); 235 return (BE_ERR_NOMEM); 236 } 237 } else { 238 /* Initialize new nvlist */ 239 if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) { 240 be_print_err(gettext("be_init: internal " 241 "error: out of memory\n")); 242 return (BE_ERR_NOMEM); 243 } 244 } 245 246 /* Set the mountpoint property for the root dataset */ 247 if (nvlist_add_string(bt.nbe_zfs_props, 248 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), "/") != 0) { 249 be_print_err(gettext("be_init: internal error " 250 "out of memory\n")); 251 ret = BE_ERR_NOMEM; 252 goto done; 253 } 254 255 /* Set the 'canmount' property */ 256 if (nvlist_add_string(bt.nbe_zfs_props, 257 zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto") != 0) { 258 be_print_err(gettext("be_init: internal error " 259 "out of memory\n")); 260 ret = BE_ERR_NOMEM; 261 goto done; 262 } 263 264 /* Create BE root dataset for the new BE */ 265 if (zfs_create(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM, 266 bt.nbe_zfs_props) != 0) { 267 be_print_err(gettext("be_init: failed to " 268 "create BE root dataset (%s): %s\n"), nbe_root_ds, 269 libzfs_error_description(g_zfs)); 270 ret = zfs_err_to_be_err(g_zfs); 271 goto done; 272 } 273 274 /* Set UUID for new BE */ 275 if ((ret = be_set_uuid(nbe_root_ds)) != BE_SUCCESS) { 276 be_print_err(gettext("be_init: failed to " 277 "set uuid for new BE\n")); 278 } 279 280 /* 281 * Clear the mountpoint property so that the non-shared 282 * file systems created below inherit their mountpoints. 283 */ 284 (void) nvlist_remove(bt.nbe_zfs_props, 285 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), DATA_TYPE_STRING); 286 287 /* Create the new BE's non-shared file systems */ 288 for (i = 0; i < fs_num && fs_names[i]; i++) { 289 /* 290 * If fs == "/", skip it; 291 * we already created the root dataset 292 */ 293 if (strcmp(fs_names[i], "/") == 0) 294 continue; 295 296 /* Generate string for file system */ 297 (void) snprintf(child_fs, sizeof (child_fs), "%s%s", 298 nbe_root_ds, fs_names[i]); 299 300 /* Create file system */ 301 if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM, 302 bt.nbe_zfs_props) != 0) { 303 be_print_err(gettext("be_init: failed to create " 304 "BE's child dataset (%s): %s\n"), child_fs, 305 libzfs_error_description(g_zfs)); 306 ret = zfs_err_to_be_err(g_zfs); 307 goto done; 308 } 309 } 310 311 /* Create the new BE's shared file systems */ 312 if (shared_fs_num > 0) { 313 nvlist_t *props = NULL; 314 315 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 316 be_print_err(gettext("be_init: nvlist_alloc failed\n")); 317 ret = BE_ERR_NOMEM; 318 goto done; 319 } 320 321 for (i = 0; i < shared_fs_num; i++) { 322 /* Generate string for shared file system */ 323 (void) snprintf(child_fs, sizeof (child_fs), "%s%s", 324 bt.nbe_zpool, shared_fs_names[i]); 325 326 if (nvlist_add_string(props, 327 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 328 shared_fs_names[i]) != 0) { 329 be_print_err(gettext("be_init: " 330 "internal error: out of memory\n")); 331 nvlist_free(props); 332 ret = BE_ERR_NOMEM; 333 goto done; 334 } 335 336 /* Create file system if it doesn't already exist */ 337 if (zfs_dataset_exists(g_zfs, child_fs, 338 ZFS_TYPE_FILESYSTEM)) { 339 continue; 340 } 341 if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM, 342 props) != 0) { 343 be_print_err(gettext("be_init: failed to " 344 "create BE's shared dataset (%s): %s\n"), 345 child_fs, libzfs_error_description(g_zfs)); 346 ret = zfs_err_to_be_err(g_zfs); 347 nvlist_free(props); 348 goto done; 349 } 350 } 351 352 nvlist_free(props); 353 } 354 355 done: 356 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, B_FALSE, be_has_snapshot_callback, 488 &bs_found); 489 if (!dd.destroy_snaps && bs_found) { 490 ZFS_CLOSE(zhp); 491 return (BE_ERR_SS_EXISTS); 492 } 493 494 /* Get the UUID of the global BE */ 495 if (getzoneid() == GLOBAL_ZONEID) { 496 if (be_get_uuid(zfs_get_name(zhp), 497 &dd.gz_be_uuid) != BE_SUCCESS) { 498 be_print_err(gettext("be_destroy: BE has no " 499 "UUID (%s)\n"), zfs_get_name(zhp)); 500 } 501 } 502 503 /* 504 * If the global BE is mounted, make sure we've been given the 505 * flag to forcibly unmount it. 506 */ 507 if (zfs_is_mounted(zhp, &mp)) { 508 if (!(dd.force_unmount)) { 509 be_print_err(gettext("be_destroy: " 510 "%s is currently mounted at %s, cannot destroy\n"), 511 bt.obe_name, mp != NULL ? mp : "<unknown>"); 512 513 free(mp); 514 ZFS_CLOSE(zhp); 515 return (BE_ERR_MOUNTED); 516 } 517 free(mp); 518 } 519 520 /* 521 * Destroy the non-global zone BE's if we are in the global zone 522 * and there is a UUID associated with the global zone BE 523 */ 524 if (getzoneid() == GLOBAL_ZONEID && !uuid_is_null(dd.gz_be_uuid)) { 525 if ((ret = be_destroy_zones(bt.obe_name, bt.obe_root_ds, &dd)) 526 != BE_SUCCESS) { 527 be_print_err(gettext("be_destroy: failed to " 528 "destroy one or more zones for BE %s\n"), 529 bt.obe_name); 530 goto done; 531 } 532 } 533 534 /* Unmount the BE if it was mounted */ 535 if (zfs_is_mounted(zhp, NULL)) { 536 if ((ret = _be_unmount(bt.obe_name, BE_UNMOUNT_FLAG_FORCE)) 537 != BE_SUCCESS) { 538 be_print_err(gettext("be_destroy: " 539 "failed to unmount %s\n"), bt.obe_name); 540 ZFS_CLOSE(zhp); 541 return (ret); 542 } 543 } 544 ZFS_CLOSE(zhp); 545 546 /* Destroy this BE */ 547 if ((ret = _be_destroy((const char *)bt.obe_root_ds, &dd)) 548 != BE_SUCCESS) { 549 goto done; 550 } 551 552 /* Remove BE's entry from the boot menu */ 553 if (getzoneid() == GLOBAL_ZONEID) { 554 if ((ret = be_remove_menu(bt.obe_name, bt.obe_zpool, NULL)) 555 != BE_SUCCESS) { 556 be_print_err(gettext("be_destroy: failed to " 557 "remove BE %s from the boot menu\n"), 558 bt.obe_root_ds); 559 goto done; 560 } 561 } 562 563 done: 564 be_zfs_fini(); 565 566 return (ret); 567 } 568 569 /* 570 * Function: be_copy 571 * Description: This function makes a copy of an existing BE. If the original 572 * BE and the new BE are in the same pool, it uses zfs cloning to 573 * create the new BE, otherwise it does a physical copy. 574 * If the original BE name isn't provided, it uses the currently 575 * booted BE. If the new BE name isn't provided, it creates an 576 * auto named BE and returns that name to the caller. 577 * Parameters: 578 * be_attrs - pointer to nvlist_t of attributes being passed in. 579 * The following attributes are used by this function: 580 * 581 * BE_ATTR_ORIG_BE_NAME *optional 582 * BE_ATTR_SNAP_NAME *optional 583 * BE_ATTR_NEW_BE_NAME *optional 584 * BE_ATTR_NEW_BE_POOL *optional 585 * BE_ATTR_NEW_BE_DESC *optional 586 * BE_ATTR_ZFS_PROPERTIES *optional 587 * BE_ATTR_POLICY *optional 588 * 589 * If the BE_ATTR_NEW_BE_NAME was not passed in, upon 590 * successful BE creation, the following attribute values 591 * will be returned to the caller by setting them in the 592 * be_attrs parameter passed in: 593 * 594 * BE_ATTR_SNAP_NAME 595 * BE_ATTR_NEW_BE_NAME 596 * Return: 597 * BE_SUCCESS - Success 598 * be_errno_t - Failure 599 * Scope: 600 * Public 601 */ 602 int 603 be_copy(nvlist_t *be_attrs) 604 { 605 be_transaction_data_t bt = { 0 }; 606 be_fs_list_data_t fld = { 0 }; 607 zfs_handle_t *zhp = NULL; 608 zpool_handle_t *zphp = NULL; 609 nvlist_t *zfs_props = NULL; 610 uuid_t uu = { 0 }; 611 uuid_t parent_uu = { 0 }; 612 char obe_root_ds[MAXPATHLEN]; 613 char nbe_root_ds[MAXPATHLEN]; 614 char ss[MAXPATHLEN]; 615 char *new_mp = NULL; 616 char *obe_name = NULL; 617 boolean_t autoname = B_FALSE; 618 boolean_t be_created = B_FALSE; 619 int i; 620 int zret; 621 int ret = BE_SUCCESS; 622 struct be_defaults be_defaults; 623 624 /* Initialize libzfs handle */ 625 if (!be_zfs_init()) 626 return (BE_ERR_INIT); 627 628 /* Get original BE name */ 629 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 630 BE_ATTR_ORIG_BE_NAME, DATA_TYPE_STRING, &obe_name, NULL) != 0) { 631 be_print_err(gettext("be_copy: failed to lookup " 632 "BE_ATTR_ORIG_BE_NAME attribute\n")); 633 return (BE_ERR_INVAL); 634 } 635 636 if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) { 637 return (ret); 638 } 639 640 be_get_defaults(&be_defaults); 641 642 /* If original BE name not provided, use current BE */ 643 if (obe_name != NULL) { 644 bt.obe_name = obe_name; 645 /* Validate original BE name */ 646 if (!be_valid_be_name(bt.obe_name)) { 647 be_print_err(gettext("be_copy: " 648 "invalid BE name %s\n"), bt.obe_name); 649 return (BE_ERR_INVAL); 650 } 651 } 652 653 if (be_defaults.be_deflt_rpool_container) { 654 if ((zphp = zpool_open(g_zfs, bt.obe_zpool)) == NULL) { 655 be_print_err(gettext("be_get_node_data: failed to " 656 "open rpool (%s): %s\n"), bt.obe_zpool, 657 libzfs_error_description(g_zfs)); 658 return (zfs_err_to_be_err(g_zfs)); 659 } 660 if (be_find_zpool_callback(zphp, &bt) == 0) { 661 return (BE_ERR_BE_NOENT); 662 } 663 } else { 664 /* Find which zpool obe_name lives in */ 665 if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 666 0) { 667 be_print_err(gettext("be_copy: failed to " 668 "find zpool for BE (%s)\n"), bt.obe_name); 669 return (BE_ERR_BE_NOENT); 670 } else if (zret < 0) { 671 be_print_err(gettext("be_copy: " 672 "zpool_iter failed: %s\n"), 673 libzfs_error_description(g_zfs)); 674 return (zfs_err_to_be_err(g_zfs)); 675 } 676 } 677 678 /* Get snapshot name of original BE if one was provided */ 679 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 680 BE_ATTR_SNAP_NAME, DATA_TYPE_STRING, &bt.obe_snap_name, NULL) 681 != 0) { 682 be_print_err(gettext("be_copy: failed to lookup " 683 "BE_ATTR_SNAP_NAME attribute\n")); 684 return (BE_ERR_INVAL); 685 } 686 687 /* Get new BE name */ 688 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 689 BE_ATTR_NEW_BE_NAME, DATA_TYPE_STRING, &bt.nbe_name, NULL) 690 != 0) { 691 be_print_err(gettext("be_copy: failed to lookup " 692 "BE_ATTR_NEW_BE_NAME attribute\n")); 693 return (BE_ERR_INVAL); 694 } 695 696 /* Get zpool name to create new BE in */ 697 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 698 BE_ATTR_NEW_BE_POOL, DATA_TYPE_STRING, &bt.nbe_zpool, NULL) != 0) { 699 be_print_err(gettext("be_copy: failed to lookup " 700 "BE_ATTR_NEW_BE_POOL attribute\n")); 701 return (BE_ERR_INVAL); 702 } 703 704 /* Get new BE's description if one was provided */ 705 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 706 BE_ATTR_NEW_BE_DESC, DATA_TYPE_STRING, &bt.nbe_desc, NULL) != 0) { 707 be_print_err(gettext("be_copy: failed to lookup " 708 "BE_ATTR_NEW_BE_DESC attribute\n")); 709 return (BE_ERR_INVAL); 710 } 711 712 /* Get BE policy to create this snapshot under */ 713 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 714 BE_ATTR_POLICY, DATA_TYPE_STRING, &bt.policy, NULL) != 0) { 715 be_print_err(gettext("be_copy: failed to lookup " 716 "BE_ATTR_POLICY attribute\n")); 717 return (BE_ERR_INVAL); 718 } 719 720 /* 721 * Create property list for new BE root dataset. If some 722 * zfs properties were already provided by the caller, dup 723 * that list. Otherwise initialize a new property list. 724 */ 725 if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, 726 BE_ATTR_ZFS_PROPERTIES, DATA_TYPE_NVLIST, &zfs_props, NULL) 727 != 0) { 728 be_print_err(gettext("be_copy: failed to lookup " 729 "BE_ATTR_ZFS_PROPERTIES attribute\n")); 730 return (BE_ERR_INVAL); 731 } 732 if (zfs_props != NULL) { 733 /* Make sure its a unique nvlist */ 734 if (!(zfs_props->nvl_nvflag & NV_UNIQUE_NAME) && 735 !(zfs_props->nvl_nvflag & NV_UNIQUE_NAME_TYPE)) { 736 be_print_err(gettext("be_copy: ZFS property list " 737 "not unique\n")); 738 return (BE_ERR_INVAL); 739 } 740 741 /* Dup the list */ 742 if (nvlist_dup(zfs_props, &bt.nbe_zfs_props, 0) != 0) { 743 be_print_err(gettext("be_copy: " 744 "failed to dup ZFS property list\n")); 745 return (BE_ERR_NOMEM); 746 } 747 } else { 748 /* Initialize new nvlist */ 749 if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) { 750 be_print_err(gettext("be_copy: internal " 751 "error: out of memory\n")); 752 return (BE_ERR_NOMEM); 753 } 754 } 755 756 /* 757 * If new BE name provided, validate the BE name and then verify 758 * that new BE name doesn't already exist in some pool. 759 */ 760 if (bt.nbe_name) { 761 /* Validate original BE name */ 762 if (!be_valid_be_name(bt.nbe_name)) { 763 be_print_err(gettext("be_copy: " 764 "invalid BE name %s\n"), bt.nbe_name); 765 ret = BE_ERR_INVAL; 766 goto done; 767 } 768 769 /* Verify it doesn't already exist */ 770 if (getzoneid() == GLOBAL_ZONEID) { 771 if ((zret = zpool_iter(g_zfs, be_exists_callback, 772 bt.nbe_name)) > 0) { 773 be_print_err(gettext("be_copy: BE (%s) already " 774 "exists\n"), bt.nbe_name); 775 ret = BE_ERR_BE_EXISTS; 776 goto done; 777 } else if (zret < 0) { 778 be_print_err(gettext("be_copy: zpool_iter " 779 "failed: %s\n"), 780 libzfs_error_description(g_zfs)); 781 ret = zfs_err_to_be_err(g_zfs); 782 goto done; 783 } 784 } else { 785 be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds, 786 sizeof (nbe_root_ds)); 787 if (zfs_dataset_exists(g_zfs, nbe_root_ds, 788 ZFS_TYPE_FILESYSTEM)) { 789 be_print_err(gettext("be_copy: BE (%s) already " 790 "exists\n"), bt.nbe_name); 791 ret = BE_ERR_BE_EXISTS; 792 goto done; 793 } 794 } 795 } else { 796 /* 797 * If an auto named BE is desired, it must be in the same 798 * pool is the original BE. 799 */ 800 if (bt.nbe_zpool != NULL) { 801 be_print_err(gettext("be_copy: cannot specify pool " 802 "name when creating an auto named BE\n")); 803 ret = BE_ERR_INVAL; 804 goto done; 805 } 806 807 /* 808 * Generate auto named BE 809 */ 810 if ((bt.nbe_name = be_auto_be_name(bt.obe_name)) 811 == NULL) { 812 be_print_err(gettext("be_copy: " 813 "failed to generate auto BE name\n")); 814 ret = BE_ERR_AUTONAME; 815 goto done; 816 } 817 818 autoname = B_TRUE; 819 } 820 821 /* 822 * If zpool name to create new BE in is not provided, 823 * create new BE in original BE's pool. 824 */ 825 if (bt.nbe_zpool == NULL) { 826 bt.nbe_zpool = bt.obe_zpool; 827 } 828 829 /* Get root dataset names for obe_name and nbe_name */ 830 be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds, 831 sizeof (obe_root_ds)); 832 be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds, 833 sizeof (nbe_root_ds)); 834 835 bt.obe_root_ds = obe_root_ds; 836 bt.nbe_root_ds = nbe_root_ds; 837 838 /* 839 * If an existing snapshot name has been provided to create from, 840 * verify that it exists for the original BE's root dataset. 841 */ 842 if (bt.obe_snap_name != NULL) { 843 844 /* Generate dataset name for snapshot to use. */ 845 (void) snprintf(ss, sizeof (ss), "%s@%s", bt.obe_root_ds, 846 bt.obe_snap_name); 847 848 /* Verify snapshot exists */ 849 if (!zfs_dataset_exists(g_zfs, ss, ZFS_TYPE_SNAPSHOT)) { 850 be_print_err(gettext("be_copy: " 851 "snapshot does not exist (%s): %s\n"), ss, 852 libzfs_error_description(g_zfs)); 853 ret = BE_ERR_SS_NOENT; 854 goto done; 855 } 856 } else { 857 /* 858 * Else snapshot name was not provided, generate an 859 * auto named snapshot to use as its origin. 860 */ 861 if ((ret = _be_create_snapshot(bt.obe_name, 862 &bt.obe_snap_name, bt.policy)) != BE_SUCCESS) { 863 be_print_err(gettext("be_copy: " 864 "failed to create auto named snapshot\n")); 865 goto done; 866 } 867 868 if (nvlist_add_string(be_attrs, BE_ATTR_SNAP_NAME, 869 bt.obe_snap_name) != 0) { 870 be_print_err(gettext("be_copy: " 871 "failed to add snap name to be_attrs\n")); 872 ret = BE_ERR_NOMEM; 873 goto done; 874 } 875 } 876 877 /* Get handle to original BE's root dataset. */ 878 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM)) 879 == NULL) { 880 be_print_err(gettext("be_copy: failed to " 881 "open BE root dataset (%s): %s\n"), bt.obe_root_ds, 882 libzfs_error_description(g_zfs)); 883 ret = zfs_err_to_be_err(g_zfs); 884 goto done; 885 } 886 887 /* If original BE is currently mounted, record its altroot. */ 888 if (zfs_is_mounted(zhp, &bt.obe_altroot) && bt.obe_altroot == NULL) { 889 be_print_err(gettext("be_copy: failed to " 890 "get altroot of mounted BE %s: %s\n"), 891 bt.obe_name, libzfs_error_description(g_zfs)); 892 ret = zfs_err_to_be_err(g_zfs); 893 goto done; 894 } 895 896 if (strcmp(bt.obe_zpool, bt.nbe_zpool) == 0) { 897 898 /* Do clone */ 899 900 /* 901 * Iterate through original BE's datasets and clone 902 * them to create new BE. This call will end up closing 903 * the zfs handle passed in whether it succeeds for fails. 904 */ 905 if ((ret = be_clone_fs_callback(zhp, &bt)) != 0) { 906 zhp = NULL; 907 /* Creating clone BE failed */ 908 if (!autoname || ret != BE_ERR_BE_EXISTS) { 909 be_print_err(gettext("be_copy: " 910 "failed to clone new BE (%s) from " 911 "orig BE (%s)\n"), 912 bt.nbe_name, bt.obe_name); 913 ret = BE_ERR_CLONE; 914 goto done; 915 } 916 917 /* 918 * We failed to create the new BE because a BE with 919 * the auto-name we generated above has since come 920 * into existence. Regenerate a new auto-name 921 * and retry. 922 */ 923 for (i = 1; i < BE_AUTO_NAME_MAX_TRY; i++) { 924 925 /* Sleep 1 before retrying */ 926 (void) sleep(1); 927 928 /* Generate new auto BE name */ 929 free(bt.nbe_name); 930 if ((bt.nbe_name = be_auto_be_name(bt.obe_name)) 931 == NULL) { 932 be_print_err(gettext("be_copy: " 933 "failed to generate auto " 934 "BE name\n")); 935 ret = BE_ERR_AUTONAME; 936 goto done; 937 } 938 939 /* 940 * Regenerate string for new BE's 941 * root dataset name 942 */ 943 be_make_root_ds(bt.nbe_zpool, bt.nbe_name, 944 nbe_root_ds, sizeof (nbe_root_ds)); 945 bt.nbe_root_ds = nbe_root_ds; 946 947 /* 948 * Get handle to original BE's root dataset. 949 */ 950 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, 951 ZFS_TYPE_FILESYSTEM)) == NULL) { 952 be_print_err(gettext("be_copy: " 953 "failed to open BE root dataset " 954 "(%s): %s\n"), bt.obe_root_ds, 955 libzfs_error_description(g_zfs)); 956 ret = zfs_err_to_be_err(g_zfs); 957 goto done; 958 } 959 960 /* 961 * Try to clone the BE again. This 962 * call will end up closing the zfs 963 * handle passed in whether it 964 * succeeds or fails. 965 */ 966 ret = be_clone_fs_callback(zhp, &bt); 967 zhp = NULL; 968 if (ret == 0) { 969 break; 970 } else if (ret != BE_ERR_BE_EXISTS) { 971 be_print_err(gettext("be_copy: " 972 "failed to clone new BE " 973 "(%s) from orig BE (%s)\n"), 974 bt.nbe_name, bt.obe_name); 975 ret = BE_ERR_CLONE; 976 goto done; 977 } 978 } 979 980 /* 981 * If we've exhausted the maximum number of 982 * tries, free the auto BE name and return 983 * error. 984 */ 985 if (i == BE_AUTO_NAME_MAX_TRY) { 986 be_print_err(gettext("be_copy: failed " 987 "to create unique auto BE name\n")); 988 free(bt.nbe_name); 989 bt.nbe_name = NULL; 990 ret = BE_ERR_AUTONAME; 991 goto done; 992 } 993 } 994 zhp = NULL; 995 996 } else { 997 998 /* Do copy (i.e. send BE datasets via zfs_send/recv) */ 999 1000 /* 1001 * Verify BE container dataset in nbe_zpool exists. 1002 * If not, create it. 1003 */ 1004 if (!be_create_container_ds(bt.nbe_zpool)) { 1005 ret = BE_ERR_CREATDS; 1006 goto done; 1007 } 1008 1009 /* 1010 * Iterate through original BE's datasets and send 1011 * them to the other pool. This call will end up closing 1012 * the zfs handle passed in whether it succeeds or fails. 1013 */ 1014 if ((ret = be_send_fs_callback(zhp, &bt)) != 0) { 1015 be_print_err(gettext("be_copy: failed to " 1016 "send BE (%s) to pool (%s)\n"), bt.obe_name, 1017 bt.nbe_zpool); 1018 ret = BE_ERR_COPY; 1019 zhp = NULL; 1020 goto done; 1021 } 1022 zhp = NULL; 1023 } 1024 1025 /* 1026 * Set flag to note that the dataset(s) for the new BE have been 1027 * successfully created so that if a failure happens from this point 1028 * on, we know to cleanup these datasets. 1029 */ 1030 be_created = B_TRUE; 1031 1032 /* 1033 * Validate that the new BE is mountable. 1034 * Do not attempt to mount non-global zone datasets 1035 * since they are not cloned yet. 1036 */ 1037 if ((ret = _be_mount(bt.nbe_name, &new_mp, BE_MOUNT_FLAG_NO_ZONES)) 1038 != BE_SUCCESS) { 1039 be_print_err(gettext("be_copy: failed to " 1040 "mount newly created BE\n")); 1041 (void) _be_unmount(bt.nbe_name, 0); 1042 goto done; 1043 } 1044 1045 /* Set UUID for new BE */ 1046 if (getzoneid() == GLOBAL_ZONEID) { 1047 if (be_set_uuid(bt.nbe_root_ds) != BE_SUCCESS) { 1048 be_print_err(gettext("be_copy: failed to " 1049 "set uuid for new BE\n")); 1050 } 1051 } else { 1052 if ((ret = be_zone_get_parent_uuid(bt.obe_root_ds, 1053 &parent_uu)) != BE_SUCCESS) { 1054 be_print_err(gettext("be_copy: failed to get " 1055 "parentbe uuid from orig BE\n")); 1056 ret = BE_ERR_ZONE_NO_PARENTBE; 1057 goto done; 1058 } else if ((ret = be_zone_set_parent_uuid(bt.nbe_root_ds, 1059 parent_uu)) != BE_SUCCESS) { 1060 be_print_err(gettext("be_copy: failed to set " 1061 "parentbe uuid for newly created BE\n")); 1062 goto done; 1063 } 1064 } 1065 1066 /* 1067 * Process zones outside of the private BE namespace. 1068 * This has to be done here because we need the uuid set in the 1069 * root dataset of the new BE. The uuid is use to set the parentbe 1070 * property for the new zones datasets. 1071 */ 1072 if (getzoneid() == GLOBAL_ZONEID && 1073 be_get_uuid(bt.obe_root_ds, &uu) == BE_SUCCESS) { 1074 if ((ret = be_copy_zones(bt.obe_name, bt.obe_root_ds, 1075 bt.nbe_root_ds)) != BE_SUCCESS) { 1076 be_print_err(gettext("be_copy: failed to process " 1077 "zones\n")); 1078 goto done; 1079 } 1080 } 1081 1082 /* 1083 * Generate a list of file systems from the original BE that are 1084 * legacy mounted. We use this list to determine which entries in 1085 * vfstab we need to update for the new BE we've just created. 1086 */ 1087 if ((ret = be_get_legacy_fs(bt.obe_name, bt.obe_root_ds, NULL, NULL, 1088 &fld)) != BE_SUCCESS) { 1089 be_print_err(gettext("be_copy: failed to " 1090 "get legacy mounted file system list for %s\n"), 1091 bt.obe_name); 1092 goto done; 1093 } 1094 1095 /* 1096 * Update new BE's vfstab. 1097 */ 1098 if ((ret = be_update_vfstab(bt.nbe_name, bt.obe_zpool, bt.nbe_zpool, 1099 &fld, new_mp)) != BE_SUCCESS) { 1100 be_print_err(gettext("be_copy: failed to " 1101 "update new BE's vfstab (%s)\n"), bt.nbe_name); 1102 goto done; 1103 } 1104 1105 /* Unmount the new BE */ 1106 if ((ret = _be_unmount(bt.nbe_name, 0)) != BE_SUCCESS) { 1107 be_print_err(gettext("be_copy: failed to " 1108 "unmount newly created BE\n")); 1109 goto done; 1110 } 1111 1112 /* 1113 * Add boot menu entry for newly created clone 1114 */ 1115 if (getzoneid() == GLOBAL_ZONEID && 1116 (ret = be_append_menu(bt.nbe_name, bt.nbe_zpool, 1117 NULL, bt.obe_root_ds, bt.nbe_desc)) != BE_SUCCESS) { 1118 be_print_err(gettext("be_copy: failed to " 1119 "add BE (%s) to boot menu\n"), bt.nbe_name); 1120 goto done; 1121 } 1122 1123 /* 1124 * If we succeeded in creating an auto named BE, set its policy 1125 * type and return the auto generated name to the caller by storing 1126 * it in the nvlist passed in by the caller. 1127 */ 1128 if (autoname) { 1129 /* Get handle to new BE's root dataset. */ 1130 if ((zhp = zfs_open(g_zfs, bt.nbe_root_ds, 1131 ZFS_TYPE_FILESYSTEM)) == NULL) { 1132 be_print_err(gettext("be_copy: failed to " 1133 "open BE root dataset (%s): %s\n"), bt.nbe_root_ds, 1134 libzfs_error_description(g_zfs)); 1135 ret = zfs_err_to_be_err(g_zfs); 1136 goto done; 1137 } 1138 1139 /* 1140 * Set the policy type property into the new BE's root dataset 1141 */ 1142 if (bt.policy == NULL) { 1143 /* If no policy type provided, use default type */ 1144 bt.policy = be_default_policy(); 1145 } 1146 1147 if (zfs_prop_set(zhp, BE_POLICY_PROPERTY, bt.policy) != 0) { 1148 be_print_err(gettext("be_copy: failed to " 1149 "set BE policy for %s: %s\n"), bt.nbe_name, 1150 libzfs_error_description(g_zfs)); 1151 ret = zfs_err_to_be_err(g_zfs); 1152 goto done; 1153 } 1154 1155 /* 1156 * Return the auto generated name to the caller 1157 */ 1158 if (bt.nbe_name) { 1159 if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_NAME, 1160 bt.nbe_name) != 0) { 1161 be_print_err(gettext("be_copy: failed to " 1162 "add snap name to be_attrs\n")); 1163 } 1164 } 1165 } 1166 1167 done: 1168 ZFS_CLOSE(zhp); 1169 be_free_fs_list(&fld); 1170 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 nvlist_free(bt.nbe_zfs_props); 2094 goto done; 2095 } 2096 /* 2097 * We failed to create the new zone BE because a zone 2098 * BE with the auto-name we generated above has since 2099 * come into existence. Regenerate a new auto-name 2100 * and retry. 2101 */ 2102 for (num_retries = 1; 2103 num_retries < BE_AUTO_NAME_MAX_TRY; 2104 num_retries++) { 2105 2106 /* Sleep 1 before retrying */ 2107 (void) sleep(1); 2108 2109 /* Generate new auto zone BE name */ 2110 free(new_zone_be_name); 2111 if ((new_zone_be_name = be_auto_zone_be_name( 2112 zone_container_ds, 2113 zone_be_name)) == NULL) { 2114 be_print_err(gettext("be_copy_zones: " 2115 "failed to generate auto name " 2116 "for zone BE.\n")); 2117 ret = BE_ERR_AUTONAME; 2118 nvlist_free(bt.nbe_zfs_props); 2119 goto done; 2120 } 2121 2122 (void) snprintf(new_zoneroot_ds, 2123 sizeof (new_zoneroot_ds), 2124 "%s/%s", zone_container_ds, 2125 new_zone_be_name); 2126 bt.nbe_name = new_zone_be_name; 2127 bt.nbe_root_ds = new_zoneroot_ds; 2128 2129 /* 2130 * Get handle to original zone BE's root 2131 * dataset. 2132 */ 2133 if ((z_zhp = zfs_open(g_zfs, zoneroot_ds, 2134 ZFS_TYPE_FILESYSTEM)) == NULL) { 2135 be_print_err(gettext("be_copy_zones: " 2136 "failed to open zone root " 2137 "dataset (%s): %s\n"), 2138 zoneroot_ds, 2139 libzfs_error_description(g_zfs)); 2140 ret = zfs_err_to_be_err(g_zfs); 2141 nvlist_free(bt.nbe_zfs_props); 2142 goto done; 2143 } 2144 2145 /* 2146 * Try to clone the zone BE again. This 2147 * call will end up closing the zfs 2148 * handle passed in whether it 2149 * succeeds or fails. 2150 */ 2151 iret = be_clone_fs_callback(z_zhp, &bt); 2152 z_zhp = NULL; 2153 if (iret == 0) { 2154 break; 2155 } else if (iret != BE_ERR_BE_EXISTS) { 2156 be_print_err(gettext("be_copy_zones: " 2157 "failed to create zone BE clone " 2158 "for new zone BE %s\n"), 2159 new_zone_be_name); 2160 ret = iret; 2161 nvlist_free(bt.nbe_zfs_props); 2162 goto done; 2163 } 2164 } 2165 /* 2166 * If we've exhausted the maximum number of 2167 * tries, free the auto zone BE name and return 2168 * error. 2169 */ 2170 if (num_retries == BE_AUTO_NAME_MAX_TRY) { 2171 be_print_err(gettext("be_copy_zones: failed " 2172 "to create a unique auto zone BE name\n")); 2173 free(bt.nbe_name); 2174 bt.nbe_name = NULL; 2175 ret = BE_ERR_AUTONAME; 2176 nvlist_free(bt.nbe_zfs_props); 2177 goto done; 2178 } 2179 } 2180 2181 nvlist_free(bt.nbe_zfs_props); 2182 2183 z_zhp = NULL; 2184 2185 if ((z_zhp = zfs_open(g_zfs, new_zoneroot_ds, 2186 ZFS_TYPE_FILESYSTEM)) == NULL) { 2187 be_print_err(gettext("be_copy_zones: " 2188 "failed to open the new zone BE root dataset " 2189 "(%s): %s\n"), new_zoneroot_ds, 2190 libzfs_error_description(g_zfs)); 2191 ret = zfs_err_to_be_err(g_zfs); 2192 goto done; 2193 } 2194 2195 if (zfs_prop_set(z_zhp, BE_ZONE_PARENTBE_PROPERTY, 2196 uu_string) != 0) { 2197 be_print_err(gettext("be_copy_zones: " 2198 "failed to set parentbe property\n")); 2199 ZFS_CLOSE(z_zhp); 2200 ret = zfs_err_to_be_err(g_zfs); 2201 goto done; 2202 } 2203 2204 if (zfs_prop_set(z_zhp, BE_ZONE_ACTIVE_PROPERTY, "on") != 0) { 2205 be_print_err(gettext("be_copy_zones: " 2206 "failed to set active property\n")); 2207 ZFS_CLOSE(z_zhp); 2208 ret = zfs_err_to_be_err(g_zfs); 2209 goto done; 2210 } 2211 2212 /* 2213 * Generate a list of file systems from the original 2214 * zone BE that are legacy mounted. We use this list 2215 * to determine which entries in the vfstab we need to 2216 * update for the new zone BE we've just created. 2217 */ 2218 if ((ret = be_get_legacy_fs(obe_name, obe_root_ds, 2219 zoneroot_ds, zoneroot, &fld)) != BE_SUCCESS) { 2220 be_print_err(gettext("be_copy_zones: " 2221 "failed to get legacy mounted file system " 2222 "list for zone %s\n"), zonename); 2223 ZFS_CLOSE(z_zhp); 2224 goto done; 2225 } 2226 2227 /* 2228 * Update new zone BE's vfstab. 2229 */ 2230 if ((ret = be_update_zone_vfstab(z_zhp, bt.nbe_name, 2231 zonepath_ds, zonepath_ds, &fld)) != BE_SUCCESS) { 2232 be_print_err(gettext("be_copy_zones: " 2233 "failed to update new BE's vfstab (%s)\n"), 2234 bt.nbe_name); 2235 ZFS_CLOSE(z_zhp); 2236 be_free_fs_list(&fld); 2237 goto done; 2238 } 2239 2240 be_free_fs_list(&fld); 2241 ZFS_CLOSE(z_zhp); 2242 } 2243 2244 done: 2245 free(snap_name); 2246 if (brands != NULL) 2247 z_free_brand_list(brands); 2248 if (zlist != NULL) 2249 z_free_zone_list(zlist); 2250 2251 if (mounted_here) 2252 (void) _be_unmount(obe_name, 0); 2253 2254 ZFS_CLOSE(obe_zhp); 2255 return (ret); 2256 } 2257 2258 /* 2259 * Function: be_clone_fs_callback 2260 * Description: Callback function used to iterate through a BE's filesystems 2261 * to clone them for the new BE. 2262 * Parameters: 2263 * zhp - zfs_handle_t pointer for the filesystem being processed. 2264 * data - be_transaction_data_t pointer providing information 2265 * about original BE and new BE. 2266 * Return: 2267 * 0 - Success 2268 * be_errno_t - Failure 2269 * Scope: 2270 * Private 2271 */ 2272 static int 2273 be_clone_fs_callback(zfs_handle_t *zhp, void *data) 2274 { 2275 be_transaction_data_t *bt = data; 2276 zfs_handle_t *zhp_ss = NULL; 2277 char prop_buf[MAXPATHLEN]; 2278 char zhp_name[ZFS_MAX_DATASET_NAME_LEN]; 2279 char clone_ds[MAXPATHLEN]; 2280 char ss[MAXPATHLEN]; 2281 int ret = 0; 2282 2283 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop_buf, 2284 ZFS_MAXPROPLEN, NULL, NULL, 0, B_FALSE) != 0) { 2285 be_print_err(gettext("be_clone_fs_callback: " 2286 "failed to get dataset mountpoint (%s): %s\n"), 2287 zfs_get_name(zhp), libzfs_error_description(g_zfs)); 2288 ret = zfs_err_to_be_err(g_zfs); 2289 ZFS_CLOSE(zhp); 2290 return (ret); 2291 } 2292 2293 if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) != 0 && 2294 strcmp(prop_buf, "legacy") != 0) { 2295 /* 2296 * Since zfs can't currently handle setting the 2297 * mountpoint for a zoned dataset we'll have to skip 2298 * this dataset. This is because the mountpoint is not 2299 * set to "legacy". 2300 */ 2301 goto zoned; 2302 } 2303 /* 2304 * Get a copy of the dataset name from the zfs handle 2305 */ 2306 (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name)); 2307 2308 /* 2309 * Get the clone dataset name and prepare the zfs properties for it. 2310 */ 2311 if ((ret = be_prep_clone_send_fs(zhp, bt, clone_ds, 2312 sizeof (clone_ds))) != BE_SUCCESS) { 2313 ZFS_CLOSE(zhp); 2314 return (ret); 2315 } 2316 2317 /* 2318 * Generate the name of the snapshot to use. 2319 */ 2320 (void) snprintf(ss, sizeof (ss), "%s@%s", zhp_name, 2321 bt->obe_snap_name); 2322 2323 /* 2324 * Get handle to snapshot. 2325 */ 2326 if ((zhp_ss = zfs_open(g_zfs, ss, ZFS_TYPE_SNAPSHOT)) == NULL) { 2327 be_print_err(gettext("be_clone_fs_callback: " 2328 "failed to get handle to snapshot (%s): %s\n"), ss, 2329 libzfs_error_description(g_zfs)); 2330 ret = zfs_err_to_be_err(g_zfs); 2331 ZFS_CLOSE(zhp); 2332 return (ret); 2333 } 2334 2335 /* 2336 * Clone the dataset. 2337 */ 2338 if (zfs_clone(zhp_ss, clone_ds, bt->nbe_zfs_props) != 0) { 2339 be_print_err(gettext("be_clone_fs_callback: " 2340 "failed to create clone dataset (%s): %s\n"), 2341 clone_ds, libzfs_error_description(g_zfs)); 2342 2343 ZFS_CLOSE(zhp_ss); 2344 ZFS_CLOSE(zhp); 2345 2346 return (zfs_err_to_be_err(g_zfs)); 2347 } 2348 2349 ZFS_CLOSE(zhp_ss); 2350 2351 zoned: 2352 /* 2353 * Iterate through zhp's children datasets (if any) 2354 * and clone them accordingly. 2355 */ 2356 if ((ret = zfs_iter_filesystems(zhp, be_clone_fs_callback, bt)) != 0) { 2357 /* 2358 * Error occurred while processing a child dataset. 2359 * Destroy this dataset and return error. 2360 */ 2361 zfs_handle_t *d_zhp = NULL; 2362 2363 ZFS_CLOSE(zhp); 2364 2365 if ((d_zhp = zfs_open(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM)) 2366 == NULL) { 2367 return (ret); 2368 } 2369 2370 (void) zfs_destroy(d_zhp, B_FALSE); 2371 ZFS_CLOSE(d_zhp); 2372 return (ret); 2373 } 2374 2375 ZFS_CLOSE(zhp); 2376 return (0); 2377 } 2378 2379 /* 2380 * Function: be_send_fs_callback 2381 * Description: Callback function used to iterate through a BE's filesystems 2382 * to copy them for the new BE. 2383 * Parameters: 2384 * zhp - zfs_handle_t pointer for the filesystem being processed. 2385 * data - be_transaction_data_t pointer providing information 2386 * about original BE and new BE. 2387 * Return: 2388 * 0 - Success 2389 * be_errnot_t - Failure 2390 * Scope: 2391 * Private 2392 */ 2393 static int 2394 be_send_fs_callback(zfs_handle_t *zhp, void *data) 2395 { 2396 be_transaction_data_t *bt = data; 2397 recvflags_t flags = { 0 }; 2398 char zhp_name[ZFS_MAX_DATASET_NAME_LEN]; 2399 char clone_ds[MAXPATHLEN]; 2400 sendflags_t send_flags = { 0 }; 2401 int pid, status, retval; 2402 int srpipe[2]; 2403 int ret = 0; 2404 2405 /* 2406 * Get a copy of the dataset name from the zfs handle 2407 */ 2408 (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name)); 2409 2410 /* 2411 * Get the clone dataset name and prepare the zfs properties for it. 2412 */ 2413 if ((ret = be_prep_clone_send_fs(zhp, bt, clone_ds, 2414 sizeof (clone_ds))) != BE_SUCCESS) { 2415 ZFS_CLOSE(zhp); 2416 return (ret); 2417 } 2418 2419 /* 2420 * Create the new dataset. 2421 */ 2422 if (zfs_create(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM, bt->nbe_zfs_props) 2423 != 0) { 2424 be_print_err(gettext("be_send_fs_callback: " 2425 "failed to create new dataset '%s': %s\n"), 2426 clone_ds, libzfs_error_description(g_zfs)); 2427 ret = zfs_err_to_be_err(g_zfs); 2428 ZFS_CLOSE(zhp); 2429 return (ret); 2430 } 2431 2432 /* 2433 * Destination file system is already created 2434 * hence we need to set the force flag on 2435 */ 2436 flags.force = B_TRUE; 2437 2438 /* 2439 * Initiate the pipe to be used for the send and recv 2440 */ 2441 if (pipe(srpipe) != 0) { 2442 int err = errno; 2443 be_print_err(gettext("be_send_fs_callback: failed to " 2444 "open pipe\n")); 2445 ZFS_CLOSE(zhp); 2446 return (errno_to_be_err(err)); 2447 } 2448 2449 /* 2450 * Fork off a child to send the dataset 2451 */ 2452 if ((pid = fork()) == -1) { 2453 int err = errno; 2454 be_print_err(gettext("be_send_fs_callback: failed to fork\n")); 2455 (void) close(srpipe[0]); 2456 (void) close(srpipe[1]); 2457 ZFS_CLOSE(zhp); 2458 return (errno_to_be_err(err)); 2459 } else if (pid == 0) { /* child process */ 2460 (void) close(srpipe[0]); 2461 2462 /* Send dataset */ 2463 if (zfs_send(zhp, NULL, bt->obe_snap_name, &send_flags, 2464 srpipe[1], NULL, NULL, NULL) != 0) { 2465 _exit(1); 2466 } 2467 ZFS_CLOSE(zhp); 2468 2469 _exit(0); 2470 } 2471 2472 (void) close(srpipe[1]); 2473 2474 /* Receive dataset */ 2475 if (zfs_receive(g_zfs, clone_ds, NULL, &flags, srpipe[0], NULL) != 0) { 2476 be_print_err(gettext("be_send_fs_callback: failed to " 2477 "recv dataset (%s)\n"), clone_ds); 2478 } 2479 (void) close(srpipe[0]); 2480 2481 /* wait for child to exit */ 2482 do { 2483 retval = waitpid(pid, &status, 0); 2484 if (retval == -1) { 2485 status = 0; 2486 } 2487 } while (retval != pid); 2488 2489 if (WEXITSTATUS(status) != 0) { 2490 be_print_err(gettext("be_send_fs_callback: failed to " 2491 "send dataset (%s)\n"), zhp_name); 2492 ZFS_CLOSE(zhp); 2493 return (BE_ERR_ZFS); 2494 } 2495 2496 2497 /* 2498 * Iterate through zhp's children datasets (if any) 2499 * and send them accordingly. 2500 */ 2501 if ((ret = zfs_iter_filesystems(zhp, be_send_fs_callback, bt)) != 0) { 2502 /* 2503 * Error occurred while processing a child dataset. 2504 * Destroy this dataset and return error. 2505 */ 2506 zfs_handle_t *d_zhp = NULL; 2507 2508 ZFS_CLOSE(zhp); 2509 2510 if ((d_zhp = zfs_open(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM)) 2511 == NULL) { 2512 return (ret); 2513 } 2514 2515 (void) zfs_destroy(d_zhp, B_FALSE); 2516 ZFS_CLOSE(d_zhp); 2517 return (ret); 2518 } 2519 2520 ZFS_CLOSE(zhp); 2521 return (0); 2522 } 2523 2524 /* 2525 * Function: be_destroy_callback 2526 * Description: Callback function used to destroy a BEs children datasets 2527 * and snapshots. 2528 * Parameters: 2529 * zhp - zfs_handle_t pointer to the filesystem being processed. 2530 * data - Not used. 2531 * Returns: 2532 * 0 - Success 2533 * be_errno_t - Failure 2534 * Scope: 2535 * Private 2536 */ 2537 static int 2538 be_destroy_callback(zfs_handle_t *zhp, void *data) 2539 { 2540 be_destroy_data_t *dd = data; 2541 int ret = 0; 2542 2543 /* 2544 * Iterate down this file system's hierarchical children 2545 * and destroy them first. 2546 */ 2547 if ((ret = zfs_iter_filesystems(zhp, be_destroy_callback, dd)) != 0) { 2548 ZFS_CLOSE(zhp); 2549 return (ret); 2550 } 2551 2552 if (dd->destroy_snaps) { 2553 /* 2554 * Iterate through this file system's snapshots and 2555 * destroy them before destroying the file system itself. 2556 */ 2557 if ((ret = zfs_iter_snapshots(zhp, B_FALSE, be_destroy_callback, 2558 dd)) 2559 != 0) { 2560 ZFS_CLOSE(zhp); 2561 return (ret); 2562 } 2563 } 2564 2565 /* Attempt to unmount the dataset before destroying it */ 2566 if (dd->force_unmount) { 2567 if ((ret = zfs_unmount(zhp, NULL, MS_FORCE)) != 0) { 2568 be_print_err(gettext("be_destroy_callback: " 2569 "failed to unmount %s: %s\n"), zfs_get_name(zhp), 2570 libzfs_error_description(g_zfs)); 2571 ret = zfs_err_to_be_err(g_zfs); 2572 ZFS_CLOSE(zhp); 2573 return (ret); 2574 } 2575 } 2576 2577 if (zfs_destroy(zhp, B_FALSE) != 0) { 2578 be_print_err(gettext("be_destroy_callback: " 2579 "failed to destroy %s: %s\n"), zfs_get_name(zhp), 2580 libzfs_error_description(g_zfs)); 2581 ret = zfs_err_to_be_err(g_zfs); 2582 ZFS_CLOSE(zhp); 2583 return (ret); 2584 } 2585 2586 ZFS_CLOSE(zhp); 2587 return (0); 2588 } 2589 2590 /* 2591 * Function: be_demote_callback 2592 * Description: This callback function is used to iterate through the file 2593 * systems of a BE, looking for the right clone to promote such 2594 * that this file system is left without any dependent clones. 2595 * If the file system has no dependent clones, it doesn't need 2596 * to get demoted, and the function will return success. 2597 * 2598 * The demotion will be done in two passes. The first pass 2599 * will attempt to find the youngest snapshot that has a clone 2600 * that is part of some other BE. The second pass will attempt 2601 * to find the youngest snapshot that has a clone that is not 2602 * part of a BE. Doing this helps ensure the aggregated set of 2603 * file systems that compose a BE stay coordinated wrt BE 2604 * snapshots and BE dependents. It also prevents a random user 2605 * generated clone of a BE dataset to become the parent of other 2606 * BE datasets after demoting this dataset. 2607 * 2608 * Parameters: 2609 * zhp - zfs_handle_t pointer to the current file system being 2610 * processed. 2611 * data - not used. 2612 * Return: 2613 * 0 - Success 2614 * be_errno_t - Failure 2615 * Scope: 2616 * Private 2617 */ 2618 static int 2619 /* LINTED */ 2620 be_demote_callback(zfs_handle_t *zhp, void *data) 2621 { 2622 be_demote_data_t dd = { 0 }; 2623 int i, ret = 0; 2624 2625 /* 2626 * Initialize be_demote_data for the first pass - this will find a 2627 * clone in another BE, if one exists. 2628 */ 2629 dd.find_in_BE = B_TRUE; 2630 2631 for (i = 0; i < 2; i++) { 2632 2633 if (zfs_iter_snapshots(zhp, B_FALSE, 2634 be_demote_find_clone_callback, &dd) != 0) { 2635 be_print_err(gettext("be_demote_callback: " 2636 "failed to iterate snapshots for %s: %s\n"), 2637 zfs_get_name(zhp), libzfs_error_description(g_zfs)); 2638 ret = zfs_err_to_be_err(g_zfs); 2639 ZFS_CLOSE(zhp); 2640 return (ret); 2641 } 2642 if (dd.clone_zhp != NULL) { 2643 /* Found the clone to promote. Promote it. */ 2644 if (zfs_promote(dd.clone_zhp) != 0) { 2645 be_print_err(gettext("be_demote_callback: " 2646 "failed to promote %s: %s\n"), 2647 zfs_get_name(dd.clone_zhp), 2648 libzfs_error_description(g_zfs)); 2649 ret = zfs_err_to_be_err(g_zfs); 2650 ZFS_CLOSE(dd.clone_zhp); 2651 ZFS_CLOSE(zhp); 2652 return (ret); 2653 } 2654 2655 ZFS_CLOSE(dd.clone_zhp); 2656 } 2657 2658 /* 2659 * Reinitialize be_demote_data for the second pass. 2660 * This will find a user created clone outside of any BE 2661 * namespace, if one exists. 2662 */ 2663 dd.clone_zhp = NULL; 2664 dd.origin_creation = 0; 2665 dd.snapshot = NULL; 2666 dd.find_in_BE = B_FALSE; 2667 } 2668 2669 /* Iterate down this file system's children and demote them */ 2670 if ((ret = zfs_iter_filesystems(zhp, be_demote_callback, NULL)) != 0) { 2671 ZFS_CLOSE(zhp); 2672 return (ret); 2673 } 2674 2675 ZFS_CLOSE(zhp); 2676 return (0); 2677 } 2678 2679 /* 2680 * Function: be_demote_find_clone_callback 2681 * Description: This callback function is used to iterate through the 2682 * snapshots of a dataset, looking for the youngest snapshot 2683 * that has a clone. If found, it returns a reference to the 2684 * clone back to the caller in the callback data. 2685 * Parameters: 2686 * zhp - zfs_handle_t pointer to current snapshot being looked at 2687 * data - be_demote_data_t pointer used to store the clone that 2688 * is found. 2689 * Returns: 2690 * 0 - Successfully iterated through all snapshots. 2691 * 1 - Failed to iterate through all snapshots. 2692 * Scope: 2693 * Private 2694 */ 2695 static int 2696 be_demote_find_clone_callback(zfs_handle_t *zhp, void *data) 2697 { 2698 be_demote_data_t *dd = data; 2699 time_t snap_creation; 2700 int zret = 0; 2701 2702 /* If snapshot has no clones, no need to look at it */ 2703 if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) == 0) { 2704 ZFS_CLOSE(zhp); 2705 return (0); 2706 } 2707 2708 dd->snapshot = zfs_get_name(zhp); 2709 2710 /* Get the creation time of this snapshot */ 2711 snap_creation = (time_t)zfs_prop_get_int(zhp, ZFS_PROP_CREATION); 2712 2713 /* 2714 * If this snapshot's creation time is greater than (or younger than) 2715 * the current youngest snapshot found, iterate this snapshot to 2716 * check if it has a clone that we're looking for. 2717 */ 2718 if (snap_creation >= dd->origin_creation) { 2719 /* 2720 * Iterate the dependents of this snapshot to find a 2721 * a clone that's a direct dependent. 2722 */ 2723 if ((zret = zfs_iter_dependents(zhp, B_FALSE, 2724 be_demote_get_one_clone, dd)) == -1) { 2725 be_print_err(gettext("be_demote_find_clone_callback: " 2726 "failed to iterate dependents of %s\n"), 2727 zfs_get_name(zhp)); 2728 ZFS_CLOSE(zhp); 2729 return (1); 2730 } else if (zret == 1) { 2731 /* 2732 * Found a clone, update the origin_creation time 2733 * in the callback data. 2734 */ 2735 dd->origin_creation = snap_creation; 2736 } 2737 } 2738 2739 ZFS_CLOSE(zhp); 2740 return (0); 2741 } 2742 2743 /* 2744 * Function: be_demote_get_one_clone 2745 * Description: This callback function is used to iterate through a 2746 * snapshot's dependencies to find a filesystem that is a 2747 * direct clone of the snapshot being iterated. 2748 * Parameters: 2749 * zhp - zfs_handle_t pointer to current dataset being looked at 2750 * data - be_demote_data_t pointer used to store the clone 2751 * that is found, and also provides flag to note 2752 * whether or not the clone filesystem being searched 2753 * for needs to be found in a BE dataset hierarchy. 2754 * Return: 2755 * 1 - Success, found clone and its also a BE's root dataset. 2756 * 0 - Failure, clone not found. 2757 * Scope: 2758 * Private 2759 */ 2760 static int 2761 be_demote_get_one_clone(zfs_handle_t *zhp, void *data) 2762 { 2763 be_demote_data_t *dd = data; 2764 char origin[ZFS_MAX_DATASET_NAME_LEN]; 2765 char ds_path[ZFS_MAX_DATASET_NAME_LEN]; 2766 2767 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 2768 ZFS_CLOSE(zhp); 2769 return (0); 2770 } 2771 2772 (void) strlcpy(ds_path, zfs_get_name(zhp), sizeof (ds_path)); 2773 2774 /* 2775 * Make sure this is a direct clone of the snapshot 2776 * we're iterating. 2777 */ 2778 if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL, 2779 NULL, 0, B_FALSE) != 0) { 2780 be_print_err(gettext("be_demote_get_one_clone: " 2781 "failed to get origin of %s: %s\n"), ds_path, 2782 libzfs_error_description(g_zfs)); 2783 ZFS_CLOSE(zhp); 2784 return (0); 2785 } 2786 if (strcmp(origin, dd->snapshot) != 0) { 2787 ZFS_CLOSE(zhp); 2788 return (0); 2789 } 2790 2791 if (dd->find_in_BE) { 2792 if ((zpool_iter(g_zfs, be_check_be_roots_callback, ds_path)) 2793 > 0) { 2794 if (dd->clone_zhp != NULL) 2795 ZFS_CLOSE(dd->clone_zhp); 2796 dd->clone_zhp = zhp; 2797 return (1); 2798 } 2799 2800 ZFS_CLOSE(zhp); 2801 return (0); 2802 } 2803 2804 if (dd->clone_zhp != NULL) 2805 ZFS_CLOSE(dd->clone_zhp); 2806 2807 dd->clone_zhp = zhp; 2808 return (1); 2809 } 2810 2811 /* 2812 * Function: be_get_snap 2813 * Description: This function takes a snapshot dataset name and separates 2814 * out the parent dataset portion from the snapshot name. 2815 * I.e. it finds the '@' in the snapshot dataset name and 2816 * replaces it with a '\0'. 2817 * Parameters: 2818 * origin - char pointer to a snapshot dataset name. Its 2819 * contents will be modified by this function. 2820 * *snap - pointer to a char pointer. Will be set to the 2821 * snapshot name portion upon success. 2822 * Return: 2823 * BE_SUCCESS - Success 2824 * 1 - Failure 2825 * Scope: 2826 * Private 2827 */ 2828 static int 2829 be_get_snap(char *origin, char **snap) 2830 { 2831 char *cp; 2832 2833 /* 2834 * Separate out the origin's dataset and snapshot portions by 2835 * replacing the @ with a '\0' 2836 */ 2837 cp = strrchr(origin, '@'); 2838 if (cp != NULL) { 2839 if (cp[1] != '\0') { 2840 cp[0] = '\0'; 2841 *snap = cp+1; 2842 } else { 2843 return (1); 2844 } 2845 } else { 2846 return (1); 2847 } 2848 2849 return (BE_SUCCESS); 2850 } 2851 2852 /* 2853 * Function: be_create_container_ds 2854 * Description: This function checks that the zpool passed has the BE 2855 * container dataset, and if not, then creates it. 2856 * Parameters: 2857 * zpool - name of pool to create BE container dataset in. 2858 * Return: 2859 * B_TRUE - Successfully created BE container dataset, or it 2860 * already existed. 2861 * B_FALSE - Failed to create container dataset. 2862 * Scope: 2863 * Private 2864 */ 2865 static boolean_t 2866 be_create_container_ds(char *zpool) 2867 { 2868 nvlist_t *props = NULL; 2869 char be_container_ds[MAXPATHLEN]; 2870 2871 /* Generate string for BE container dataset for this pool */ 2872 be_make_container_ds(zpool, be_container_ds, 2873 sizeof (be_container_ds)); 2874 2875 if (!zfs_dataset_exists(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM)) { 2876 2877 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 2878 be_print_err(gettext("be_create_container_ds: " 2879 "nvlist_alloc failed\n")); 2880 return (B_FALSE); 2881 } 2882 2883 if (nvlist_add_string(props, 2884 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 2885 ZFS_MOUNTPOINT_LEGACY) != 0) { 2886 be_print_err(gettext("be_create_container_ds: " 2887 "internal error: out of memory\n")); 2888 nvlist_free(props); 2889 return (B_FALSE); 2890 } 2891 2892 if (nvlist_add_string(props, 2893 zfs_prop_to_name(ZFS_PROP_CANMOUNT), "off") != 0) { 2894 be_print_err(gettext("be_create_container_ds: " 2895 "internal error: out of memory\n")); 2896 nvlist_free(props); 2897 return (B_FALSE); 2898 } 2899 2900 if (zfs_create(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM, 2901 props) != 0) { 2902 be_print_err(gettext("be_create_container_ds: " 2903 "failed to create container dataset (%s): %s\n"), 2904 be_container_ds, libzfs_error_description(g_zfs)); 2905 nvlist_free(props); 2906 return (B_FALSE); 2907 } 2908 2909 nvlist_free(props); 2910 } 2911 2912 return (B_TRUE); 2913 } 2914 2915 /* 2916 * Function: be_prep_clone_send_fs 2917 * Description: This function takes a zfs handle to a dataset from the 2918 * original BE, and generates the name of the clone dataset 2919 * to create for the new BE. It also prepares the zfs 2920 * properties to be used for the new BE. 2921 * Parameters: 2922 * zhp - pointer to zfs_handle_t of the file system being 2923 * cloned/copied. 2924 * bt - be_transaction_data pointer providing information 2925 * about the original BE and new BE. 2926 * clone_ds - buffer to store the name of the dataset 2927 * for the new BE. 2928 * clone_ds_len - length of clone_ds buffer 2929 * Return: 2930 * BE_SUCCESS - Success 2931 * be_errno_t - Failure 2932 * Scope: 2933 * Private 2934 */ 2935 static int 2936 be_prep_clone_send_fs(zfs_handle_t *zhp, be_transaction_data_t *bt, 2937 char *clone_ds, int clone_ds_len) 2938 { 2939 zprop_source_t sourcetype; 2940 char source[ZFS_MAX_DATASET_NAME_LEN]; 2941 char zhp_name[ZFS_MAX_DATASET_NAME_LEN]; 2942 char mountpoint[MAXPATHLEN]; 2943 char *child_fs = NULL; 2944 char *zhp_mountpoint = NULL; 2945 int err = 0; 2946 2947 /* 2948 * Get a copy of the dataset name zfs_name from zhp 2949 */ 2950 (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name)); 2951 2952 /* 2953 * Get file system name relative to the root. 2954 */ 2955 if (strncmp(zhp_name, bt->obe_root_ds, strlen(bt->obe_root_ds)) 2956 == 0) { 2957 child_fs = zhp_name + strlen(bt->obe_root_ds); 2958 2959 /* 2960 * if child_fs is NULL, this means we're processing the 2961 * root dataset itself; set child_fs to the empty string. 2962 */ 2963 if (child_fs == NULL) 2964 child_fs = ""; 2965 } else { 2966 return (BE_ERR_INVAL); 2967 } 2968 2969 /* 2970 * Generate the name of the clone file system. 2971 */ 2972 (void) snprintf(clone_ds, clone_ds_len, "%s%s", bt->nbe_root_ds, 2973 child_fs); 2974 2975 /* Get the mountpoint and source properties of the existing dataset */ 2976 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, 2977 sizeof (mountpoint), &sourcetype, source, sizeof (source), 2978 B_FALSE) != 0) { 2979 be_print_err(gettext("be_prep_clone_send_fs: " 2980 "failed to get mountpoint for (%s): %s\n"), 2981 zhp_name, libzfs_error_description(g_zfs)); 2982 return (zfs_err_to_be_err(g_zfs)); 2983 } 2984 2985 /* 2986 * Workaround for 6668667 where a mountpoint property of "/" comes 2987 * back as "". 2988 */ 2989 if (strcmp(mountpoint, "") == 0) { 2990 (void) snprintf(mountpoint, sizeof (mountpoint), "/"); 2991 } 2992 2993 /* 2994 * Figure out what to set as the mountpoint for the new dataset. 2995 * If the source of the mountpoint property is local, use the 2996 * mountpoint value itself. Otherwise, remove it from the 2997 * zfs properties list so that it gets inherited. 2998 */ 2999 if (sourcetype & ZPROP_SRC_LOCAL) { 3000 /* 3001 * If the BE that this file system is a part of is 3002 * currently mounted, strip off the BE altroot portion 3003 * from the mountpoint. 3004 */ 3005 zhp_mountpoint = mountpoint; 3006 3007 if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 3008 bt->obe_altroot != NULL && strcmp(bt->obe_altroot, 3009 "/") != 0 && zfs_is_mounted(zhp, NULL)) { 3010 3011 int altroot_len = strlen(bt->obe_altroot); 3012 3013 if (strncmp(bt->obe_altroot, mountpoint, altroot_len) 3014 == 0) { 3015 if (mountpoint[altroot_len] == '/') 3016 zhp_mountpoint = mountpoint + 3017 altroot_len; 3018 else if (mountpoint[altroot_len] == '\0') 3019 (void) snprintf(mountpoint, 3020 sizeof (mountpoint), "/"); 3021 } 3022 } 3023 3024 if (nvlist_add_string(bt->nbe_zfs_props, 3025 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 3026 zhp_mountpoint) != 0) { 3027 be_print_err(gettext("be_prep_clone_send_fs: " 3028 "internal error: out of memory\n")); 3029 return (BE_ERR_NOMEM); 3030 } 3031 } else { 3032 err = nvlist_remove_all(bt->nbe_zfs_props, 3033 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT)); 3034 if (err != 0 && err != ENOENT) { 3035 be_print_err(gettext("be_prep_clone_send_fs: " 3036 "failed to remove mountpoint from " 3037 "nvlist\n")); 3038 return (BE_ERR_INVAL); 3039 } 3040 } 3041 3042 /* 3043 * Set the 'canmount' property 3044 */ 3045 if (nvlist_add_string(bt->nbe_zfs_props, 3046 zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto") != 0) { 3047 be_print_err(gettext("be_prep_clone_send_fs: " 3048 "internal error: out of memory\n")); 3049 return (BE_ERR_NOMEM); 3050 } 3051 3052 return (BE_SUCCESS); 3053 } 3054 3055 /* 3056 * Function: be_get_zone_be_name 3057 * Description: This function takes the zones root dataset, the container 3058 * dataset and returns the zones BE name based on the zone 3059 * root dataset. 3060 * Parameters: 3061 * root_ds - the zones root dataset. 3062 * container_ds - the container dataset for the zone. 3063 * Returns: 3064 * char * - the BE name of this zone based on the root dataset. 3065 */ 3066 static char * 3067 be_get_zone_be_name(char *root_ds, char *container_ds) 3068 { 3069 return (root_ds + (strlen(container_ds) + 1)); 3070 } 3071 3072 /* 3073 * Function: be_zone_root_exists_callback 3074 * Description: This callback function is used to determine if a 3075 * zone root container dataset has any children. It always 3076 * returns 1, signifying a hierarchical child of the zone 3077 * root container dataset has been traversed and therefore 3078 * it has children. 3079 * Parameters: 3080 * zhp - zfs_handle_t pointer to current dataset being processed. 3081 * data - not used. 3082 * Returns: 3083 * 1 - dataset exists 3084 * Scope: 3085 * Private 3086 */ 3087 static int 3088 /* LINTED */ 3089 be_zone_root_exists_callback(zfs_handle_t *zhp, void *data) 3090 { 3091 ZFS_CLOSE(zhp); 3092 return (1); 3093 } 3094