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