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