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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * This file contains the functions used to support the ZFS integration 29 * with zones. This includes validation (e.g. zonecfg dataset), cloning, 30 * file system creation and destruction. 31 */ 32 33 #include <stdio.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <string.h> 37 #include <locale.h> 38 #include <libintl.h> 39 #include <sys/stat.h> 40 #include <sys/statvfs.h> 41 #include <libgen.h> 42 #include <libzonecfg.h> 43 #include <sys/mnttab.h> 44 #include <libzfs.h> 45 #include <sys/mntent.h> 46 #include <values.h> 47 #include <strings.h> 48 #include <assert.h> 49 50 #include "zoneadm.h" 51 52 libzfs_handle_t *g_zfs; 53 54 typedef struct zfs_mount_data { 55 char *match_name; 56 zfs_handle_t *match_handle; 57 } zfs_mount_data_t; 58 59 typedef struct zfs_snapshot_data { 60 char *match_name; /* zonename@SUNWzone */ 61 int len; /* strlen of match_name */ 62 int max; /* highest digit appended to snap name */ 63 int num; /* number of snapshots to rename */ 64 int cntr; /* counter for renaming snapshots */ 65 } zfs_snapshot_data_t; 66 67 typedef struct clone_data { 68 zfs_handle_t *clone_zhp; /* clone dataset to promote */ 69 time_t origin_creation; /* snapshot creation time of clone */ 70 const char *snapshot; /* snapshot of dataset being demoted */ 71 } clone_data_t; 72 73 /* 74 * A ZFS file system iterator call-back function which is used to validate 75 * datasets imported into the zone. 76 */ 77 /* ARGSUSED */ 78 static int 79 check_zvol(zfs_handle_t *zhp, void *unused) 80 { 81 int ret; 82 83 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { 84 /* 85 * TRANSLATION_NOTE 86 * zfs and dataset are literals that should not be translated. 87 */ 88 (void) fprintf(stderr, gettext("cannot verify zfs dataset %s: " 89 "volumes cannot be specified as a zone dataset resource\n"), 90 zfs_get_name(zhp)); 91 ret = -1; 92 } else { 93 ret = zfs_iter_children(zhp, check_zvol, NULL); 94 } 95 96 zfs_close(zhp); 97 98 return (ret); 99 } 100 101 /* 102 * A ZFS file system iterator call-back function which returns the 103 * zfs_handle_t for a ZFS file system on the specified mount point. 104 */ 105 static int 106 match_mountpoint(zfs_handle_t *zhp, void *data) 107 { 108 int res; 109 zfs_mount_data_t *cbp; 110 char mp[ZFS_MAXPROPLEN]; 111 112 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 113 zfs_close(zhp); 114 return (0); 115 } 116 117 /* First check if the dataset is mounted. */ 118 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTED, mp, sizeof (mp), NULL, NULL, 119 0, B_FALSE) != 0 || strcmp(mp, "no") == 0) { 120 zfs_close(zhp); 121 return (0); 122 } 123 124 /* Now check mount point. */ 125 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL, 126 0, B_FALSE) != 0) { 127 zfs_close(zhp); 128 return (0); 129 } 130 131 cbp = (zfs_mount_data_t *)data; 132 133 if (strcmp(mp, "legacy") == 0) { 134 /* If legacy, must look in mnttab for mountpoint. */ 135 FILE *fp; 136 struct mnttab entry; 137 const char *nm; 138 139 nm = zfs_get_name(zhp); 140 if ((fp = fopen(MNTTAB, "r")) == NULL) { 141 zfs_close(zhp); 142 return (0); 143 } 144 145 while (getmntent(fp, &entry) == 0) { 146 if (strcmp(nm, entry.mnt_special) == 0) { 147 if (strcmp(entry.mnt_mountp, cbp->match_name) 148 == 0) { 149 (void) fclose(fp); 150 cbp->match_handle = zhp; 151 return (1); 152 } 153 break; 154 } 155 } 156 (void) fclose(fp); 157 158 } else if (strcmp(mp, cbp->match_name) == 0) { 159 cbp->match_handle = zhp; 160 return (1); 161 } 162 163 /* Iterate over any nested datasets. */ 164 res = zfs_iter_filesystems(zhp, match_mountpoint, data); 165 zfs_close(zhp); 166 return (res); 167 } 168 169 /* 170 * Get ZFS handle for the specified mount point. 171 */ 172 static zfs_handle_t * 173 mount2zhandle(char *mountpoint) 174 { 175 zfs_mount_data_t cb; 176 177 cb.match_name = mountpoint; 178 cb.match_handle = NULL; 179 (void) zfs_iter_root(g_zfs, match_mountpoint, &cb); 180 return (cb.match_handle); 181 } 182 183 /* 184 * Check if there is already a file system (zfs or any other type) mounted on 185 * path. 186 */ 187 static boolean_t 188 is_mountpnt(char *path) 189 { 190 FILE *fp; 191 struct mnttab entry; 192 193 if ((fp = fopen(MNTTAB, "r")) == NULL) 194 return (B_FALSE); 195 196 while (getmntent(fp, &entry) == 0) { 197 if (strcmp(path, entry.mnt_mountp) == 0) { 198 (void) fclose(fp); 199 return (B_TRUE); 200 } 201 } 202 203 (void) fclose(fp); 204 return (B_FALSE); 205 } 206 207 /* 208 * Run the brand's pre-snapshot hook before we take a ZFS snapshot of the zone. 209 */ 210 static int 211 pre_snapshot(char *presnapbuf) 212 { 213 int status; 214 215 /* No brand-specific handler */ 216 if (presnapbuf[0] == '\0') 217 return (Z_OK); 218 219 /* Run the hook */ 220 status = do_subproc(presnapbuf); 221 if ((status = subproc_status(gettext("brand-specific presnapshot"), 222 status, B_FALSE)) != ZONE_SUBPROC_OK) 223 return (Z_ERR); 224 225 return (Z_OK); 226 } 227 228 /* 229 * Run the brand's post-snapshot hook after we take a ZFS snapshot of the zone. 230 */ 231 static int 232 post_snapshot(char *postsnapbuf) 233 { 234 int status; 235 236 /* No brand-specific handler */ 237 if (postsnapbuf[0] == '\0') 238 return (Z_OK); 239 240 /* Run the hook */ 241 status = do_subproc(postsnapbuf); 242 if ((status = subproc_status(gettext("brand-specific postsnapshot"), 243 status, B_FALSE)) != ZONE_SUBPROC_OK) 244 return (Z_ERR); 245 246 return (Z_OK); 247 } 248 249 /* 250 * This is a ZFS snapshot iterator call-back function which returns the 251 * highest number of SUNWzone snapshots that have been taken. 252 */ 253 static int 254 get_snap_max(zfs_handle_t *zhp, void *data) 255 { 256 int res; 257 zfs_snapshot_data_t *cbp; 258 259 if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) { 260 zfs_close(zhp); 261 return (0); 262 } 263 264 cbp = (zfs_snapshot_data_t *)data; 265 266 if (strncmp(zfs_get_name(zhp), cbp->match_name, cbp->len) == 0) { 267 char *nump; 268 int num; 269 270 cbp->num++; 271 nump = (char *)(zfs_get_name(zhp) + cbp->len); 272 num = atoi(nump); 273 if (num > cbp->max) 274 cbp->max = num; 275 } 276 277 res = zfs_iter_snapshots(zhp, get_snap_max, data); 278 zfs_close(zhp); 279 return (res); 280 } 281 282 /* 283 * Take a ZFS snapshot to be used for cloning the zone. 284 */ 285 static int 286 take_snapshot(zfs_handle_t *zhp, char *snapshot_name, int snap_size, 287 char *presnapbuf, char *postsnapbuf) 288 { 289 int res; 290 char template[ZFS_MAXNAMELEN]; 291 zfs_snapshot_data_t cb; 292 293 /* 294 * First we need to figure out the next available name for the 295 * zone snapshot. Look through the list of zones snapshots for 296 * this file system to determine the maximum snapshot name. 297 */ 298 if (snprintf(template, sizeof (template), "%s@SUNWzone", 299 zfs_get_name(zhp)) >= sizeof (template)) 300 return (Z_ERR); 301 302 cb.match_name = template; 303 cb.len = strlen(template); 304 cb.max = 0; 305 306 if (zfs_iter_snapshots(zhp, get_snap_max, &cb) != 0) 307 return (Z_ERR); 308 309 cb.max++; 310 311 if (snprintf(snapshot_name, snap_size, "%s@SUNWzone%d", 312 zfs_get_name(zhp), cb.max) >= snap_size) 313 return (Z_ERR); 314 315 if (pre_snapshot(presnapbuf) != Z_OK) 316 return (Z_ERR); 317 res = zfs_snapshot(g_zfs, snapshot_name, B_FALSE, NULL); 318 if (post_snapshot(postsnapbuf) != Z_OK) 319 return (Z_ERR); 320 321 if (res != 0) 322 return (Z_ERR); 323 return (Z_OK); 324 } 325 326 /* 327 * We are using an explicit snapshot from some earlier point in time so 328 * we need to validate it. Run the brand specific hook. 329 */ 330 static int 331 validate_snapshot(char *snapshot_name, char *snap_path, char *validsnapbuf) 332 { 333 int status; 334 char cmdbuf[MAXPATHLEN]; 335 336 /* No brand-specific handler */ 337 if (validsnapbuf[0] == '\0') 338 return (Z_OK); 339 340 /* pass args - snapshot_name & snap_path */ 341 if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %s %s", validsnapbuf, 342 snapshot_name, snap_path) >= sizeof (cmdbuf)) { 343 zerror("Command line too long"); 344 return (Z_ERR); 345 } 346 347 /* Run the hook */ 348 status = do_subproc(cmdbuf); 349 if ((status = subproc_status(gettext("brand-specific validatesnapshot"), 350 status, B_FALSE)) != ZONE_SUBPROC_OK) 351 return (Z_ERR); 352 353 return (Z_OK); 354 } 355 356 /* 357 * Remove the sw inventory file from inside this zonepath that we picked up out 358 * of the snapshot. 359 */ 360 static int 361 clean_out_clone() 362 { 363 int err; 364 zone_dochandle_t handle; 365 366 if ((handle = zonecfg_init_handle()) == NULL) { 367 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 368 return (Z_ERR); 369 } 370 371 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 372 errno = err; 373 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 374 zonecfg_fini_handle(handle); 375 return (Z_ERR); 376 } 377 378 zonecfg_rm_detached(handle, B_FALSE); 379 zonecfg_fini_handle(handle); 380 381 return (Z_OK); 382 } 383 384 /* 385 * Make a ZFS clone on zonepath from snapshot_name. 386 */ 387 static int 388 clone_snap(char *snapshot_name, char *zonepath) 389 { 390 int res = Z_OK; 391 int err; 392 zfs_handle_t *zhp; 393 zfs_handle_t *clone; 394 nvlist_t *props = NULL; 395 396 if ((zhp = zfs_open(g_zfs, snapshot_name, ZFS_TYPE_SNAPSHOT)) == NULL) 397 return (Z_NO_ENTRY); 398 399 (void) printf(gettext("Cloning snapshot %s\n"), snapshot_name); 400 401 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 || 402 nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS), 403 "off") != 0) { 404 if (props != NULL) 405 nvlist_free(props); 406 (void) fprintf(stderr, gettext("could not create ZFS clone " 407 "%s: out of memory\n"), zonepath); 408 return (Z_ERR); 409 } 410 411 err = zfs_clone(zhp, zonepath, props); 412 zfs_close(zhp); 413 414 nvlist_free(props); 415 416 if (err != 0) 417 return (Z_ERR); 418 419 /* create the mountpoint if necessary */ 420 if ((clone = zfs_open(g_zfs, zonepath, ZFS_TYPE_DATASET)) == NULL) 421 return (Z_ERR); 422 423 /* 424 * The clone has been created so we need to print a diagnostic 425 * message if one of the following steps fails for some reason. 426 */ 427 if (zfs_mount(clone, NULL, 0) != 0) { 428 (void) fprintf(stderr, gettext("could not mount ZFS clone " 429 "%s\n"), zfs_get_name(clone)); 430 res = Z_ERR; 431 432 } else if (clean_out_clone() != Z_OK) { 433 (void) fprintf(stderr, gettext("could not remove the " 434 "software inventory from ZFS clone %s\n"), 435 zfs_get_name(clone)); 436 res = Z_ERR; 437 } 438 439 zfs_close(clone); 440 return (res); 441 } 442 443 /* 444 * This function takes a zonepath and attempts to determine what the ZFS 445 * file system name (not mountpoint) should be for that path. We do not 446 * assume that zonepath is an existing directory or ZFS fs since we use 447 * this function as part of the process of creating a new ZFS fs or clone. 448 * 449 * The way this works is that we look at the parent directory of the zonepath 450 * to see if it is a ZFS fs. If it is, we get the name of that ZFS fs and 451 * append the last component of the zonepath to generate the ZFS name for the 452 * zonepath. This matches the algorithm that ZFS uses for automatically 453 * mounting a new fs after it is created. 454 * 455 * Although a ZFS fs can be mounted anywhere, we don't worry about handling 456 * all of the complexity that a user could possibly configure with arbitrary 457 * mounts since there is no way to generate a ZFS name from a random path in 458 * the file system. We only try to handle the automatic mounts that ZFS does 459 * for each file system. ZFS restricts this so that a new fs must be created 460 * in an existing parent ZFS fs. It then automatically mounts the new fs 461 * directly under the mountpoint for the parent fs using the last component 462 * of the name as the mountpoint directory. 463 * 464 * For example: 465 * Name Mountpoint 466 * space/eng/dev/test/zone1 /project1/eng/dev/test/zone1 467 * 468 * Return Z_OK if the path mapped to a ZFS file system name, otherwise return 469 * Z_ERR. 470 */ 471 static int 472 path2name(char *zonepath, char *zfs_name, int len) 473 { 474 int res; 475 char *bnm, *dnm, *dname, *bname; 476 zfs_handle_t *zhp; 477 struct stat stbuf; 478 479 /* 480 * We need two tmp strings to handle paths directly in / (e.g. /foo) 481 * since dirname will overwrite the first char after "/" in this case. 482 */ 483 if ((bnm = strdup(zonepath)) == NULL) 484 return (Z_ERR); 485 486 if ((dnm = strdup(zonepath)) == NULL) { 487 free(bnm); 488 return (Z_ERR); 489 } 490 491 bname = basename(bnm); 492 dname = dirname(dnm); 493 494 /* 495 * This is a quick test to save iterating over all of the zfs datasets 496 * on the system (which can be a lot). If the parent dir is not in a 497 * ZFS fs, then we're done. 498 */ 499 if (stat(dname, &stbuf) != 0 || !S_ISDIR(stbuf.st_mode) || 500 strcmp(stbuf.st_fstype, MNTTYPE_ZFS) != 0) { 501 free(bnm); 502 free(dnm); 503 return (Z_ERR); 504 } 505 506 /* See if the parent directory is its own ZFS dataset. */ 507 if ((zhp = mount2zhandle(dname)) == NULL) { 508 /* 509 * The parent is not a ZFS dataset so we can't automatically 510 * create a dataset on the given path. 511 */ 512 free(bnm); 513 free(dnm); 514 return (Z_ERR); 515 } 516 517 res = snprintf(zfs_name, len, "%s/%s", zfs_get_name(zhp), bname); 518 519 free(bnm); 520 free(dnm); 521 zfs_close(zhp); 522 if (res >= len) 523 return (Z_ERR); 524 525 return (Z_OK); 526 } 527 528 /* 529 * A ZFS file system iterator call-back function used to determine if the 530 * file system has dependents (snapshots & clones). 531 */ 532 /* ARGSUSED */ 533 static int 534 has_dependent(zfs_handle_t *zhp, void *data) 535 { 536 zfs_close(zhp); 537 return (1); 538 } 539 540 /* 541 * Given a snapshot name, get the file system path where the snapshot lives. 542 * A snapshot name is of the form fs_name@snap_name. For example, snapshot 543 * pl/zones/z1@SUNWzone1 would have a path of 544 * /pl/zones/z1/.zfs/snapshot/SUNWzone1. 545 */ 546 static int 547 snap2path(char *snap_name, char *path, int len) 548 { 549 char *p; 550 zfs_handle_t *zhp; 551 char mp[ZFS_MAXPROPLEN]; 552 553 if ((p = strrchr(snap_name, '@')) == NULL) 554 return (Z_ERR); 555 556 /* Get the file system name from the snap_name. */ 557 *p = '\0'; 558 zhp = zfs_open(g_zfs, snap_name, ZFS_TYPE_DATASET); 559 *p = '@'; 560 if (zhp == NULL) 561 return (Z_ERR); 562 563 /* Get the file system mount point. */ 564 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL, 565 0, B_FALSE) != 0) { 566 zfs_close(zhp); 567 return (Z_ERR); 568 } 569 zfs_close(zhp); 570 571 p++; 572 if (snprintf(path, len, "%s/.zfs/snapshot/%s", mp, p) >= len) 573 return (Z_ERR); 574 575 return (Z_OK); 576 } 577 578 /* 579 * This callback function is used to iterate through a snapshot's dependencies 580 * to find a filesystem that is a direct clone of the snapshot being iterated. 581 */ 582 static int 583 get_direct_clone(zfs_handle_t *zhp, void *data) 584 { 585 clone_data_t *cd = data; 586 char origin[ZFS_MAXNAMELEN]; 587 char ds_path[ZFS_MAXNAMELEN]; 588 589 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 590 zfs_close(zhp); 591 return (0); 592 } 593 594 (void) strlcpy(ds_path, zfs_get_name(zhp), sizeof (ds_path)); 595 596 /* Make sure this is a direct clone of the snapshot we're iterating. */ 597 if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL, 598 NULL, 0, B_FALSE) != 0 || strcmp(origin, cd->snapshot) != 0) { 599 zfs_close(zhp); 600 return (0); 601 } 602 603 if (cd->clone_zhp != NULL) 604 zfs_close(cd->clone_zhp); 605 606 cd->clone_zhp = zhp; 607 return (1); 608 } 609 610 /* 611 * A ZFS file system iterator call-back function used to determine the clone 612 * to promote. This function finds the youngest (i.e. last one taken) snapshot 613 * that has a clone. If found, it returns a reference to that clone in the 614 * callback data. 615 */ 616 static int 617 find_clone(zfs_handle_t *zhp, void *data) 618 { 619 clone_data_t *cd = data; 620 time_t snap_creation; 621 int zret = 0; 622 623 /* If snapshot has no clones, skip it */ 624 if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) == 0) { 625 zfs_close(zhp); 626 return (0); 627 } 628 629 cd->snapshot = zfs_get_name(zhp); 630 631 /* Get the creation time of this snapshot */ 632 snap_creation = (time_t)zfs_prop_get_int(zhp, ZFS_PROP_CREATION); 633 634 /* 635 * If this snapshot's creation time is greater than (i.e. younger than) 636 * the current youngest snapshot found, iterate this snapshot to 637 * get the right clone. 638 */ 639 if (snap_creation >= cd->origin_creation) { 640 /* 641 * Iterate the dependents of this snapshot to find a clone 642 * that's a direct dependent. 643 */ 644 if ((zret = zfs_iter_dependents(zhp, B_FALSE, get_direct_clone, 645 cd)) == -1) { 646 zfs_close(zhp); 647 return (1); 648 } else if (zret == 1) { 649 /* 650 * Found a clone, update the origin_creation time 651 * in the callback data. 652 */ 653 cd->origin_creation = snap_creation; 654 } 655 } 656 657 zfs_close(zhp); 658 return (0); 659 } 660 661 /* 662 * A ZFS file system iterator call-back function used to remove standalone 663 * snapshots. 664 */ 665 /* ARGSUSED */ 666 static int 667 rm_snap(zfs_handle_t *zhp, void *data) 668 { 669 /* If snapshot has clones, something is wrong */ 670 if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) != 0) { 671 zfs_close(zhp); 672 return (1); 673 } 674 675 if (zfs_unmount(zhp, NULL, 0) == 0) { 676 (void) zfs_destroy(zhp, B_FALSE); 677 } 678 679 zfs_close(zhp); 680 return (0); 681 } 682 683 /* 684 * A ZFS snapshot iterator call-back function which renames snapshots. 685 */ 686 static int 687 rename_snap(zfs_handle_t *zhp, void *data) 688 { 689 int res; 690 zfs_snapshot_data_t *cbp; 691 char template[ZFS_MAXNAMELEN]; 692 693 cbp = (zfs_snapshot_data_t *)data; 694 695 /* 696 * When renaming snapshots with the iterator, the iterator can see 697 * the same snapshot after we've renamed up in the namespace. To 698 * prevent this we check the count for the number of snapshots we have 699 * to rename and stop at that point. 700 */ 701 if (cbp->cntr >= cbp->num) { 702 zfs_close(zhp); 703 return (0); 704 } 705 706 if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) { 707 zfs_close(zhp); 708 return (0); 709 } 710 711 /* Only rename the snapshots we automatically generate when we clone. */ 712 if (strncmp(zfs_get_name(zhp), cbp->match_name, cbp->len) != 0) { 713 zfs_close(zhp); 714 return (0); 715 } 716 717 (void) snprintf(template, sizeof (template), "%s%d", cbp->match_name, 718 cbp->max++); 719 720 res = (zfs_rename(zhp, template, B_FALSE) != 0); 721 if (res != 0) 722 (void) fprintf(stderr, gettext("failed to rename snapshot %s " 723 "to %s: %s\n"), zfs_get_name(zhp), template, 724 libzfs_error_description(g_zfs)); 725 726 cbp->cntr++; 727 728 zfs_close(zhp); 729 return (res); 730 } 731 732 /* 733 * Rename the source dataset's snapshots that are automatically generated when 734 * we clone a zone so that there won't be a name collision when we promote the 735 * cloned dataset. Once the snapshots have been renamed, then promote the 736 * clone. 737 * 738 * The snapshot rename process gets the highest number on the snapshot names 739 * (the format is zonename@SUNWzoneXX where XX are digits) on both the source 740 * and clone datasets, then renames the source dataset snapshots starting at 741 * the next number. 742 */ 743 static int 744 promote_clone(zfs_handle_t *src_zhp, zfs_handle_t *cln_zhp) 745 { 746 zfs_snapshot_data_t sd; 747 char nm[ZFS_MAXNAMELEN]; 748 char template[ZFS_MAXNAMELEN]; 749 750 (void) strlcpy(nm, zfs_get_name(cln_zhp), sizeof (nm)); 751 /* 752 * Start by getting the clone's snapshot max which we use 753 * during the rename of the original dataset's snapshots. 754 */ 755 (void) snprintf(template, sizeof (template), "%s@SUNWzone", nm); 756 sd.match_name = template; 757 sd.len = strlen(template); 758 sd.max = 0; 759 760 if (zfs_iter_snapshots(cln_zhp, get_snap_max, &sd) != 0) 761 return (Z_ERR); 762 763 /* 764 * Now make sure the source's snapshot max is at least as high as 765 * the clone's snapshot max. 766 */ 767 (void) snprintf(template, sizeof (template), "%s@SUNWzone", 768 zfs_get_name(src_zhp)); 769 sd.match_name = template; 770 sd.len = strlen(template); 771 sd.num = 0; 772 773 if (zfs_iter_snapshots(src_zhp, get_snap_max, &sd) != 0) 774 return (Z_ERR); 775 776 /* 777 * Now rename the source dataset's snapshots so there's no 778 * conflict when we promote the clone. 779 */ 780 sd.max++; 781 sd.cntr = 0; 782 if (zfs_iter_snapshots(src_zhp, rename_snap, &sd) != 0) 783 return (Z_ERR); 784 785 /* close and reopen the clone dataset to get the latest info */ 786 zfs_close(cln_zhp); 787 if ((cln_zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) == NULL) 788 return (Z_ERR); 789 790 if (zfs_promote(cln_zhp) != 0) { 791 (void) fprintf(stderr, gettext("failed to promote %s: %s\n"), 792 nm, libzfs_error_description(g_zfs)); 793 return (Z_ERR); 794 } 795 796 zfs_close(cln_zhp); 797 return (Z_OK); 798 } 799 800 /* 801 * Promote the youngest clone. That clone will then become the origin of all 802 * of the other clones that were hanging off of the source dataset. 803 */ 804 int 805 promote_all_clones(zfs_handle_t *zhp) 806 { 807 clone_data_t cd; 808 char nm[ZFS_MAXNAMELEN]; 809 810 cd.clone_zhp = NULL; 811 cd.origin_creation = 0; 812 cd.snapshot = NULL; 813 814 if (zfs_iter_snapshots(zhp, find_clone, &cd) != 0) { 815 zfs_close(zhp); 816 return (Z_ERR); 817 } 818 819 /* Nothing to promote. */ 820 if (cd.clone_zhp == NULL) 821 return (Z_OK); 822 823 /* Found the youngest clone to promote. Promote it. */ 824 if (promote_clone(zhp, cd.clone_zhp) != 0) { 825 zfs_close(cd.clone_zhp); 826 zfs_close(zhp); 827 return (Z_ERR); 828 } 829 830 /* close and reopen the main dataset to get the latest info */ 831 (void) strlcpy(nm, zfs_get_name(zhp), sizeof (nm)); 832 zfs_close(zhp); 833 if ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) == NULL) 834 return (Z_ERR); 835 836 return (Z_OK); 837 } 838 839 /* 840 * Clone a pre-existing ZFS snapshot, either by making a direct ZFS clone, if 841 * possible, or by copying the data from the snapshot to the zonepath. 842 */ 843 int 844 clone_snapshot_zfs(char *snap_name, char *zonepath, char *validatesnap) 845 { 846 int err = Z_OK; 847 char clone_name[MAXPATHLEN]; 848 char snap_path[MAXPATHLEN]; 849 850 if (snap2path(snap_name, snap_path, sizeof (snap_path)) != Z_OK) { 851 (void) fprintf(stderr, gettext("unable to find path for %s.\n"), 852 snap_name); 853 return (Z_ERR); 854 } 855 856 if (validate_snapshot(snap_name, snap_path, validatesnap) != Z_OK) 857 return (Z_NO_ENTRY); 858 859 /* 860 * The zonepath cannot be ZFS cloned, try to copy the data from 861 * within the snapshot to the zonepath. 862 */ 863 if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) { 864 if ((err = clone_copy(snap_path, zonepath)) == Z_OK) 865 if (clean_out_clone() != Z_OK) 866 (void) fprintf(stderr, 867 gettext("could not remove the " 868 "software inventory from %s\n"), zonepath); 869 870 return (err); 871 } 872 873 if ((err = clone_snap(snap_name, clone_name)) != Z_OK) { 874 if (err != Z_NO_ENTRY) { 875 /* 876 * Cloning the snapshot failed. Fall back to trying 877 * to install the zone by copying from the snapshot. 878 */ 879 if ((err = clone_copy(snap_path, zonepath)) == Z_OK) 880 if (clean_out_clone() != Z_OK) 881 (void) fprintf(stderr, 882 gettext("could not remove the " 883 "software inventory from %s\n"), 884 zonepath); 885 } else { 886 /* 887 * The snapshot is unusable for some reason so restore 888 * the zone state to configured since we were unable to 889 * actually do anything about getting the zone 890 * installed. 891 */ 892 int tmp; 893 894 if ((tmp = zone_set_state(target_zone, 895 ZONE_STATE_CONFIGURED)) != Z_OK) { 896 errno = tmp; 897 zperror2(target_zone, 898 gettext("could not set state")); 899 } 900 } 901 } 902 903 return (err); 904 } 905 906 /* 907 * Attempt to clone a source_zone to a target zonepath by using a ZFS clone. 908 */ 909 int 910 clone_zfs(char *source_zonepath, char *zonepath, char *presnapbuf, 911 char *postsnapbuf) 912 { 913 zfs_handle_t *zhp; 914 char clone_name[MAXPATHLEN]; 915 char snap_name[MAXPATHLEN]; 916 917 /* 918 * Try to get a zfs handle for the source_zonepath. If this fails 919 * the source_zonepath is not ZFS so return an error. 920 */ 921 if ((zhp = mount2zhandle(source_zonepath)) == NULL) 922 return (Z_ERR); 923 924 /* 925 * Check if there is a file system already mounted on zonepath. If so, 926 * we can't clone to the path so we should fall back to copying. 927 */ 928 if (is_mountpnt(zonepath)) { 929 zfs_close(zhp); 930 (void) fprintf(stderr, 931 gettext("A file system is already mounted on %s,\n" 932 "preventing use of a ZFS clone.\n"), zonepath); 933 return (Z_ERR); 934 } 935 936 /* 937 * Instead of using path2name to get the clone name from the zonepath, 938 * we could generate a name from the source zone ZFS name. However, 939 * this would mean we would create the clone under the ZFS fs of the 940 * source instead of what the zonepath says. For example, 941 * 942 * source_zonepath zonepath 943 * /pl/zones/dev/z1 /pl/zones/deploy/z2 944 * 945 * We don't want the clone to be under "dev", we want it under 946 * "deploy", so that we can leverage the normal attribute inheritance 947 * that ZFS provides in the fs hierarchy. 948 */ 949 if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) { 950 zfs_close(zhp); 951 return (Z_ERR); 952 } 953 954 if (take_snapshot(zhp, snap_name, sizeof (snap_name), presnapbuf, 955 postsnapbuf) != Z_OK) { 956 zfs_close(zhp); 957 return (Z_ERR); 958 } 959 zfs_close(zhp); 960 961 if (clone_snap(snap_name, clone_name) != Z_OK) { 962 /* Clean up the snapshot we just took. */ 963 if ((zhp = zfs_open(g_zfs, snap_name, ZFS_TYPE_SNAPSHOT)) 964 != NULL) { 965 if (zfs_unmount(zhp, NULL, 0) == 0) 966 (void) zfs_destroy(zhp, B_FALSE); 967 zfs_close(zhp); 968 } 969 970 return (Z_ERR); 971 } 972 973 (void) printf(gettext("Instead of copying, a ZFS clone has been " 974 "created for this zone.\n")); 975 976 return (Z_OK); 977 } 978 979 /* 980 * Attempt to create a ZFS file system for the specified zonepath. 981 * We either will successfully create a ZFS file system and get it mounted 982 * on the zonepath or we don't. The caller doesn't care since a regular 983 * directory is used for the zonepath if no ZFS file system is mounted there. 984 */ 985 void 986 create_zfs_zonepath(char *zonepath) 987 { 988 zfs_handle_t *zhp; 989 char zfs_name[MAXPATHLEN]; 990 nvlist_t *props = NULL; 991 992 if (path2name(zonepath, zfs_name, sizeof (zfs_name)) != Z_OK) 993 return; 994 995 /* Check if the dataset already exists. */ 996 if ((zhp = zfs_open(g_zfs, zfs_name, ZFS_TYPE_DATASET)) != NULL) { 997 zfs_close(zhp); 998 return; 999 } 1000 1001 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 || 1002 nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS), 1003 "off") != 0) { 1004 if (props != NULL) 1005 nvlist_free(props); 1006 (void) fprintf(stderr, gettext("cannot create ZFS dataset %s: " 1007 "out of memory\n"), zfs_name); 1008 } 1009 1010 if (zfs_create(g_zfs, zfs_name, ZFS_TYPE_FILESYSTEM, props) != 0 || 1011 (zhp = zfs_open(g_zfs, zfs_name, ZFS_TYPE_DATASET)) == NULL) { 1012 (void) fprintf(stderr, gettext("cannot create ZFS dataset %s: " 1013 "%s\n"), zfs_name, libzfs_error_description(g_zfs)); 1014 nvlist_free(props); 1015 return; 1016 } 1017 1018 nvlist_free(props); 1019 1020 if (zfs_mount(zhp, NULL, 0) != 0) { 1021 (void) fprintf(stderr, gettext("cannot mount ZFS dataset %s: " 1022 "%s\n"), zfs_name, libzfs_error_description(g_zfs)); 1023 (void) zfs_destroy(zhp, B_FALSE); 1024 } else { 1025 if (chmod(zonepath, S_IRWXU) != 0) { 1026 (void) fprintf(stderr, gettext("file system %s " 1027 "successfully created, but chmod %o failed: %s\n"), 1028 zfs_name, S_IRWXU, strerror(errno)); 1029 (void) destroy_zfs(zonepath); 1030 } else { 1031 (void) printf(gettext("A ZFS file system has been " 1032 "created for this zone.\n")); 1033 } 1034 } 1035 1036 zfs_close(zhp); 1037 } 1038 1039 /* 1040 * If the zonepath is a ZFS file system, attempt to destroy it. We return Z_OK 1041 * if we were able to zfs_destroy the zonepath, otherwise we return Z_ERR 1042 * which means the caller should clean up the zonepath in the traditional 1043 * way. 1044 */ 1045 int 1046 destroy_zfs(char *zonepath) 1047 { 1048 zfs_handle_t *zhp; 1049 boolean_t is_clone = B_FALSE; 1050 char origin[ZFS_MAXPROPLEN]; 1051 1052 if ((zhp = mount2zhandle(zonepath)) == NULL) 1053 return (Z_ERR); 1054 1055 if (promote_all_clones(zhp) != 0) 1056 return (Z_ERR); 1057 1058 /* Now cleanup any snapshots remaining. */ 1059 if (zfs_iter_snapshots(zhp, rm_snap, NULL) != 0) { 1060 zfs_close(zhp); 1061 return (Z_ERR); 1062 } 1063 1064 /* 1065 * We can't destroy the file system if it has still has dependents. 1066 * There shouldn't be any at this point, but we'll double check. 1067 */ 1068 if (zfs_iter_dependents(zhp, B_TRUE, has_dependent, NULL) != 0) { 1069 (void) fprintf(stderr, gettext("zfs destroy %s failed: the " 1070 "dataset still has dependents\n"), zfs_get_name(zhp)); 1071 zfs_close(zhp); 1072 return (Z_ERR); 1073 } 1074 1075 /* 1076 * This might be a clone. Try to get the snapshot so we can attempt 1077 * to destroy that as well. 1078 */ 1079 if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL, 1080 NULL, 0, B_FALSE) == 0) 1081 is_clone = B_TRUE; 1082 1083 if (zfs_unmount(zhp, NULL, 0) != 0) { 1084 (void) fprintf(stderr, gettext("zfs unmount %s failed: %s\n"), 1085 zfs_get_name(zhp), libzfs_error_description(g_zfs)); 1086 zfs_close(zhp); 1087 return (Z_ERR); 1088 } 1089 1090 if (zfs_destroy(zhp, B_FALSE) != 0) { 1091 /* 1092 * If the destroy fails for some reason, try to remount 1093 * the file system so that we can use "rm -rf" to clean up 1094 * instead. 1095 */ 1096 (void) fprintf(stderr, gettext("zfs destroy %s failed: %s\n"), 1097 zfs_get_name(zhp), libzfs_error_description(g_zfs)); 1098 (void) zfs_mount(zhp, NULL, 0); 1099 zfs_close(zhp); 1100 return (Z_ERR); 1101 } 1102 1103 /* 1104 * If the zone has ever been moved then the mountpoint dir will not be 1105 * cleaned up by the zfs_destroy(). To handle this case try to clean 1106 * it up now but don't worry if it fails, that will be normal. 1107 */ 1108 (void) rmdir(zonepath); 1109 1110 (void) printf(gettext("The ZFS file system for this zone has been " 1111 "destroyed.\n")); 1112 1113 if (is_clone) { 1114 zfs_handle_t *ohp; 1115 1116 /* 1117 * Try to clean up the snapshot that the clone was taken from. 1118 */ 1119 if ((ohp = zfs_open(g_zfs, origin, 1120 ZFS_TYPE_SNAPSHOT)) != NULL) { 1121 if (zfs_iter_dependents(ohp, B_TRUE, has_dependent, 1122 NULL) == 0 && zfs_unmount(ohp, NULL, 0) == 0) 1123 (void) zfs_destroy(ohp, B_FALSE); 1124 zfs_close(ohp); 1125 } 1126 } 1127 1128 zfs_close(zhp); 1129 return (Z_OK); 1130 } 1131 1132 /* 1133 * Return true if the path is its own zfs file system. We determine this 1134 * by stat-ing the path to see if it is zfs and stat-ing the parent to see 1135 * if it is a different fs. 1136 */ 1137 boolean_t 1138 is_zonepath_zfs(char *zonepath) 1139 { 1140 int res; 1141 char *path; 1142 char *parent; 1143 struct statvfs64 buf1, buf2; 1144 1145 if (statvfs64(zonepath, &buf1) != 0) 1146 return (B_FALSE); 1147 1148 if (strcmp(buf1.f_basetype, "zfs") != 0) 1149 return (B_FALSE); 1150 1151 if ((path = strdup(zonepath)) == NULL) 1152 return (B_FALSE); 1153 1154 parent = dirname(path); 1155 res = statvfs64(parent, &buf2); 1156 free(path); 1157 1158 if (res != 0) 1159 return (B_FALSE); 1160 1161 if (buf1.f_fsid == buf2.f_fsid) 1162 return (B_FALSE); 1163 1164 return (B_TRUE); 1165 } 1166 1167 /* 1168 * Implement the fast move of a ZFS file system by simply updating the 1169 * mountpoint. Since it is file system already, we don't have the 1170 * issue of cross-file system copying. 1171 */ 1172 int 1173 move_zfs(char *zonepath, char *new_zonepath) 1174 { 1175 int ret = Z_ERR; 1176 zfs_handle_t *zhp; 1177 1178 if ((zhp = mount2zhandle(zonepath)) == NULL) 1179 return (Z_ERR); 1180 1181 if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1182 new_zonepath) == 0) { 1183 /* 1184 * Clean up the old mount point. We ignore any failure since 1185 * the zone is already successfully mounted on the new path. 1186 */ 1187 (void) rmdir(zonepath); 1188 ret = Z_OK; 1189 } 1190 1191 zfs_close(zhp); 1192 1193 return (ret); 1194 } 1195 1196 /* 1197 * Validate that the given dataset exists on the system, and that neither it nor 1198 * its children are zvols. 1199 * 1200 * Note that we don't do anything with the 'zoned' property here. All 1201 * management is done in zoneadmd when the zone is actually rebooted. This 1202 * allows us to automatically set the zoned property even when a zone is 1203 * rebooted by the administrator. 1204 */ 1205 int 1206 verify_datasets(zone_dochandle_t handle) 1207 { 1208 int return_code = Z_OK; 1209 struct zone_dstab dstab; 1210 zfs_handle_t *zhp; 1211 char propbuf[ZFS_MAXPROPLEN]; 1212 char source[ZFS_MAXNAMELEN]; 1213 zprop_source_t srctype; 1214 1215 if (zonecfg_setdsent(handle) != Z_OK) { 1216 /* 1217 * TRANSLATION_NOTE 1218 * zfs and dataset are literals that should not be translated. 1219 */ 1220 (void) fprintf(stderr, gettext("could not verify zfs datasets: " 1221 "unable to enumerate datasets\n")); 1222 return (Z_ERR); 1223 } 1224 1225 while (zonecfg_getdsent(handle, &dstab) == Z_OK) { 1226 1227 if ((zhp = zfs_open(g_zfs, dstab.zone_dataset_name, 1228 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) { 1229 (void) fprintf(stderr, gettext("could not verify zfs " 1230 "dataset %s: %s\n"), dstab.zone_dataset_name, 1231 libzfs_error_description(g_zfs)); 1232 return_code = Z_ERR; 1233 continue; 1234 } 1235 1236 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, 1237 sizeof (propbuf), &srctype, source, 1238 sizeof (source), 0) == 0 && 1239 (srctype == ZPROP_SRC_INHERITED)) { 1240 (void) fprintf(stderr, gettext("could not verify zfs " 1241 "dataset %s: mountpoint cannot be inherited\n"), 1242 dstab.zone_dataset_name); 1243 return_code = Z_ERR; 1244 zfs_close(zhp); 1245 continue; 1246 } 1247 1248 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { 1249 (void) fprintf(stderr, gettext("cannot verify zfs " 1250 "dataset %s: volumes cannot be specified as a " 1251 "zone dataset resource\n"), 1252 dstab.zone_dataset_name); 1253 return_code = Z_ERR; 1254 } 1255 1256 if (zfs_iter_children(zhp, check_zvol, NULL) != 0) 1257 return_code = Z_ERR; 1258 1259 zfs_close(zhp); 1260 } 1261 (void) zonecfg_enddsent(handle); 1262 1263 return (return_code); 1264 } 1265 1266 /* 1267 * Verify that the ZFS dataset exists, and its mountpoint 1268 * property is set to "legacy". 1269 */ 1270 int 1271 verify_fs_zfs(struct zone_fstab *fstab) 1272 { 1273 zfs_handle_t *zhp; 1274 char propbuf[ZFS_MAXPROPLEN]; 1275 1276 if ((zhp = zfs_open(g_zfs, fstab->zone_fs_special, 1277 ZFS_TYPE_DATASET)) == NULL) { 1278 (void) fprintf(stderr, gettext("could not verify fs %s: " 1279 "could not access zfs dataset '%s'\n"), 1280 fstab->zone_fs_dir, fstab->zone_fs_special); 1281 return (Z_ERR); 1282 } 1283 1284 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 1285 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1286 "'%s' is not a file system\n"), 1287 fstab->zone_fs_dir, fstab->zone_fs_special); 1288 zfs_close(zhp); 1289 return (Z_ERR); 1290 } 1291 1292 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf), 1293 NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) { 1294 (void) fprintf(stderr, gettext("could not verify fs %s: " 1295 "zfs '%s' mountpoint is not \"legacy\"\n"), 1296 fstab->zone_fs_dir, fstab->zone_fs_special); 1297 zfs_close(zhp); 1298 return (Z_ERR); 1299 } 1300 1301 zfs_close(zhp); 1302 return (Z_OK); 1303 } 1304 1305 /* 1306 * Destroy the specified mnttab structure that was created by mnttab_dup(). 1307 * NOTE: The structure's mnt_time field isn't freed. 1308 */ 1309 static void 1310 mnttab_destroy(struct mnttab *tabp) 1311 { 1312 assert(tabp != NULL); 1313 1314 free(tabp->mnt_mountp); 1315 free(tabp->mnt_special); 1316 free(tabp->mnt_fstype); 1317 free(tabp->mnt_mntopts); 1318 free(tabp); 1319 } 1320 1321 /* 1322 * Duplicate the specified mnttab structure. The mnt_mountp and mnt_time 1323 * fields aren't duplicated. This function returns a pointer to the new mnttab 1324 * structure or NULL if an error occurred. If an error occurs, then this 1325 * function sets errno to reflect the error. mnttab structures created by 1326 * this function should be destroyed via mnttab_destroy(). 1327 */ 1328 static struct mnttab * 1329 mnttab_dup(const struct mnttab *srcp) 1330 { 1331 struct mnttab *retval; 1332 1333 assert(srcp != NULL); 1334 1335 retval = (struct mnttab *)calloc(1, sizeof (*retval)); 1336 if (retval == NULL) { 1337 errno = ENOMEM; 1338 return (NULL); 1339 } 1340 if (srcp->mnt_special != NULL) { 1341 retval->mnt_special = strdup(srcp->mnt_special); 1342 if (retval->mnt_special == NULL) 1343 goto err; 1344 } 1345 if (srcp->mnt_fstype != NULL) { 1346 retval->mnt_fstype = strdup(srcp->mnt_fstype); 1347 if (retval->mnt_fstype == NULL) 1348 goto err; 1349 } 1350 retval->mnt_mntopts = (char *)malloc(MAX_MNTOPT_STR * sizeof (char)); 1351 if (retval->mnt_mntopts == NULL) 1352 goto err; 1353 if (srcp->mnt_mntopts != NULL) { 1354 if (strlcpy(retval->mnt_mntopts, srcp->mnt_mntopts, 1355 MAX_MNTOPT_STR * sizeof (char)) >= MAX_MNTOPT_STR * 1356 sizeof (char)) { 1357 mnttab_destroy(retval); 1358 errno = EOVERFLOW; /* similar to mount(2) behavior */ 1359 return (NULL); 1360 } 1361 } else { 1362 retval->mnt_mntopts[0] = '\0'; 1363 } 1364 return (retval); 1365 1366 err: 1367 mnttab_destroy(retval); 1368 errno = ENOMEM; 1369 return (NULL); 1370 } 1371 1372 /* 1373 * Determine whether the specified ZFS dataset's mountpoint property is set 1374 * to "legacy". If the specified dataset does not have a legacy mountpoint, 1375 * then the string pointer to which the mountpoint argument points is assigned 1376 * a dynamically-allocated string containing the dataset's mountpoint 1377 * property. If the dataset's mountpoint property is "legacy" or a libzfs 1378 * error occurs, then the string pointer to which the mountpoint argument 1379 * points isn't modified. 1380 * 1381 * This function returns B_TRUE if it doesn't encounter any fatal errors. 1382 * It returns B_FALSE if it encounters a fatal error and sets errno to the 1383 * appropriate error code. 1384 */ 1385 static boolean_t 1386 get_zfs_non_legacy_mountpoint(const char *dataset_name, char **mountpoint) 1387 { 1388 zfs_handle_t *zhp; 1389 char propbuf[ZFS_MAXPROPLEN]; 1390 1391 assert(dataset_name != NULL); 1392 assert(mountpoint != NULL); 1393 1394 if ((zhp = zfs_open(g_zfs, dataset_name, ZFS_TYPE_DATASET)) == NULL) { 1395 errno = EINVAL; 1396 return (B_FALSE); 1397 } 1398 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf), 1399 NULL, NULL, 0, 0) != 0) { 1400 zfs_close(zhp); 1401 errno = EINVAL; 1402 return (B_FALSE); 1403 } 1404 zfs_close(zhp); 1405 if (strcmp(propbuf, "legacy") != 0) { 1406 if ((*mountpoint = strdup(propbuf)) == NULL) { 1407 errno = ENOMEM; 1408 return (B_FALSE); 1409 } 1410 } 1411 return (B_TRUE); 1412 } 1413 1414 1415 /* 1416 * This zonecfg_find_mounts() callback records information about mounts of 1417 * interest in a zonepath. It also tallies the number of zone 1418 * root overlay mounts and the number of unexpected mounts found. 1419 * This function outputs errors using zerror() if it finds unexpected 1420 * mounts. cookiep should point to an initialized zone_mounts_t structure. 1421 * 1422 * This function returns zero on success and a nonzero value on failure. 1423 */ 1424 static int 1425 zone_mounts_cb(const struct mnttab *mountp, void *cookiep) 1426 { 1427 zone_mounts_t *mounts; 1428 const char *zone_mount_dir; 1429 1430 assert(mountp != NULL); 1431 assert(cookiep != NULL); 1432 1433 mounts = (zone_mounts_t *)cookiep; 1434 zone_mount_dir = mountp->mnt_mountp + mounts->zonepath_len; 1435 if (strcmp(zone_mount_dir, "/root") == 0) { 1436 /* 1437 * Check for an overlay mount. If we already detected a /root 1438 * mount, then the current mount must be an overlay mount. 1439 */ 1440 if (mounts->root_mnttab != NULL) { 1441 mounts->num_root_overlay_mounts++; 1442 return (0); 1443 } 1444 1445 /* 1446 * Store the root mount's mnttab information in the 1447 * zone_mounts_t structure for future use. 1448 */ 1449 if ((mounts->root_mnttab = mnttab_dup(mountp)) == NULL) { 1450 zperror(cmd_to_str(CMD_MOVE), B_FALSE); 1451 return (-1); 1452 } 1453 1454 /* 1455 * Determine if the filesystem is a ZFS filesystem with a 1456 * non-legacy mountpoint. If it is, then set the root 1457 * filesystem's mnttab's mnt_mountp field to a non-NULL 1458 * value, which will serve as a flag to indicate this special 1459 * condition. 1460 */ 1461 if (strcmp(mountp->mnt_fstype, MNTTYPE_ZFS) == 0 && 1462 get_zfs_non_legacy_mountpoint(mountp->mnt_special, 1463 &mounts->root_mnttab->mnt_mountp) != B_TRUE) { 1464 zperror(cmd_to_str(CMD_MOVE), B_FALSE); 1465 return (-1); 1466 } 1467 } else { 1468 /* 1469 * An unexpected mount was found. Notify the user. 1470 */ 1471 if (mounts->num_unexpected_mounts == 0) 1472 zerror(gettext("These file systems are mounted on " 1473 "subdirectories of %s.\n"), mounts->zonepath); 1474 mounts->num_unexpected_mounts++; 1475 (void) zfm_print(mountp, NULL); 1476 } 1477 return (0); 1478 } 1479 1480 /* 1481 * Initialize the specified zone_mounts_t structure for the given zonepath. 1482 * If this function succeeds, it returns zero and the specified zone_mounts_t 1483 * structure contains information about mounts in the specified zonepath. 1484 * The function returns a nonzero value if it fails. The zone_mounts_t 1485 * structure doesn't need be destroyed via zone_mounts_destroy() if this 1486 * function fails. 1487 */ 1488 int 1489 zone_mounts_init(zone_mounts_t *mounts, const char *zonepath) 1490 { 1491 assert(mounts != NULL); 1492 assert(zonepath != NULL); 1493 1494 bzero(mounts, sizeof (*mounts)); 1495 if ((mounts->zonepath = strdup(zonepath)) == NULL) { 1496 zerror(gettext("the process ran out of memory while checking " 1497 "for mounts in zonepath %s."), zonepath); 1498 return (-1); 1499 } 1500 mounts->zonepath_len = strlen(zonepath); 1501 if (zonecfg_find_mounts((char *)zonepath, zone_mounts_cb, mounts) == 1502 -1) { 1503 zerror(gettext("an error occurred while checking for mounts " 1504 "in zonepath %s."), zonepath); 1505 zone_mounts_destroy(mounts); 1506 return (-1); 1507 } 1508 return (0); 1509 } 1510 1511 /* 1512 * Destroy the memory used by the specified zone_mounts_t structure's fields. 1513 * This function doesn't free the memory occupied by the structure itself 1514 * (i.e., it doesn't free the parameter). 1515 */ 1516 void 1517 zone_mounts_destroy(zone_mounts_t *mounts) 1518 { 1519 assert(mounts != NULL); 1520 1521 free(mounts->zonepath); 1522 if (mounts->root_mnttab != NULL) 1523 mnttab_destroy(mounts->root_mnttab); 1524 } 1525 1526 /* 1527 * Mount a moving zone's root filesystem (if it had a root filesystem mount 1528 * prior to the move) using the specified zonepath. mounts should refer to 1529 * the zone_mounts_t structure describing the zone's mount information. 1530 * 1531 * This function returns zero if the mount succeeds and a nonzero value 1532 * if it doesn't. 1533 */ 1534 int 1535 zone_mount_rootfs(zone_mounts_t *mounts, const char *zonepath) 1536 { 1537 char zoneroot[MAXPATHLEN]; 1538 struct mnttab *mtab; 1539 int flags; 1540 1541 assert(mounts != NULL); 1542 assert(zonepath != NULL); 1543 1544 /* 1545 * If there isn't a root filesystem, then don't do anything. 1546 */ 1547 mtab = mounts->root_mnttab; 1548 if (mtab == NULL) 1549 return (0); 1550 1551 /* 1552 * Determine the root filesystem's new mountpoint. 1553 */ 1554 if (snprintf(zoneroot, sizeof (zoneroot), "%s/root", zonepath) >= 1555 sizeof (zoneroot)) { 1556 zerror(gettext("Zonepath %s is too long.\n"), zonepath); 1557 return (-1); 1558 } 1559 1560 /* 1561 * If the root filesystem is a non-legacy ZFS filesystem (i.e., if it's 1562 * mnt_mountp field is non-NULL), then make the filesystem's new 1563 * mount point its mountpoint property and mount the filesystem. 1564 */ 1565 if (mtab->mnt_mountp != NULL) { 1566 zfs_handle_t *zhp; 1567 1568 if ((zhp = zfs_open(g_zfs, mtab->mnt_special, 1569 ZFS_TYPE_DATASET)) == NULL) { 1570 zerror(gettext("could not get ZFS handle for the zone's" 1571 " root filesystem")); 1572 return (-1); 1573 } 1574 if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1575 zoneroot) != 0) { 1576 zerror(gettext("could not modify zone's root " 1577 "filesystem's mountpoint property")); 1578 zfs_close(zhp); 1579 return (-1); 1580 } 1581 if (zfs_mount(zhp, mtab->mnt_mntopts, 0) != 0) { 1582 zerror(gettext("unable to mount zone root %s: %s"), 1583 zoneroot, libzfs_error_description(g_zfs)); 1584 if (zfs_prop_set(zhp, 1585 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1586 mtab->mnt_mountp) != 0) 1587 zerror(gettext("unable to restore zone's root " 1588 "filesystem's mountpoint property")); 1589 zfs_close(zhp); 1590 return (-1); 1591 } 1592 zfs_close(zhp); 1593 return (0); 1594 } 1595 1596 /* 1597 * The root filesystem is either a legacy-mounted ZFS filesystem or 1598 * a non-ZFS filesystem. Use mount(2) to mount the root filesystem. 1599 */ 1600 if (mtab->mnt_mntopts != NULL) 1601 flags = MS_OPTIONSTR; 1602 else 1603 flags = 0; 1604 if (mount(mtab->mnt_special, zoneroot, flags, mtab->mnt_fstype, NULL, 0, 1605 mtab->mnt_mntopts, MAX_MNTOPT_STR * sizeof (char)) != 0) { 1606 flags = errno; 1607 zerror(gettext("unable to mount zone root %s: %s"), zoneroot, 1608 strerror(flags)); 1609 return (-1); 1610 } 1611 return (0); 1612 } 1613 1614 /* 1615 * Unmount a moving zone's root filesystem (if such a mount exists) using the 1616 * specified zonepath. mounts should refer to the zone_mounts_t structure 1617 * describing the zone's mount information. If force is B_TRUE, then if the 1618 * unmount fails, then the function will try to forcibly unmount the zone's root 1619 * filesystem. 1620 * 1621 * This function returns zero if the unmount (forced or otherwise) succeeds; 1622 * otherwise, it returns a nonzero value. 1623 */ 1624 int 1625 zone_unmount_rootfs(zone_mounts_t *mounts, const char *zonepath, 1626 boolean_t force) 1627 { 1628 char zoneroot[MAXPATHLEN]; 1629 struct mnttab *mtab; 1630 int err; 1631 1632 assert(mounts != NULL); 1633 assert(zonepath != NULL); 1634 1635 /* 1636 * If there isn't a root filesystem, then don't do anything. 1637 */ 1638 mtab = mounts->root_mnttab; 1639 if (mtab == NULL) 1640 return (0); 1641 1642 /* 1643 * Determine the root filesystem's mountpoint. 1644 */ 1645 if (snprintf(zoneroot, sizeof (zoneroot), "%s/root", zonepath) >= 1646 sizeof (zoneroot)) { 1647 zerror(gettext("Zonepath %s is too long.\n"), zonepath); 1648 return (-1); 1649 } 1650 1651 /* 1652 * If the root filesystem is a non-legacy ZFS fileystem, then unmount 1653 * the filesystem via libzfs. 1654 */ 1655 if (mtab->mnt_mountp != NULL) { 1656 zfs_handle_t *zhp; 1657 1658 if ((zhp = zfs_open(g_zfs, mtab->mnt_special, 1659 ZFS_TYPE_DATASET)) == NULL) { 1660 zerror(gettext("could not get ZFS handle for the zone's" 1661 " root filesystem")); 1662 return (-1); 1663 } 1664 if (zfs_unmount(zhp, zoneroot, 0) != 0) { 1665 if (force && zfs_unmount(zhp, zoneroot, MS_FORCE) == 1666 0) { 1667 zfs_close(zhp); 1668 return (0); 1669 } 1670 zerror(gettext("unable to unmount zone root %s: %s"), 1671 zoneroot, libzfs_error_description(g_zfs)); 1672 zfs_close(zhp); 1673 return (-1); 1674 } 1675 zfs_close(zhp); 1676 return (0); 1677 } 1678 1679 /* 1680 * Use umount(2) to unmount the root filesystem. If this fails, then 1681 * forcibly unmount it if the force flag is set. 1682 */ 1683 if (umount(zoneroot) != 0) { 1684 if (force && umount2(zoneroot, MS_FORCE) == 0) 1685 return (0); 1686 err = errno; 1687 zerror(gettext("unable to unmount zone root %s: %s"), zoneroot, 1688 strerror(err)); 1689 return (-1); 1690 } 1691 return (0); 1692 } 1693 1694 int 1695 init_zfs(void) 1696 { 1697 if ((g_zfs = libzfs_init()) == NULL) { 1698 (void) fprintf(stderr, gettext("failed to initialize ZFS " 1699 "library\n")); 1700 return (Z_ERR); 1701 } 1702 1703 return (Z_OK); 1704 } 1705