summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorjv227347 <Jordan.Vaughan@Sun.com>2009-12-07 16:44:49 -0800
committerjv227347 <Jordan.Vaughan@Sun.com>2009-12-07 16:44:49 -0800
commit0094b373ead542a342e4250eaf37854ccd3e50c0 (patch)
treec69e6bf413789e6956ec187f6b1e7efea1137548 /usr/src
parent0f79c548a94d01d7494ec7ffa3bc72cda00b4f7c (diff)
downloadillumos-gate-0094b373ead542a342e4250eaf37854ccd3e50c0.tar.gz
6880335 zoneadm move needs brand hook
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/zoneadm/zfs.c391
-rw-r--r--usr/src/cmd/zoneadm/zoneadm.c95
-rw-r--r--usr/src/cmd/zoneadm/zoneadm.h43
-rw-r--r--usr/src/cmd/zoneadmd/vplat.c4
-rw-r--r--usr/src/head/libzonecfg.h5
-rw-r--r--usr/src/lib/brand/native/zone/sw_support.c4
-rw-r--r--usr/src/lib/libzonecfg/common/libzonecfg.c8
7 files changed, 519 insertions, 31 deletions
diff --git a/usr/src/cmd/zoneadm/zfs.c b/usr/src/cmd/zoneadm/zfs.c
index 1d52db5a66..694f44937e 100644
--- a/usr/src/cmd/zoneadm/zfs.c
+++ b/usr/src/cmd/zoneadm/zfs.c
@@ -44,6 +44,8 @@
#include <libzfs.h>
#include <sys/mntent.h>
#include <values.h>
+#include <strings.h>
+#include <assert.h>
#include "zoneadm.h"
@@ -1300,6 +1302,395 @@ verify_fs_zfs(struct zone_fstab *fstab)
return (Z_OK);
}
+/*
+ * Destroy the specified mnttab structure that was created by mnttab_dup().
+ * NOTE: The structure's mnt_time field isn't freed.
+ */
+static void
+mnttab_destroy(struct mnttab *tabp)
+{
+ assert(tabp != NULL);
+
+ free(tabp->mnt_mountp);
+ free(tabp->mnt_special);
+ free(tabp->mnt_fstype);
+ free(tabp->mnt_mntopts);
+ free(tabp);
+}
+
+/*
+ * Duplicate the specified mnttab structure. The mnt_mountp and mnt_time
+ * fields aren't duplicated. This function returns a pointer to the new mnttab
+ * structure or NULL if an error occurred. If an error occurs, then this
+ * function sets errno to reflect the error. mnttab structures created by
+ * this function should be destroyed via mnttab_destroy().
+ */
+static struct mnttab *
+mnttab_dup(const struct mnttab *srcp)
+{
+ struct mnttab *retval;
+
+ assert(srcp != NULL);
+
+ retval = (struct mnttab *)calloc(1, sizeof (*retval));
+ if (retval == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ if (srcp->mnt_special != NULL) {
+ retval->mnt_special = strdup(srcp->mnt_special);
+ if (retval->mnt_special == NULL)
+ goto err;
+ }
+ if (srcp->mnt_fstype != NULL) {
+ retval->mnt_fstype = strdup(srcp->mnt_fstype);
+ if (retval->mnt_fstype == NULL)
+ goto err;
+ }
+ retval->mnt_mntopts = (char *)malloc(MAX_MNTOPT_STR * sizeof (char));
+ if (retval->mnt_mntopts == NULL)
+ goto err;
+ if (srcp->mnt_mntopts != NULL) {
+ if (strlcpy(retval->mnt_mntopts, srcp->mnt_mntopts,
+ MAX_MNTOPT_STR * sizeof (char)) >= MAX_MNTOPT_STR *
+ sizeof (char)) {
+ mnttab_destroy(retval);
+ errno = EOVERFLOW; /* similar to mount(2) behavior */
+ return (NULL);
+ }
+ } else {
+ retval->mnt_mntopts[0] = '\0';
+ }
+ return (retval);
+
+err:
+ mnttab_destroy(retval);
+ errno = ENOMEM;
+ return (NULL);
+}
+
+/*
+ * Determine whether the specified ZFS dataset's mountpoint property is set
+ * to "legacy". If the specified dataset does not have a legacy mountpoint,
+ * then the string pointer to which the mountpoint argument points is assigned
+ * a dynamically-allocated string containing the dataset's mountpoint
+ * property. If the dataset's mountpoint property is "legacy" or a libzfs
+ * error occurs, then the string pointer to which the mountpoint argument
+ * points isn't modified.
+ *
+ * This function returns B_TRUE if it doesn't encounter any fatal errors.
+ * It returns B_FALSE if it encounters a fatal error and sets errno to the
+ * appropriate error code.
+ */
+static boolean_t
+get_zfs_non_legacy_mountpoint(const char *dataset_name, char **mountpoint)
+{
+ zfs_handle_t *zhp;
+ char propbuf[ZFS_MAXPROPLEN];
+
+ assert(dataset_name != NULL);
+ assert(mountpoint != NULL);
+
+ if ((zhp = zfs_open(g_zfs, dataset_name, ZFS_TYPE_DATASET)) == NULL) {
+ errno = EINVAL;
+ return (B_FALSE);
+ }
+ if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf),
+ NULL, NULL, 0, 0) != 0) {
+ zfs_close(zhp);
+ errno = EINVAL;
+ return (B_FALSE);
+ }
+ zfs_close(zhp);
+ if (strcmp(propbuf, "legacy") != 0) {
+ if ((*mountpoint = strdup(propbuf)) == NULL) {
+ errno = ENOMEM;
+ return (B_FALSE);
+ }
+ }
+ return (B_TRUE);
+}
+
+
+/*
+ * This zonecfg_find_mounts() callback records information about mounts of
+ * interest in a zonepath. It also tallies the number of zone
+ * root overlay mounts and the number of unexpected mounts found.
+ * This function outputs errors using zerror() if it finds unexpected
+ * mounts. cookiep should point to an initialized zone_mounts_t structure.
+ *
+ * This function returns zero on success and a nonzero value on failure.
+ */
+static int
+zone_mounts_cb(const struct mnttab *mountp, void *cookiep)
+{
+ zone_mounts_t *mounts;
+ const char *zone_mount_dir;
+
+ assert(mountp != NULL);
+ assert(cookiep != NULL);
+
+ mounts = (zone_mounts_t *)cookiep;
+ zone_mount_dir = mountp->mnt_mountp + mounts->zonepath_len;
+ if (strcmp(zone_mount_dir, "/root") == 0) {
+ /*
+ * Check for an overlay mount. If we already detected a /root
+ * mount, then the current mount must be an overlay mount.
+ */
+ if (mounts->root_mnttab != NULL) {
+ mounts->num_root_overlay_mounts++;
+ return (0);
+ }
+
+ /*
+ * Store the root mount's mnttab information in the
+ * zone_mounts_t structure for future use.
+ */
+ if ((mounts->root_mnttab = mnttab_dup(mountp)) == NULL) {
+ zperror(cmd_to_str(CMD_MOVE), B_FALSE);
+ return (-1);
+ }
+
+ /*
+ * Determine if the filesystem is a ZFS filesystem with a
+ * non-legacy mountpoint. If it is, then set the root
+ * filesystem's mnttab's mnt_mountp field to a non-NULL
+ * value, which will serve as a flag to indicate this special
+ * condition.
+ */
+ if (strcmp(mountp->mnt_fstype, MNTTYPE_ZFS) == 0 &&
+ get_zfs_non_legacy_mountpoint(mountp->mnt_special,
+ &mounts->root_mnttab->mnt_mountp) != B_TRUE) {
+ zperror(cmd_to_str(CMD_MOVE), B_FALSE);
+ return (-1);
+ }
+ } else {
+ /*
+ * An unexpected mount was found. Notify the user.
+ */
+ if (mounts->num_unexpected_mounts == 0)
+ zerror(gettext("These file systems are mounted on "
+ "subdirectories of %s.\n"), mounts->zonepath);
+ mounts->num_unexpected_mounts++;
+ (void) zfm_print(mountp, NULL);
+ }
+ return (0);
+}
+
+/*
+ * Initialize the specified zone_mounts_t structure for the given zonepath.
+ * If this function succeeds, it returns zero and the specified zone_mounts_t
+ * structure contains information about mounts in the specified zonepath.
+ * The function returns a nonzero value if it fails. The zone_mounts_t
+ * structure doesn't need be destroyed via zone_mounts_destroy() if this
+ * function fails.
+ */
+int
+zone_mounts_init(zone_mounts_t *mounts, const char *zonepath)
+{
+ assert(mounts != NULL);
+ assert(zonepath != NULL);
+
+ bzero(mounts, sizeof (*mounts));
+ if ((mounts->zonepath = strdup(zonepath)) == NULL) {
+ zerror(gettext("the process ran out of memory while checking "
+ "for mounts in zonepath %s."), zonepath);
+ return (-1);
+ }
+ mounts->zonepath_len = strlen(zonepath);
+ if (zonecfg_find_mounts((char *)zonepath, zone_mounts_cb, mounts) ==
+ -1) {
+ zerror(gettext("an error occurred while checking for mounts "
+ "in zonepath %s."), zonepath);
+ zone_mounts_destroy(mounts);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Destroy the memory used by the specified zone_mounts_t structure's fields.
+ * This function doesn't free the memory occupied by the structure itself
+ * (i.e., it doesn't free the parameter).
+ */
+void
+zone_mounts_destroy(zone_mounts_t *mounts)
+{
+ assert(mounts != NULL);
+
+ free(mounts->zonepath);
+ if (mounts->root_mnttab != NULL)
+ mnttab_destroy(mounts->root_mnttab);
+}
+
+/*
+ * Mount a moving zone's root filesystem (if it had a root filesystem mount
+ * prior to the move) using the specified zonepath. mounts should refer to
+ * the zone_mounts_t structure describing the zone's mount information.
+ *
+ * This function returns zero if the mount succeeds and a nonzero value
+ * if it doesn't.
+ */
+int
+zone_mount_rootfs(zone_mounts_t *mounts, const char *zonepath)
+{
+ char zoneroot[MAXPATHLEN];
+ struct mnttab *mtab;
+ int flags;
+
+ assert(mounts != NULL);
+ assert(zonepath != NULL);
+
+ /*
+ * If there isn't a root filesystem, then don't do anything.
+ */
+ mtab = mounts->root_mnttab;
+ if (mtab == NULL)
+ return (0);
+
+ /*
+ * Determine the root filesystem's new mountpoint.
+ */
+ if (snprintf(zoneroot, sizeof (zoneroot), "%s/root", zonepath) >=
+ sizeof (zoneroot)) {
+ zerror(gettext("Zonepath %s is too long.\n"), zonepath);
+ return (-1);
+ }
+
+ /*
+ * If the root filesystem is a non-legacy ZFS filesystem (i.e., if it's
+ * mnt_mountp field is non-NULL), then make the filesystem's new
+ * mount point its mountpoint property and mount the filesystem.
+ */
+ if (mtab->mnt_mountp != NULL) {
+ zfs_handle_t *zhp;
+
+ if ((zhp = zfs_open(g_zfs, mtab->mnt_special,
+ ZFS_TYPE_DATASET)) == NULL) {
+ zerror(gettext("could not get ZFS handle for the zone's"
+ " root filesystem"));
+ return (-1);
+ }
+ if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
+ zoneroot) != 0) {
+ zerror(gettext("could not modify zone's root "
+ "filesystem's mountpoint property"));
+ zfs_close(zhp);
+ return (-1);
+ }
+ if (zfs_mount(zhp, mtab->mnt_mntopts, 0) != 0) {
+ zerror(gettext("unable to mount zone root %s: %s"),
+ zoneroot, libzfs_error_description(g_zfs));
+ if (zfs_prop_set(zhp,
+ zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
+ mtab->mnt_mountp) != 0)
+ zerror(gettext("unable to restore zone's root "
+ "filesystem's mountpoint property"));
+ zfs_close(zhp);
+ return (-1);
+ }
+ zfs_close(zhp);
+ return (0);
+ }
+
+ /*
+ * The root filesystem is either a legacy-mounted ZFS filesystem or
+ * a non-ZFS filesystem. Use mount(2) to mount the root filesystem.
+ */
+ if (mtab->mnt_mntopts != NULL)
+ flags = MS_OPTIONSTR;
+ else
+ flags = 0;
+ if (mount(mtab->mnt_special, zoneroot, flags, mtab->mnt_fstype, NULL, 0,
+ mtab->mnt_mntopts, MAX_MNTOPT_STR * sizeof (char)) != 0) {
+ flags = errno;
+ zerror(gettext("unable to mount zone root %s: %s"), zoneroot,
+ strerror(flags));
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Unmount a moving zone's root filesystem (if such a mount exists) using the
+ * specified zonepath. mounts should refer to the zone_mounts_t structure
+ * describing the zone's mount information. If force is B_TRUE, then if the
+ * unmount fails, then the function will try to forcibly unmount the zone's root
+ * filesystem.
+ *
+ * This function returns zero if the unmount (forced or otherwise) succeeds;
+ * otherwise, it returns a nonzero value.
+ */
+int
+zone_unmount_rootfs(zone_mounts_t *mounts, const char *zonepath,
+ boolean_t force)
+{
+ char zoneroot[MAXPATHLEN];
+ struct mnttab *mtab;
+ int err;
+
+ assert(mounts != NULL);
+ assert(zonepath != NULL);
+
+ /*
+ * If there isn't a root filesystem, then don't do anything.
+ */
+ mtab = mounts->root_mnttab;
+ if (mtab == NULL)
+ return (0);
+
+ /*
+ * Determine the root filesystem's mountpoint.
+ */
+ if (snprintf(zoneroot, sizeof (zoneroot), "%s/root", zonepath) >=
+ sizeof (zoneroot)) {
+ zerror(gettext("Zonepath %s is too long.\n"), zonepath);
+ return (-1);
+ }
+
+ /*
+ * If the root filesystem is a non-legacy ZFS fileystem, then unmount
+ * the filesystem via libzfs.
+ */
+ if (mtab->mnt_mountp != NULL) {
+ zfs_handle_t *zhp;
+
+ if ((zhp = zfs_open(g_zfs, mtab->mnt_special,
+ ZFS_TYPE_DATASET)) == NULL) {
+ zerror(gettext("could not get ZFS handle for the zone's"
+ " root filesystem"));
+ return (-1);
+ }
+ if (zfs_unmount(zhp, zoneroot, 0) != 0) {
+ if (force && zfs_unmount(zhp, zoneroot, MS_FORCE) ==
+ 0) {
+ zfs_close(zhp);
+ return (0);
+ }
+ zerror(gettext("unable to unmount zone root %s: %s"),
+ zoneroot, libzfs_error_description(g_zfs));
+ zfs_close(zhp);
+ return (-1);
+ }
+ zfs_close(zhp);
+ return (0);
+ }
+
+ /*
+ * Use umount(2) to unmount the root filesystem. If this fails, then
+ * forcibly unmount it if the force flag is set.
+ */
+ if (umount(zoneroot) != 0) {
+ if (force && umount2(zoneroot, MS_FORCE) == 0)
+ return (0);
+ err = errno;
+ zerror(gettext("unable to unmount zone root %s: %s"), zoneroot,
+ strerror(err));
+ return (-1);
+ }
+ return (0);
+}
+
int
init_zfs(void)
{
diff --git a/usr/src/cmd/zoneadm/zoneadm.c b/usr/src/cmd/zoneadm/zoneadm.c
index 058de1e7ed..af08db8d70 100644
--- a/usr/src/cmd/zoneadm/zoneadm.c
+++ b/usr/src/cmd/zoneadm/zoneadm.c
@@ -3488,9 +3488,9 @@ copy_zone(char *src, char *dst)
}
/* ARGSUSED */
-static int
-zfm_print(const char *p, void *r) {
- zerror(" %s\n", p);
+int
+zfm_print(const struct mnttab *p, void *r) {
+ zerror(" %s\n", p->mnt_mountp);
return (0);
}
@@ -3951,12 +3951,14 @@ move_func(int argc, char *argv[])
zone_dochandle_t handle;
boolean_t fast;
boolean_t is_zfs = B_FALSE;
+ boolean_t root_fs_mounted = B_FALSE;
struct dirent *dp;
DIR *dirp;
boolean_t empty = B_TRUE;
boolean_t revert;
struct stat zonepath_buf;
struct stat new_zonepath_buf;
+ zone_mounts_t mounts;
if (zonecfg_in_alt_root()) {
zerror(gettext("cannot move zone in alternate root"));
@@ -4033,13 +4035,20 @@ move_func(int argc, char *argv[])
return (Z_ERR);
}
- /* Don't move the zone if anything is still mounted there */
- if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
- zerror(gettext("These file systems are mounted on "
- "subdirectories of %s.\n"), zonepath);
- (void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
+ /*
+ * Collect information about mounts within the zone's zonepath.
+ * Overlay mounts on the zone's root directory are erroneous.
+ * Bail if we encounter any unexpected mounts.
+ */
+ if (zone_mounts_init(&mounts, zonepath) != 0)
return (Z_ERR);
+ if (mounts.num_root_overlay_mounts != 0) {
+ zerror(gettext("%d overlay mount(s) detected on %s/root."),
+ mounts.num_root_overlay_mounts, zonepath);
+ goto err_and_mounts_destroy;
}
+ if (mounts.num_unexpected_mounts != 0)
+ goto err_and_mounts_destroy;
/*
* Check if we are moving in the same file system and can do a fast
@@ -4049,24 +4058,29 @@ move_func(int argc, char *argv[])
if ((handle = zonecfg_init_handle()) == NULL) {
zperror(cmd_to_str(CMD_MOVE), B_TRUE);
- return (Z_ERR);
+ goto err_and_mounts_destroy;
}
if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
errno = err;
zperror(cmd_to_str(CMD_MOVE), B_TRUE);
- zonecfg_fini_handle(handle);
- return (Z_ERR);
+ goto err_and_fini_handle;
}
if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
zerror(gettext("another %s may have an operation in progress."),
"zoneadm");
- zonecfg_fini_handle(handle);
- return (Z_ERR);
+ goto err_and_fini_handle;
}
/*
+ * Unmount the zone's root filesystem before we move the zone's
+ * zonepath.
+ */
+ if (zone_unmount_rootfs(&mounts, zonepath, B_FALSE) != 0)
+ goto err_and_rele_lockfile;
+
+ /*
* We're making some file system changes now so we have to clean up
* the file system before we are done. This will either clean up the
* new zonepath if the zonecfg update failed or it will clean up the
@@ -4088,9 +4102,8 @@ move_func(int argc, char *argv[])
if (rmdir(new_zonepath) != 0) {
zperror(gettext("could not rmdir new zone path"),
B_FALSE);
- zonecfg_fini_handle(handle);
- zonecfg_release_lock_file(target_zone, lockfd);
- return (Z_ERR);
+ (void) zone_mount_rootfs(&mounts, zonepath);
+ goto err_and_rele_lockfile;
}
if (rename(zonepath, new_zonepath) != 0) {
@@ -4100,9 +4113,8 @@ move_func(int argc, char *argv[])
* so just return from this error.
*/
zperror(gettext("could not move zone"), B_FALSE);
- zonecfg_fini_handle(handle);
- zonecfg_release_lock_file(target_zone, lockfd);
- return (Z_ERR);
+ (void) zone_mount_rootfs(&mounts, zonepath);
+ goto err_and_rele_lockfile;
}
} else {
@@ -4125,6 +4137,16 @@ move_func(int argc, char *argv[])
goto done;
}
+ /*
+ * Mount the zone's root filesystem in the new zonepath if there was
+ * a root mount prior to the move.
+ */
+ if (zone_mount_rootfs(&mounts, new_zonepath) != 0) {
+ err = Z_ERR;
+ goto done;
+ }
+ root_fs_mounted = B_TRUE;
+
if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) {
errno = err;
zperror(gettext("could not set new zonepath"), B_TRUE);
@@ -4149,6 +4171,24 @@ done:
* or we clean up the old zonepath if everything is ok.
*/
if (revert) {
+ /*
+ * Check for the unlikely scenario in which the zone's
+ * zonepath and its root file system moved but libzonecfg
+ * couldn't save the new zonepath to the zone's configuration
+ * file. The mounted root filesystem must be unmounted before
+ * zoneadm restores the zone's zonepath.
+ */
+ if (root_fs_mounted && zone_unmount_rootfs(&mounts,
+ new_zonepath, B_TRUE) != 0) {
+ /*
+ * We can't forcibly unmount the zone's root file system
+ * from the new zonepath. Bail!
+ */
+ zerror(gettext("fatal error: cannot unmount %s/root\n"),
+ new_zonepath);
+ goto err_and_mounts_destroy;
+ }
+
/* The zonecfg update failed, cleanup the new zonepath. */
if (is_zfs) {
if (move_zfs(new_zonepath, zonepath) == Z_ERR) {
@@ -4158,8 +4198,9 @@ done:
/*
* err is already != Z_OK since we're reverting
*/
+ } else {
+ (void) zone_mount_rootfs(&mounts, zonepath);
}
-
} else if (fast) {
if (rename(new_zonepath, zonepath) != 0) {
zperror(gettext("could not restore zonepath"),
@@ -4167,6 +4208,8 @@ done:
/*
* err is already != Z_OK since we're reverting
*/
+ } else {
+ (void) zone_mount_rootfs(&mounts, zonepath);
}
} else {
(void) printf(gettext("Cleaning up zonepath %s..."),
@@ -4187,8 +4230,9 @@ done:
*/
err = Z_ERR;
}
- }
+ (void) zone_mount_rootfs(&mounts, zonepath);
+ }
} else {
/* The move was successful, cleanup the old zonepath. */
if (!is_zfs && !fast) {
@@ -4206,7 +4250,16 @@ done:
}
}
+ zone_mounts_destroy(&mounts);
return ((err == Z_OK) ? Z_OK : Z_ERR);
+
+err_and_rele_lockfile:
+ zonecfg_release_lock_file(target_zone, lockfd);
+err_and_fini_handle:
+ zonecfg_fini_handle(handle);
+err_and_mounts_destroy:
+ zone_mounts_destroy(&mounts);
+ return (Z_ERR);
}
/* ARGSUSED */
diff --git a/usr/src/cmd/zoneadm/zoneadm.h b/usr/src/cmd/zoneadm/zoneadm.h
index c3506bcfc7..29c0b445ba 100644
--- a/usr/src/cmd/zoneadm/zoneadm.h
+++ b/usr/src/cmd/zoneadm/zoneadm.h
@@ -27,6 +27,8 @@
#ifndef _ZONEADM_H
#define _ZONEADM_H
+#include <sys/types.h>
+
#define CMD_HELP 0
#define CMD_BOOT 1
#define CMD_HALT 2
@@ -62,10 +64,46 @@
#define SW_CMP_SILENT 0x02
/*
+ * This structure stores information about mounts of interest within an
+ * installed zone.
+ */
+typedef struct zone_mounts {
+ /* The zone's zonepath */
+ char *zonepath;
+
+ /* The length of zonepath */
+ int zonepath_len;
+
+ /*
+ * This indicates the number of unexpected mounts that were encountered
+ * in the zone.
+ */
+ int num_unexpected_mounts;
+
+ /*
+ * This is the number of overlay mounts detected on the zone's root
+ * directory.
+ */
+ int num_root_overlay_mounts;
+
+ /*
+ * This is used to track important zone root mount information. The
+ * mnt_time field isn't used. If root_mnttab is NULL, then the
+ * associated zone doesn't have a mounted root filesystem.
+ *
+ * NOTE: mnt_mountp is non-NULL iff the zone's root filesystem is a
+ * ZFS filesystem with a non-legacy mountpoint. In this case, it
+ * refers to a string containing the dataset's mountpoint.
+ */
+ struct mnttab *root_mnttab;
+} zone_mounts_t;
+
+/*
* zoneadm.c
*/
extern char *target_zone;
+extern int zfm_print(const struct mnttab *mntp, void *unused);
extern int clone_copy(char *source_zonepath, char *zonepath);
extern char *cmd_to_str(int cmd_num);
extern int do_subproc(char *cmdbuf);
@@ -88,6 +126,11 @@ extern boolean_t is_zonepath_zfs(char *zonepath);
extern int move_zfs(char *zonepath, char *new_zonepath);
extern int verify_datasets(zone_dochandle_t handle);
extern int verify_fs_zfs(struct zone_fstab *fstab);
+extern int zone_mounts_init(zone_mounts_t *mounts, const char *zonepath);
+extern void zone_mounts_destroy(zone_mounts_t *mounts);
+extern int zone_mount_rootfs(zone_mounts_t *mounts, const char *zonepath);
+extern int zone_unmount_rootfs(zone_mounts_t *mounts, const char *zonepath,
+ boolean_t force);
extern int init_zfs(void);
#endif /* _ZONEADM_H */
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c
index 4911839ed6..a9722c1bd6 100644
--- a/usr/src/cmd/zoneadmd/vplat.c
+++ b/usr/src/cmd/zoneadmd/vplat.c
@@ -3772,8 +3772,8 @@ remove_mlps(zlog_t *zlogp, zoneid_t zoneid)
}
int
-prtmount(const char *fs, void *x) {
- zerror((zlog_t *)x, B_FALSE, " %s", fs);
+prtmount(const struct mnttab *fs, void *x) {
+ zerror((zlog_t *)x, B_FALSE, " %s", fs->mnt_mountp);
return (0);
}
diff --git a/usr/src/head/libzonecfg.h b/usr/src/head/libzonecfg.h
index ee2b67f83c..870a8350a4 100644
--- a/usr/src/head/libzonecfg.h
+++ b/usr/src/head/libzonecfg.h
@@ -49,6 +49,7 @@ extern "C" {
#include <libbrand.h>
#include <sys/uuid.h>
#include <libuutil.h>
+#include <sys/mnttab.h>
#define ZONE_ID_UNDEFINED -1
@@ -328,8 +329,8 @@ extern int zonecfg_lookup_ipd(zone_dochandle_t, struct zone_fstab *);
extern int zonecfg_add_fs_option(struct zone_fstab *, char *);
extern int zonecfg_remove_fs_option(struct zone_fstab *, char *);
extern void zonecfg_free_fs_option_list(zone_fsopt_t *);
-extern int zonecfg_find_mounts(char *, int(*)(const char *, void *),
- void *);
+extern int zonecfg_find_mounts(char *, int(*)(const struct mnttab *,
+ void *), void *);
/*
* Network interface configuration.
diff --git a/usr/src/lib/brand/native/zone/sw_support.c b/usr/src/lib/brand/native/zone/sw_support.c
index 7c1b083109..5747912f6a 100644
--- a/usr/src/lib/brand/native/zone/sw_support.c
+++ b/usr/src/lib/brand/native/zone/sw_support.c
@@ -1582,8 +1582,8 @@ get_detach_info(zone_dochandle_t handle, boolean_t detaching)
/* ARGSUSED */
static int
-zfm_print(const char *p, void *r) {
- (void) fprintf(stderr, " %s\n", p);
+zfm_print(const struct mnttab *p, void *r) {
+ (void) fprintf(stderr, " %s\n", p->mnt_mountp);
return (0);
}
diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c
index 9c26ef565e..d356b73701 100644
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c
@@ -2760,14 +2760,14 @@ zonecfg_devperms_apply(zone_dochandle_t hdl, const char *inpath, uid_t owner,
* This function finds everything mounted under a zone's rootpath.
* This returns the number of mounts under rootpath, or -1 on error.
* callback is called once per mount found with the first argument
- * pointing to the mount point.
+ * pointing to a mnttab structure containing the mount's information.
*
* If the callback function returns non-zero zonecfg_find_mounts
* aborts with an error.
*/
int
-zonecfg_find_mounts(char *rootpath, int (*callback)(const char *, void *),
- void *priv) {
+zonecfg_find_mounts(char *rootpath, int (*callback)(const struct mnttab *,
+ void *), void *priv) {
FILE *mnttab;
struct mnttab m;
size_t l;
@@ -2800,7 +2800,7 @@ zonecfg_find_mounts(char *rootpath, int (*callback)(const char *, void *),
rv++;
if (callback == NULL)
continue;
- if (callback(m.mnt_mountp, priv)) {
+ if (callback(&m, priv)) {
rv = -1;
goto out;