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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file contains the functions used to support the ZFS integration 31 * with zones. This includes validation (e.g. zonecfg dataset), cloning, 32 * file system creation and destruction. 33 */ 34 35 #include <stdio.h> 36 #include <errno.h> 37 #include <unistd.h> 38 #include <string.h> 39 #include <locale.h> 40 #include <libintl.h> 41 #include <sys/stat.h> 42 #include <sys/statvfs.h> 43 #include <libgen.h> 44 #include <libzonecfg.h> 45 #include <sys/mnttab.h> 46 #include <libzfs.h> 47 48 #include "zoneadm.h" 49 50 static const char *current_dataset; 51 52 typedef struct zfs_mount_data { 53 char *match_name; 54 zfs_handle_t *match_handle; 55 } zfs_mount_data_t; 56 57 typedef struct zfs_snapshot_data { 58 char *match_name; 59 int len; 60 int max; 61 } zfs_snapshot_data_t; 62 63 /* 64 * ZFS error handler to do nothing - do not print the libzfs error messages. 65 */ 66 /* ARGSUSED */ 67 static void 68 noop_err_handler(const char *fmt, va_list ap) 69 { 70 } 71 72 /* 73 * Custom error handler for errors incurred as part of verifying datasets. We 74 * want to trim off the leading 'cannot open ...' to create a better error 75 * message. The only other way this can fail is if we fail to set the 'zoned' 76 * property. In this case we just pass the error on verbatim. 77 */ 78 static void 79 err_handler(const char *fmt, va_list ap) 80 { 81 char buf[1024]; 82 83 (void) vsnprintf(buf, sizeof (buf), fmt, ap); 84 85 if (strncmp(gettext("cannot open "), buf, 86 strlen(gettext("cannot open "))) == 0) 87 /* 88 * TRANSLATION_NOTE 89 * zfs and dataset are literals that should not be translated. 90 */ 91 (void) fprintf(stderr, gettext("could not verify zfs " 92 "dataset %s%s\n"), current_dataset, strchr(buf, ':')); 93 else 94 (void) fprintf(stderr, gettext("could not verify zfs dataset " 95 "%s: %s\n"), current_dataset, buf); 96 } 97 98 /* 99 * A ZFS file system iterator call-back function which is used to validate 100 * datasets imported into the zone. 101 */ 102 /* ARGSUSED */ 103 static int 104 check_zvol(zfs_handle_t *zhp, void *unused) 105 { 106 int ret; 107 108 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { 109 /* 110 * TRANSLATION_NOTE 111 * zfs and dataset are literals that should not be translated. 112 */ 113 (void) fprintf(stderr, gettext("cannot verify zfs dataset %s: " 114 "volumes cannot be specified as a zone dataset resource\n"), 115 zfs_get_name(zhp)); 116 ret = -1; 117 } else { 118 ret = zfs_iter_children(zhp, check_zvol, NULL); 119 } 120 121 zfs_close(zhp); 122 123 return (ret); 124 } 125 126 /* 127 * A ZFS file system iterator call-back function which returns the 128 * zfs_handle_t for a ZFS file system on the specified mount point. 129 */ 130 static int 131 match_mountpoint(zfs_handle_t *zhp, void *data) 132 { 133 int res; 134 zfs_mount_data_t *cbp; 135 char mp[ZFS_MAXPROPLEN]; 136 137 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 138 zfs_close(zhp); 139 return (0); 140 } 141 142 cbp = (zfs_mount_data_t *)data; 143 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL, 144 0, FALSE) == 0 && strcmp(mp, cbp->match_name) == 0) { 145 cbp->match_handle = zhp; 146 return (1); 147 } 148 149 res = zfs_iter_filesystems(zhp, match_mountpoint, data); 150 zfs_close(zhp); 151 return (res); 152 } 153 154 /* 155 * Get ZFS handle for the specified mount point. 156 */ 157 static zfs_handle_t * 158 mount2zhandle(char *mountpoint) 159 { 160 zfs_mount_data_t cb; 161 162 cb.match_name = mountpoint; 163 cb.match_handle = NULL; 164 (void) zfs_iter_root(match_mountpoint, &cb); 165 return (cb.match_handle); 166 } 167 168 /* 169 * Check if there is already a file system (zfs or any other type) mounted on 170 * path. 171 */ 172 static boolean_t 173 is_mountpnt(char *path) 174 { 175 FILE *fp; 176 struct mnttab entry; 177 178 if ((fp = fopen("/etc/mnttab", "r")) == NULL) 179 return (B_FALSE); 180 181 while (getmntent(fp, &entry) == 0) { 182 if (strcmp(path, entry.mnt_mountp) == 0) { 183 (void) fclose(fp); 184 return (B_TRUE); 185 } 186 } 187 188 (void) fclose(fp); 189 return (B_FALSE); 190 } 191 192 /* 193 * Perform any necessary housekeeping tasks we need to do before we take 194 * a ZFS snapshot of the zone. What this really entails is that we are 195 * taking a sw inventory of the source zone, like we do when we detach, 196 * so that there is the XML manifest in the snapshot. We use that to 197 * validate the snapshot if it is the source of a clone at some later time. 198 */ 199 static int 200 pre_snapshot(char *source_zone) 201 { 202 int err; 203 zone_dochandle_t handle; 204 205 if ((handle = zonecfg_init_handle()) == NULL) { 206 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 207 return (Z_ERR); 208 } 209 210 if ((err = zonecfg_get_handle(source_zone, handle)) != Z_OK) { 211 errno = err; 212 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 213 zonecfg_fini_handle(handle); 214 return (Z_ERR); 215 } 216 217 if ((err = zonecfg_get_detach_info(handle, B_TRUE)) != Z_OK) { 218 errno = err; 219 zperror(gettext("getting the software version information " 220 "failed"), B_TRUE); 221 zonecfg_fini_handle(handle); 222 return (Z_ERR); 223 } 224 225 if ((err = zonecfg_detach_save(handle)) != Z_OK) { 226 errno = err; 227 zperror(gettext("saving the software version manifest failed"), 228 B_TRUE); 229 zonecfg_fini_handle(handle); 230 return (Z_ERR); 231 } 232 233 zonecfg_fini_handle(handle); 234 return (Z_OK); 235 } 236 237 /* 238 * Perform any necessary housekeeping tasks we need to do after we take 239 * a ZFS snapshot of the zone. What this really entails is removing the 240 * sw inventory XML file from the zone. It is still in the snapshot where 241 * we want it, but we don't want it in the source zone itself. 242 */ 243 static int 244 post_snapshot(char *source_zone) 245 { 246 int err; 247 zone_dochandle_t handle; 248 249 if ((handle = zonecfg_init_handle()) == NULL) { 250 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 251 return (Z_ERR); 252 } 253 254 if ((err = zonecfg_get_handle(source_zone, handle)) != Z_OK) { 255 errno = err; 256 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 257 zonecfg_fini_handle(handle); 258 return (Z_ERR); 259 } 260 261 zonecfg_rm_detached(handle, B_FALSE); 262 zonecfg_fini_handle(handle); 263 264 return (Z_OK); 265 } 266 267 /* 268 * This is a ZFS snapshot iterator call-back function which returns the 269 * highest number of SUNWzone snapshots that have been taken. 270 */ 271 static int 272 get_snap_max(zfs_handle_t *zhp, void *data) 273 { 274 int res; 275 zfs_snapshot_data_t *cbp; 276 277 if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) { 278 zfs_close(zhp); 279 return (0); 280 } 281 282 cbp = (zfs_snapshot_data_t *)data; 283 284 if (strncmp(zfs_get_name(zhp), cbp->match_name, cbp->len) == 0) { 285 char *nump; 286 int num; 287 288 nump = (char *)(zfs_get_name(zhp) + cbp->len); 289 num = atoi(nump); 290 if (num > cbp->max) 291 cbp->max = num; 292 } 293 294 res = zfs_iter_snapshots(zhp, get_snap_max, data); 295 zfs_close(zhp); 296 return (res); 297 } 298 299 /* 300 * Take a ZFS snapshot to be used for cloning the zone. 301 */ 302 static int 303 take_snapshot(char *source_zone, zfs_handle_t *zhp, char *snapshot_name, 304 int snap_size) 305 { 306 int res; 307 char template[ZFS_MAXNAMELEN]; 308 zfs_snapshot_data_t cb; 309 310 /* 311 * First we need to figure out the next available name for the 312 * zone snapshot. Look through the list of zones snapshots for 313 * this file system to determine the maximum snapshot name. 314 */ 315 if (snprintf(template, sizeof (template), "%s@SUNWzone", 316 zfs_get_name(zhp)) >= sizeof (template)) 317 return (Z_ERR); 318 319 cb.match_name = template; 320 cb.len = strlen(template); 321 cb.max = 0; 322 323 if (zfs_iter_snapshots(zhp, get_snap_max, &cb) != 0) 324 return (Z_ERR); 325 326 cb.max++; 327 328 if (snprintf(snapshot_name, snap_size, "%s@SUNWzone%d", 329 zfs_get_name(zhp), cb.max) >= snap_size) 330 return (Z_ERR); 331 332 if (pre_snapshot(source_zone) != Z_OK) 333 return (Z_ERR); 334 res = zfs_snapshot(snapshot_name); 335 if (post_snapshot(source_zone) != Z_OK) 336 return (Z_ERR); 337 338 if (res != 0) 339 return (Z_ERR); 340 return (Z_OK); 341 } 342 343 /* 344 * We are using an explicit snapshot from some earlier point in time so 345 * we need to validate it. This involves checking the sw inventory that 346 * we took when we made the snapshot to verify that the current sw config 347 * on the host is still valid to run a zone made from this snapshot. 348 */ 349 static int 350 validate_snapshot(char *snapshot_name, char *snap_path) 351 { 352 int err; 353 zone_dochandle_t handle; 354 zone_dochandle_t athandle = NULL; 355 356 if ((handle = zonecfg_init_handle()) == NULL) { 357 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 358 return (Z_ERR); 359 } 360 361 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 362 errno = err; 363 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 364 zonecfg_fini_handle(handle); 365 return (Z_ERR); 366 } 367 368 if ((athandle = zonecfg_init_handle()) == NULL) { 369 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 370 goto done; 371 } 372 373 if ((err = zonecfg_get_attach_handle(snap_path, target_zone, B_TRUE, 374 athandle)) != Z_OK) { 375 if (err == Z_NO_ZONE) 376 (void) fprintf(stderr, gettext("snapshot %s was not " 377 "taken\n\tby a 'zoneadm clone' command. It can " 378 "not be used to clone zones.\n"), snapshot_name); 379 else 380 (void) fprintf(stderr, gettext("snapshot %s is " 381 "out-dated\n\tIt can no longer be used to clone " 382 "zones on this system.\n"), snapshot_name); 383 goto done; 384 } 385 386 /* Get the detach information for the locally defined zone. */ 387 if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) { 388 errno = err; 389 zperror(gettext("getting the attach information failed"), 390 B_TRUE); 391 goto done; 392 } 393 394 if ((err = sw_cmp(handle, athandle, SW_CMP_SILENT)) != Z_OK) 395 (void) fprintf(stderr, gettext("snapshot %s is out-dated\n\t" 396 "It can no longer be used to clone zones on this " 397 "system.\n"), snapshot_name); 398 399 done: 400 zonecfg_fini_handle(handle); 401 if (athandle != NULL) 402 zonecfg_fini_handle(athandle); 403 404 return (err); 405 } 406 407 /* 408 * Remove the sw inventory file from inside this zonepath that we picked up out 409 * of the snapshot. 410 */ 411 static int 412 clean_out_clone() 413 { 414 int err; 415 zone_dochandle_t handle; 416 417 if ((handle = zonecfg_init_handle()) == NULL) { 418 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 419 return (Z_ERR); 420 } 421 422 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) { 423 errno = err; 424 zperror(cmd_to_str(CMD_CLONE), B_TRUE); 425 zonecfg_fini_handle(handle); 426 return (Z_ERR); 427 } 428 429 zonecfg_rm_detached(handle, B_FALSE); 430 zonecfg_fini_handle(handle); 431 432 return (Z_OK); 433 } 434 435 /* 436 * Make a ZFS clone on zonepath from snapshot_name. 437 */ 438 static int 439 clone_snap(char *snapshot_name, char *zonepath) 440 { 441 int res = Z_OK; 442 int err; 443 zfs_handle_t *zhp; 444 zfs_handle_t *clone; 445 446 if ((zhp = zfs_open(snapshot_name, ZFS_TYPE_SNAPSHOT)) == NULL) 447 return (Z_NO_ENTRY); 448 449 (void) printf(gettext("Cloning snapshot %s\n"), snapshot_name); 450 451 err = zfs_clone(zhp, zonepath); 452 zfs_close(zhp); 453 if (err != 0) 454 return (Z_ERR); 455 456 /* create the mountpoint if necessary */ 457 if ((clone = zfs_open(zonepath, ZFS_TYPE_ANY)) == NULL) 458 return (Z_ERR); 459 460 /* 461 * The clone has been created so we need to print a diagnostic 462 * message if one of the following steps fails for some reason. 463 */ 464 if (zfs_mount(clone, NULL, 0) != 0) { 465 (void) fprintf(stderr, gettext("could not mount ZFS clone " 466 "%s\n"), zfs_get_name(clone)); 467 res = Z_ERR; 468 469 } else { 470 if (zfs_prop_set(clone, ZFS_PROP_SHARENFS, "off") != 0) { 471 /* we won't consider this a failure */ 472 (void) fprintf(stderr, gettext("could not turn off the " 473 "'sharenfs' property on ZFS clone %s\n"), 474 zfs_get_name(clone)); 475 } 476 477 if (clean_out_clone() != Z_OK) { 478 (void) fprintf(stderr, gettext("could not remove the " 479 "software inventory from ZFS clone %s\n"), 480 zfs_get_name(clone)); 481 res = Z_ERR; 482 } 483 } 484 485 zfs_close(clone); 486 return (res); 487 } 488 489 /* 490 * This function takes a zonepath and attempts to determine what the ZFS 491 * file system name (not mountpoint) should be for that path. We do not 492 * assume that zonepath is an existing directory or ZFS fs since we use 493 * this function as part of the process of creating a new ZFS fs or clone. 494 * 495 * The way this works is that we look at the parent directory of the zonepath 496 * to see if it is a ZFS fs. If it is, we get the name of that ZFS fs and 497 * append the last component of the zonepath to generate the ZFS name for the 498 * zonepath. This matches the algorithm that ZFS uses for automatically 499 * mounting a new fs after it is created. 500 * 501 * Although a ZFS fs can be mounted anywhere, we don't worry about handling 502 * all of the complexity that a user could possibly configure with arbitrary 503 * mounts since there is no way to generate a ZFS name from a random path in 504 * the file system. We only try to handle the automatic mounts that ZFS does 505 * for each file system. ZFS restricts this so that a new fs must be created 506 * in an existing parent ZFS fs. It then automatically mounts the new fs 507 * directly under the mountpoint for the parent fs using the last component 508 * of the name as the mountpoint directory. 509 * 510 * For example: 511 * Name Mountpoint 512 * space/eng/dev/test/zone1 /project1/eng/dev/test/zone1 513 * 514 * Return Z_OK if the path mapped to a ZFS file system name, otherwise return 515 * Z_ERR. 516 */ 517 static int 518 path2name(char *zonepath, char *zfs_name, int len) 519 { 520 int res; 521 char *p; 522 zfs_handle_t *zhp; 523 524 if ((p = strrchr(zonepath, '/')) == NULL) 525 return (Z_ERR); 526 527 /* 528 * If the parent directory is not its own ZFS fs, then we can't 529 * automatically create a new ZFS fs at the 'zonepath' mountpoint 530 * so return an error. 531 */ 532 *p = '\0'; 533 zhp = mount2zhandle(zonepath); 534 *p = '/'; 535 if (zhp == NULL) 536 return (Z_ERR); 537 538 res = snprintf(zfs_name, len, "%s/%s", zfs_get_name(zhp), p + 1); 539 540 zfs_close(zhp); 541 if (res >= len) 542 return (Z_ERR); 543 544 return (Z_OK); 545 } 546 547 /* 548 * A ZFS file system iterator call-back function used to determine if the 549 * file system has dependents (snapshots & clones). 550 */ 551 /* ARGSUSED */ 552 static int 553 has_dependent(zfs_handle_t *zhp, void *data) 554 { 555 zfs_close(zhp); 556 return (1); 557 } 558 559 /* 560 * Given a snapshot name, get the file system path where the snapshot lives. 561 * A snapshot name is of the form fs_name@snap_name. For example, snapshot 562 * pl/zones/z1@SUNWzone1 would have a path of 563 * /pl/zones/z1/.zfs/snapshot/SUNWzone1. 564 */ 565 static int 566 snap2path(char *snap_name, char *path, int len) 567 { 568 char *p; 569 zfs_handle_t *zhp; 570 char mp[ZFS_MAXPROPLEN]; 571 572 if ((p = strrchr(snap_name, '@')) == NULL) 573 return (Z_ERR); 574 575 /* Get the file system name from the snap_name. */ 576 *p = '\0'; 577 zhp = zfs_open(snap_name, ZFS_TYPE_ANY); 578 *p = '@'; 579 if (zhp == NULL) 580 return (Z_ERR); 581 582 /* Get the file system mount point. */ 583 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL, 584 0, FALSE) != 0) { 585 zfs_close(zhp); 586 return (Z_ERR); 587 } 588 zfs_close(zhp); 589 590 p++; 591 if (snprintf(path, len, "%s/.zfs/snapshot/%s", mp, p) >= len) 592 return (Z_ERR); 593 594 return (Z_OK); 595 } 596 597 /* 598 * Clone a pre-existing ZFS snapshot, either by making a direct ZFS clone, if 599 * possible, or by copying the data from the snapshot to the zonepath. 600 */ 601 int 602 clone_snapshot_zfs(char *snap_name, char *zonepath) 603 { 604 int err = Z_OK; 605 char clone_name[MAXPATHLEN]; 606 char snap_path[MAXPATHLEN]; 607 608 if (snap2path(snap_name, snap_path, sizeof (snap_path)) != Z_OK) { 609 (void) fprintf(stderr, gettext("unable to find path for %s.\n"), 610 snap_name); 611 return (Z_ERR); 612 } 613 614 if (validate_snapshot(snap_name, snap_path) != Z_OK) 615 return (Z_NO_ENTRY); 616 617 /* 618 * The zonepath cannot be ZFS cloned, try to copy the data from 619 * within the snapshot to the zonepath. 620 */ 621 if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) { 622 if ((err = clone_copy(snap_path, zonepath)) == Z_OK) 623 if (clean_out_clone() != Z_OK) 624 (void) fprintf(stderr, 625 gettext("could not remove the " 626 "software inventory from %s\n"), zonepath); 627 628 return (err); 629 } 630 631 if ((err = clone_snap(snap_name, clone_name)) != Z_OK) { 632 if (err != Z_NO_ENTRY) { 633 /* 634 * Cloning the snapshot failed. Fall back to trying 635 * to install the zone by copying from the snapshot. 636 */ 637 if ((err = clone_copy(snap_path, zonepath)) == Z_OK) 638 if (clean_out_clone() != Z_OK) 639 (void) fprintf(stderr, 640 gettext("could not remove the " 641 "software inventory from %s\n"), 642 zonepath); 643 } else { 644 /* 645 * The snapshot is unusable for some reason so restore 646 * the zone state to configured since we were unable to 647 * actually do anything about getting the zone 648 * installed. 649 */ 650 int tmp; 651 652 if ((tmp = zone_set_state(target_zone, 653 ZONE_STATE_CONFIGURED)) != Z_OK) { 654 errno = tmp; 655 zperror2(target_zone, 656 gettext("could not set state")); 657 } 658 } 659 } 660 661 return (err); 662 } 663 664 /* 665 * Attempt to clone a source_zone to a target zonepath by using a ZFS clone. 666 */ 667 int 668 clone_zfs(char *source_zone, char *source_zonepath, char *zonepath) 669 { 670 zfs_handle_t *zhp; 671 char clone_name[MAXPATHLEN]; 672 char snap_name[MAXPATHLEN]; 673 674 /* 675 * Try to get a zfs handle for the source_zonepath. If this fails 676 * the source_zonepath is not ZFS so return an error. 677 */ 678 if ((zhp = mount2zhandle(source_zonepath)) == NULL) 679 return (Z_ERR); 680 681 /* 682 * Check if there is a file system already mounted on zonepath. If so, 683 * we can't clone to the path so we should fall back to copying. 684 */ 685 if (is_mountpnt(zonepath)) { 686 zfs_close(zhp); 687 (void) fprintf(stderr, 688 gettext("A file system is already mounted on %s,\n" 689 "preventing use of a ZFS clone.\n"), zonepath); 690 return (Z_ERR); 691 } 692 693 /* 694 * Instead of using path2name to get the clone name from the zonepath, 695 * we could generate a name from the source zone ZFS name. However, 696 * this would mean we would create the clone under the ZFS fs of the 697 * source instead of what the zonepath says. For example, 698 * 699 * source_zonepath zonepath 700 * /pl/zones/dev/z1 /pl/zones/deploy/z2 701 * 702 * We don't want the clone to be under "dev", we want it under 703 * "deploy", so that we can leverage the normal attribute inheritance 704 * that ZFS provides in the fs hierarchy. 705 */ 706 if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) { 707 zfs_close(zhp); 708 return (Z_ERR); 709 } 710 711 if (take_snapshot(source_zone, zhp, snap_name, sizeof (snap_name)) 712 != Z_OK) { 713 zfs_close(zhp); 714 return (Z_ERR); 715 } 716 zfs_close(zhp); 717 718 if (clone_snap(snap_name, clone_name) != Z_OK) 719 return (Z_ERR); 720 721 (void) printf(gettext("Instead of copying, a ZFS clone has been " 722 "created for this zone.\n")); 723 724 return (Z_OK); 725 } 726 727 /* 728 * Attempt to create a ZFS file system for the specified zonepath. 729 * We either will successfully create a ZFS file system and get it mounted 730 * on the zonepath or we don't. The caller doesn't care since a regular 731 * directory is used for the zonepath if no ZFS file system is mounted there. 732 */ 733 void 734 create_zfs_zonepath(char *zonepath) 735 { 736 zfs_handle_t *zhp; 737 char zfs_name[MAXPATHLEN]; 738 739 if (path2name(zonepath, zfs_name, sizeof (zfs_name)) != Z_OK) 740 return; 741 742 zfs_set_error_handler(noop_err_handler); 743 744 if (zfs_create(zfs_name, ZFS_TYPE_FILESYSTEM, NULL, NULL) != 0 || 745 (zhp = zfs_open(zfs_name, ZFS_TYPE_ANY)) == NULL) { 746 zfs_set_error_handler(NULL); 747 return; 748 } 749 750 if (zfs_mount(zhp, NULL, 0) != 0) { 751 (void) zfs_destroy(zhp); 752 } else if (zfs_prop_set(zhp, ZFS_PROP_SHARENFS, "off") != 0) { 753 (void) fprintf(stderr, gettext("file system %s successfully " 754 "created,\nbut could not turn off the 'sharenfs' " 755 "property\n"), zfs_name); 756 } else { 757 if (chmod(zonepath, S_IRWXU) != 0) { 758 (void) fprintf(stderr, gettext("file system %s " 759 "successfully created, but chmod %o failed: %s\n"), 760 zfs_name, S_IRWXU, strerror(errno)); 761 (void) destroy_zfs(zonepath); 762 } else { 763 (void) printf(gettext("A ZFS file system has been " 764 "created for this zone.\n")); 765 } 766 } 767 768 zfs_set_error_handler(NULL); 769 zfs_close(zhp); 770 } 771 772 /* 773 * If the zonepath is a ZFS file system, attempt to destroy it. We return Z_OK 774 * if we were able to zfs_destroy the zonepath, otherwise we return Z_ERR 775 * which means the caller should clean up the zonepath in the traditional 776 * way. 777 */ 778 int 779 destroy_zfs(char *zonepath) 780 { 781 zfs_handle_t *zhp; 782 boolean_t is_clone = B_FALSE; 783 char origin[ZFS_MAXPROPLEN]; 784 785 zfs_set_error_handler(noop_err_handler); 786 787 if ((zhp = mount2zhandle(zonepath)) == NULL) { 788 zfs_set_error_handler(NULL); 789 return (Z_ERR); 790 } 791 792 /* 793 * We can't destroy the file system if it has dependents. 794 */ 795 if (zfs_iter_dependents(zhp, has_dependent, NULL) != 0 || 796 zfs_unmount(zhp, NULL, 0) != 0) { 797 zfs_close(zhp); 798 zfs_set_error_handler(NULL); 799 return (Z_ERR); 800 } 801 802 /* 803 * This might be a clone. Try to get the snapshot so we can attempt 804 * to destroy that as well. 805 */ 806 if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL, 807 NULL, 0, FALSE) == 0) 808 is_clone = B_TRUE; 809 810 zfs_set_error_handler(NULL); 811 if (zfs_destroy(zhp) != 0) { 812 /* 813 * If the destroy fails for some reason, try to remount 814 * the file system so that we can use "rm -rf" to clean up 815 * instead. 816 */ 817 (void) zfs_mount(zhp, NULL, 0); 818 zfs_close(zhp); 819 return (Z_ERR); 820 } 821 zfs_set_error_handler(noop_err_handler); 822 823 (void) printf(gettext("The ZFS file system for this zone has been " 824 "destroyed.\n")); 825 826 if (is_clone) { 827 zfs_handle_t *ohp; 828 829 /* 830 * Try to clean up the snapshot that the clone was taken from. 831 */ 832 if ((ohp = zfs_open(origin, ZFS_TYPE_SNAPSHOT)) != NULL) { 833 if (zfs_iter_dependents(ohp, has_dependent, NULL) 834 == 0 && zfs_unmount(ohp, NULL, 0) == 0) { 835 (void) zfs_destroy(ohp); 836 } 837 zfs_close(ohp); 838 } 839 } 840 841 zfs_close(zhp); 842 zfs_set_error_handler(NULL); 843 return (Z_OK); 844 } 845 846 /* 847 * Return true if the path is its own zfs file system. We determine this 848 * by stat-ing the path to see if it is zfs and stat-ing the parent to see 849 * if it is a different fs. 850 */ 851 boolean_t 852 is_zonepath_zfs(char *zonepath) 853 { 854 int res; 855 char *path; 856 char *parent; 857 struct statvfs buf1, buf2; 858 859 if (statvfs(zonepath, &buf1) != 0) 860 return (B_FALSE); 861 862 if (strcmp(buf1.f_basetype, "zfs") != 0) 863 return (B_FALSE); 864 865 if ((path = strdup(zonepath)) == NULL) 866 return (B_FALSE); 867 868 parent = dirname(path); 869 res = statvfs(parent, &buf2); 870 free(path); 871 872 if (res != 0) 873 return (B_FALSE); 874 875 if (buf1.f_fsid == buf2.f_fsid) 876 return (B_FALSE); 877 878 return (B_TRUE); 879 } 880 881 /* 882 * Implement the fast move of a ZFS file system by simply updating the 883 * mountpoint. Since it is file system already, we don't have the 884 * issue of cross-file system copying. 885 */ 886 int 887 move_zfs(char *zonepath, char *new_zonepath) 888 { 889 int ret = Z_ERR; 890 zfs_handle_t *zhp; 891 892 zfs_set_error_handler(noop_err_handler); 893 894 if ((zhp = mount2zhandle(zonepath)) == NULL) { 895 zfs_set_error_handler(NULL); 896 return (Z_ERR); 897 } 898 899 if (zfs_prop_set(zhp, ZFS_PROP_MOUNTPOINT, new_zonepath) == 0) { 900 /* 901 * Clean up the old mount point. We ignore any failure since 902 * the zone is already successfully mounted on the new path. 903 */ 904 (void) rmdir(zonepath); 905 ret = Z_OK; 906 } 907 908 zfs_close(zhp); 909 zfs_set_error_handler(NULL); 910 911 return (ret); 912 } 913 914 /* 915 * Validate that the given dataset exists on the system, and that neither it nor 916 * its children are zvols. 917 * 918 * Note that we don't do anything with the 'zoned' property here. All 919 * management is done in zoneadmd when the zone is actually rebooted. This 920 * allows us to automatically set the zoned property even when a zone is 921 * rebooted by the administrator. 922 */ 923 int 924 verify_datasets(zone_dochandle_t handle) 925 { 926 int return_code = Z_OK; 927 struct zone_dstab dstab; 928 zfs_handle_t *zhp; 929 char propbuf[ZFS_MAXPROPLEN]; 930 char source[ZFS_MAXNAMELEN]; 931 zfs_source_t srctype; 932 933 if (zonecfg_setdsent(handle) != Z_OK) { 934 /* 935 * TRANSLATION_NOTE 936 * zfs and dataset are literals that should not be translated. 937 */ 938 (void) fprintf(stderr, gettext("could not verify zfs datasets: " 939 "unable to enumerate datasets\n")); 940 return (Z_ERR); 941 } 942 943 zfs_set_error_handler(err_handler); 944 945 while (zonecfg_getdsent(handle, &dstab) == Z_OK) { 946 947 current_dataset = dstab.zone_dataset_name; 948 949 if ((zhp = zfs_open(dstab.zone_dataset_name, 950 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) { 951 return_code = Z_ERR; 952 continue; 953 } 954 955 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, 956 sizeof (propbuf), &srctype, source, 957 sizeof (source), 0) == 0 && 958 (srctype == ZFS_SRC_INHERITED)) { 959 (void) fprintf(stderr, gettext("could not verify zfs " 960 "dataset %s: mountpoint cannot be inherited\n"), 961 dstab.zone_dataset_name); 962 return_code = Z_ERR; 963 zfs_close(zhp); 964 continue; 965 } 966 967 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) { 968 (void) fprintf(stderr, gettext("cannot verify zfs " 969 "dataset %s: volumes cannot be specified as a " 970 "zone dataset resource\n"), 971 dstab.zone_dataset_name); 972 return_code = Z_ERR; 973 } 974 975 if (zfs_iter_children(zhp, check_zvol, NULL) != 0) 976 return_code = Z_ERR; 977 978 zfs_close(zhp); 979 } 980 (void) zonecfg_enddsent(handle); 981 zfs_set_error_handler(NULL); 982 983 return (return_code); 984 } 985 986 /* 987 * Verify that the ZFS dataset exists, and its mountpoint 988 * property is set to "legacy". 989 */ 990 int 991 verify_fs_zfs(struct zone_fstab *fstab) 992 { 993 zfs_handle_t *zhp; 994 char propbuf[ZFS_MAXPROPLEN]; 995 996 zfs_set_error_handler(noop_err_handler); 997 998 if ((zhp = zfs_open(fstab->zone_fs_special, ZFS_TYPE_ANY)) == NULL) { 999 (void) fprintf(stderr, gettext("could not verify fs %s: " 1000 "could not access zfs dataset '%s'\n"), 1001 fstab->zone_fs_dir, fstab->zone_fs_special); 1002 zfs_set_error_handler(NULL); 1003 return (Z_ERR); 1004 } 1005 1006 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 1007 (void) fprintf(stderr, gettext("cannot verify fs %s: " 1008 "'%s' is not a file system\n"), 1009 fstab->zone_fs_dir, fstab->zone_fs_special); 1010 zfs_close(zhp); 1011 zfs_set_error_handler(NULL); 1012 return (Z_ERR); 1013 } 1014 1015 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf), 1016 NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) { 1017 (void) fprintf(stderr, gettext("could not verify fs %s: " 1018 "zfs '%s' mountpoint is not \"legacy\"\n"), 1019 fstab->zone_fs_dir, fstab->zone_fs_special); 1020 zfs_close(zhp); 1021 zfs_set_error_handler(NULL); 1022 return (Z_ERR); 1023 } 1024 1025 zfs_close(zhp); 1026 zfs_set_error_handler(NULL); 1027 return (Z_OK); 1028 } 1029