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