zfs.c revision ff17c8bf86c3e567734be83f90267edee20f580f
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * CDDL HEADER START
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The contents of this file are subject to the terms of the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Common Development and Distribution License (the "License").
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * You may not use this file except in compliance with the License.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * See the License for the specific language governing permissions
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * and limitations under the License.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * When distributing Covered Code, include this CDDL HEADER in each
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * If applicable, add the following below this CDDL HEADER, with the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * fields enclosed by brackets "[]" replaced with your own identifying
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * information: Portions Copyright [yyyy] [name of copyright owner]
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * CDDL HEADER END
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Use is subject to license terms.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#pragma ident "%Z%%M% %I% %E% SMI"
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * This file contains the functions used to support the ZFS integration
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * with zones. This includes validation (e.g. zonecfg dataset), cloning,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * file system creation and destruction.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinektypedef struct zfs_mount_data {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinektypedef struct zfs_snapshot_data {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * A ZFS file system iterator call-back function which is used to validate
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * datasets imported into the zone.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek/* ARGSUSED */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * TRANSLATION_NOTE
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * zfs and dataset are literals that should not be translated.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("cannot verify zfs dataset %s: "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "volumes cannot be specified as a zone dataset resource\n"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * A ZFS file system iterator call-back function which returns the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * zfs_handle_t for a ZFS file system on the specified mount point.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (0);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL,
99653d4ee642c6528e88224f12409a5f23060994eschrock 0, B_FALSE) == 0 && strcmp(mp, cbp->match_name) == 0) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (1);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek res = zfs_iter_filesystems(zhp, match_mountpoint, data);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Get ZFS handle for the specified mount point.
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) zfs_iter_root(g_zfs, match_mountpoint, &cb);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Check if there is already a file system (zfs or any other type) mounted on
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * Run the brand's pre-snapshot hook before we take a ZFS snapshot of the zone.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /* No brand-specific handler */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /* Run the hook */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek if ((status = subproc_status(gettext("brand-specific presnapshot"),
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * Run the brand's post-snapshot hook after we take a ZFS snapshot of the zone.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /* No brand-specific handler */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /* Run the hook */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek if ((status = subproc_status(gettext("brand-specific postsnapshot"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * This is a ZFS snapshot iterator call-back function which returns the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * highest number of SUNWzone snapshots that have been taken.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (0);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (strncmp(zfs_get_name(zhp), cbp->match_name, cbp->len) == 0) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Take a ZFS snapshot to be used for cloning the zone.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinektake_snapshot(zfs_handle_t *zhp, char *snapshot_name, int snap_size,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * First we need to figure out the next available name for the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * zone snapshot. Look through the list of zones snapshots for
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * this file system to determine the maximum snapshot name.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (snprintf(template, sizeof (template), "%s@SUNWzone",
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (zfs_iter_snapshots(zhp, get_snap_max, &cb) != 0)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (snprintf(snapshot_name, snap_size, "%s@SUNWzone%d",
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * We are using an explicit snapshot from some earlier point in time so
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * we need to validate it. Run the brand specific hook.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinekvalidate_snapshot(char *snapshot_name, char *snap_path, char *validsnapbuf)
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /* No brand-specific handler */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /* pass args - snapshot_name & snap_path */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %s %s", validsnapbuf,
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /* Run the hook */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek if ((status = subproc_status(gettext("brand-specific validatesnapshot"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Remove the sw inventory file from inside this zonepath that we picked up out
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * of the snapshot.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Make a ZFS clone on zonepath from snapshot_name.
99653d4ee642c6528e88224f12409a5f23060994eschrock if ((zhp = zfs_open(g_zfs, snapshot_name, ZFS_TYPE_SNAPSHOT)) == NULL)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) printf(gettext("Cloning snapshot %s\n"), snapshot_name);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
5f8e16172ef40e14cf931b329fedb86ea369a42cnn nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
5f8e16172ef40e14cf931b329fedb86ea369a42cnn "off") != 0) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock (void) fprintf(stderr, gettext("could not create ZFS clone "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /* create the mountpoint if necessary */
990b4856d0eaada6f8140335733a1b1771ed2746lling if ((clone = zfs_open(g_zfs, zonepath, ZFS_TYPE_DATASET)) == NULL)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The clone has been created so we need to print a diagnostic
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * message if one of the following steps fails for some reason.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("could not mount ZFS clone "
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock (void) fprintf(stderr, gettext("could not remove the "
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock "software inventory from ZFS clone %s\n"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * This function takes a zonepath and attempts to determine what the ZFS
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * file system name (not mountpoint) should be for that path. We do not
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * assume that zonepath is an existing directory or ZFS fs since we use
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * this function as part of the process of creating a new ZFS fs or clone.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The way this works is that we look at the parent directory of the zonepath
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * to see if it is a ZFS fs. If it is, we get the name of that ZFS fs and
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * append the last component of the zonepath to generate the ZFS name for the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * zonepath. This matches the algorithm that ZFS uses for automatically
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * mounting a new fs after it is created.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Although a ZFS fs can be mounted anywhere, we don't worry about handling
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * all of the complexity that a user could possibly configure with arbitrary
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * mounts since there is no way to generate a ZFS name from a random path in
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the file system. We only try to handle the automatic mounts that ZFS does
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * for each file system. ZFS restricts this so that a new fs must be created
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * in an existing parent ZFS fs. It then automatically mounts the new fs
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * directly under the mountpoint for the parent fs using the last component
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * of the name as the mountpoint directory.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * For example:
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Name Mountpoint
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * space/eng/dev/test/zone1 /project1/eng/dev/test/zone1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Return Z_OK if the path mapped to a ZFS file system name, otherwise return
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * If the parent directory is not its own ZFS fs, then we can't
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * automatically create a new ZFS fs at the 'zonepath' mountpoint
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * so return an error.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek res = snprintf(zfs_name, len, "%s/%s", zfs_get_name(zhp), p + 1);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * A ZFS file system iterator call-back function used to determine if the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * file system has dependents (snapshots & clones).
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek/* ARGSUSED */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (1);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Given a snapshot name, get the file system path where the snapshot lives.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * A snapshot name is of the form fs_name@snap_name. For example, snapshot
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * pl/zones/z1@SUNWzone1 would have a path of
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /* Get the file system name from the snap_name. */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /* Get the file system mount point. */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (snprintf(path, len, "%s/.zfs/snapshot/%s", mp, p) >= len)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Clone a pre-existing ZFS snapshot, either by making a direct ZFS clone, if
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * possible, or by copying the data from the snapshot to the zonepath.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinekclone_snapshot_zfs(char *snap_name, char *zonepath, char *validatesnap)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (snap2path(snap_name, snap_path, sizeof (snap_path)) != Z_OK) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("unable to find path for %s.\n"),
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek if (validate_snapshot(snap_name, snap_path, validatesnap) != Z_OK)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The zonepath cannot be ZFS cloned, try to copy the data from
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * within the snapshot to the zonepath.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((err = clone_copy(snap_path, zonepath)) == Z_OK)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((err = clone_snap(snap_name, clone_name)) != Z_OK) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Cloning the snapshot failed. Fall back to trying
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * to install the zone by copying from the snapshot.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((err = clone_copy(snap_path, zonepath)) == Z_OK)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "software inventory from %s\n"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The snapshot is unusable for some reason so restore
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the zone state to configured since we were unable to
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * actually do anything about getting the zone
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * installed.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Attempt to clone a source_zone to a target zonepath by using a ZFS clone.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinekclone_zfs(char *source_zonepath, char *zonepath, char *presnapbuf,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Try to get a zfs handle for the source_zonepath. If this fails
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the source_zonepath is not ZFS so return an error.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((zhp = mount2zhandle(source_zonepath)) == NULL)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Check if there is a file system already mounted on zonepath. If so,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * we can't clone to the path so we should fall back to copying.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek gettext("A file system is already mounted on %s,\n"
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Instead of using path2name to get the clone name from the zonepath,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * we could generate a name from the source zone ZFS name. However,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * this would mean we would create the clone under the ZFS fs of the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * source instead of what the zonepath says. For example,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * source_zonepath zonepath
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * We don't want the clone to be under "dev", we want it under
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * "deploy", so that we can leverage the normal attribute inheritance
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * that ZFS provides in the fs hierarchy.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) {
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek if (take_snapshot(zhp, snap_name, sizeof (snap_name), presnapbuf,
d9e728a2c2e62adeef072d782e4c8a7b34e7e8e8gjelinek /* Clean up the snapshot we just took. */
d9e728a2c2e62adeef072d782e4c8a7b34e7e8e8gjelinek if ((zhp = zfs_open(g_zfs, snap_name, ZFS_TYPE_SNAPSHOT))
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) printf(gettext("Instead of copying, a ZFS clone has been "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "created for this zone.\n"));
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Attempt to create a ZFS file system for the specified zonepath.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * We either will successfully create a ZFS file system and get it mounted
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * on the zonepath or we don't. The caller doesn't care since a regular
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * directory is used for the zonepath if no ZFS file system is mounted there.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (path2name(zonepath, zfs_name, sizeof (zfs_name)) != Z_OK)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
5f8e16172ef40e14cf931b329fedb86ea369a42cnn nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
5f8e16172ef40e14cf931b329fedb86ea369a42cnn "off") != 0) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock (void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (zfs_create(g_zfs, zfs_name, ZFS_TYPE_FILESYSTEM, props) != 0 ||
990b4856d0eaada6f8140335733a1b1771ed2746lling (zhp = zfs_open(g_zfs, zfs_name, ZFS_TYPE_DATASET)) == NULL) {
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
99653d4ee642c6528e88224f12409a5f23060994eschrock "%s\n"), zfs_name, libzfs_error_description(g_zfs));
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) fprintf(stderr, gettext("cannot mount ZFS dataset %s: "
99653d4ee642c6528e88224f12409a5f23060994eschrock "%s\n"), zfs_name, libzfs_error_description(g_zfs));
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "successfully created, but chmod %o failed: %s\n"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) printf(gettext("A ZFS file system has been "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "created for this zone.\n"));
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * If the zonepath is a ZFS file system, attempt to destroy it. We return Z_OK
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * if we were able to zfs_destroy the zonepath, otherwise we return Z_ERR
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * which means the caller should clean up the zonepath in the traditional
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * We can't destroy the file system if it has dependents.
3bb79bece53191f2cf27aa61a72ea1784a7ce700eschrock if (zfs_iter_dependents(zhp, B_TRUE, has_dependent, NULL) != 0 ||
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * This might be a clone. Try to get the snapshot so we can attempt
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * to destroy that as well.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * If the destroy fails for some reason, try to remount
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the file system so that we can use "rm -rf" to clean up
d9e728a2c2e62adeef072d782e4c8a7b34e7e8e8gjelinek * If the zone has ever been moved then the mountpoint dir will not be
d9e728a2c2e62adeef072d782e4c8a7b34e7e8e8gjelinek * cleaned up by the zfs_destroy(). To handle this case try to clean
d9e728a2c2e62adeef072d782e4c8a7b34e7e8e8gjelinek * it up now but don't worry if it fails, that will be normal.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) printf(gettext("The ZFS file system for this zone has been "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "destroyed.\n"));
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Try to clean up the snapshot that the clone was taken from.
3bb79bece53191f2cf27aa61a72ea1784a7ce700eschrock if (zfs_iter_dependents(ohp, B_TRUE, has_dependent,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Return true if the path is its own zfs file system. We determine this
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * by stat-ing the path to see if it is zfs and stat-ing the parent to see
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * if it is a different fs.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Implement the fast move of a ZFS file system by simply updating the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * mountpoint. Since it is file system already, we don't have the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * issue of cross-file system copying.
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Clean up the old mount point. We ignore any failure since
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the zone is already successfully mounted on the new path.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Validate that the given dataset exists on the system, and that neither it nor
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * its children are zvols.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Note that we don't do anything with the 'zoned' property here. All
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * management is done in zoneadmd when the zone is actually rebooted. This
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * allows us to automatically set the zoned property even when a zone is
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * rebooted by the administrator.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * TRANSLATION_NOTE
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * zfs and dataset are literals that should not be translated.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("could not verify zfs datasets: "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "unable to enumerate datasets\n"));
99653d4ee642c6528e88224f12409a5f23060994eschrock if ((zhp = zfs_open(g_zfs, dstab.zone_dataset_name,
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) fprintf(stderr, gettext("could not verify zfs "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek sizeof (source), 0) == 0 &&
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("could not verify zfs "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "dataset %s: mountpoint cannot be inherited\n"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("cannot verify zfs "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "dataset %s: volumes cannot be specified as a "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "zone dataset resource\n"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Verify that the ZFS dataset exists, and its mountpoint
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * property is set to "legacy".
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("could not verify fs %s: "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "could not access zfs dataset '%s'\n"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("cannot verify fs %s: "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "'%s' is not a file system\n"),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (void) fprintf(stderr, gettext("could not verify fs %s: "
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek "zfs '%s' mountpoint is not \"legacy\"\n"),
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) fprintf(stderr, gettext("failed to initialize ZFS "
99653d4ee642c6528e88224f12409a5f23060994eschrock "library\n"));