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