Print this page
patch zone-auto-create-be


   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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2014 by Delphix. All rights reserved.

  26  */
  27 
  28 /*
  29  * System includes
  30  */
  31 
  32 #include <assert.h>
  33 #include <ctype.h>
  34 #include <errno.h>
  35 #include <libgen.h>
  36 #include <libintl.h>
  37 #include <libnvpair.h>
  38 #include <libzfs.h>
  39 #include <stdio.h>
  40 #include <stdlib.h>
  41 #include <string.h>
  42 #include <sys/mnttab.h>
  43 #include <sys/mount.h>
  44 #include <sys/stat.h>
  45 #include <sys/types.h>


1601  * Return:
1602  *              BE_SUCCESS - Success
1603  *              be_errno_t - Failure
1604  * Scope:
1605  *              Private
1606  *
1607  * NOTES - Requires that the BE being deleted has no dependent BEs.  If it
1608  *         does, the destroy will fail.
1609  */
1610 static int
1611 be_destroy_zones(char *be_name, char *be_root_ds, be_destroy_data_t *dd)
1612 {
1613         int             i;
1614         int             ret = BE_SUCCESS;
1615         int             force_umnt = BE_UNMOUNT_FLAG_NULL;
1616         char            *zonepath = NULL;
1617         char            *zonename = NULL;
1618         char            *zonepath_ds = NULL;
1619         char            *mp = NULL;
1620         zoneList_t      zlist = NULL;
1621         zoneBrandList_t *brands = NULL;
1622         zfs_handle_t    *zhp = NULL;
1623 
1624         /* If zones are not implemented, then get out. */
1625         if (!z_zones_are_implemented()) {
1626                 return (BE_SUCCESS);
1627         }
1628 
1629         /* Get list of supported brands */
1630         if ((brands = be_get_supported_brandlist()) == NULL) {
1631                 be_print_err(gettext("be_destroy_zones: "
1632                     "no supported brands\n"));
1633                 return (BE_SUCCESS);
1634         }
1635 
1636         /* Get handle to BE's root dataset */
1637         if ((zhp = zfs_open(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) ==
1638             NULL) {
1639                 be_print_err(gettext("be_destroy_zones: failed to "
1640                     "open BE root dataset (%s): %s\n"), be_root_ds,
1641                     libzfs_error_description(g_zfs));
1642                 z_free_brand_list(brands);
1643                 return (zfs_err_to_be_err(g_zfs));
1644         }
1645 
1646         /*
1647          * If the global BE is not mounted, we must mount it here to
1648          * gather data about the non-global zones in it.
1649          */
1650         if (!zfs_is_mounted(zhp, &mp)) {
1651                 if ((ret = _be_mount(be_name, &mp,
1652                     BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
1653                         be_print_err(gettext("be_destroy_zones: failed to "
1654                             "mount the BE (%s) for zones processing.\n"),
1655                             be_name);
1656                         ZFS_CLOSE(zhp);
1657                         z_free_brand_list(brands);
1658                         return (ret);
1659                 }
1660         }
1661         ZFS_CLOSE(zhp);
1662 
1663         z_set_zone_root(mp);
1664         free(mp);
1665 
1666         /* Get list of supported zones. */
1667         if ((zlist = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) {
1668                 z_free_brand_list(brands);
1669                 return (BE_SUCCESS);
1670         }
1671 
1672         /* Unmount the BE before destroying the zones in it. */
1673         if (dd->force_unmount)
1674                 force_umnt = BE_UNMOUNT_FLAG_FORCE;
1675         if ((ret = _be_unmount(be_name, force_umnt)) != BE_SUCCESS) {
1676                 be_print_err(gettext("be_destroy_zones: failed to "
1677                     "unmount the BE (%s)\n"), be_name);
1678                 goto done;
1679         }
1680 
1681         /* Iterate through the zones and destroy them. */
1682         for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) {











1683 
1684                 /* Skip zones that aren't at least installed */
1685                 if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED)
1686                         continue;
1687 
1688                 zonepath = z_zlist_get_zonepath(zlist, i);
1689 
1690                 /*
1691                  * Get the dataset of this zonepath.  If its not
1692                  * a dataset, skip it.
1693                  */
1694                 if ((zonepath_ds = be_get_ds_from_dir(zonepath)) == NULL)
1695                         continue;
1696 
1697                 /*
1698                  * Check if this zone is supported based on the
1699                  * dataset of its zonepath.
1700                  */
1701                 if (!be_zone_supported(zonepath_ds)) {
1702                         free(zonepath_ds);
1703                         continue;
1704                 }
1705 
1706                 /* Find the zone BE root datasets for this zone. */
1707                 if ((ret = be_destroy_zone_roots(zonepath_ds, dd))
1708                     != BE_SUCCESS) {
1709                         be_print_err(gettext("be_destroy_zones: failed to "
1710                             "find and destroy zone roots for zone %s\n"),
1711                             zonename);
1712                         free(zonepath_ds);
1713                         goto done;
1714                 }
1715                 free(zonepath_ds);
1716         }
1717 
1718 done:
1719         z_free_brand_list(brands);
1720         z_free_zone_list(zlist);
1721 
1722         return (ret);
1723 }
1724 
1725 /*
1726  * Function:    be_destroy_zone_roots
1727  * Description: This function will open the zone's root container dataset
1728  *              and iterate the datasets within, looking for roots that
1729  *              belong to the given global BE and destroying them.
1730  *              If no other zone roots remain in the zone's root container
1731  *              dataset, the function will destroy it and the zone's
1732  *              zonepath dataset as well.
1733  * Parameters:
1734  *              zonepath_ds - pointer to zone's zonepath dataset.
1735  *              dd - pointer to a linked destroy data.
1736  * Returns:
1737  *              BE_SUCCESS - Success
1738  *              be_errno_t - Failure
1739  * Scope:


1891         int             i, num_retries;
1892         int             ret = BE_SUCCESS;
1893         int             iret = 0;
1894         char            *zonename = NULL;
1895         char            *zonepath = NULL;
1896         char            *zone_be_name = NULL;
1897         char            *temp_mntpt = NULL;
1898         char            *new_zone_be_name = NULL;
1899         char            zoneroot[MAXPATHLEN];
1900         char            zoneroot_ds[MAXPATHLEN];
1901         char            zone_container_ds[MAXPATHLEN];
1902         char            new_zoneroot_ds[MAXPATHLEN];
1903         char            ss[MAXPATHLEN];
1904         uuid_t          uu = { 0 };
1905         char            uu_string[UUID_PRINTABLE_STRING_LENGTH] = { 0 };
1906         be_transaction_data_t bt = { 0 };
1907         zfs_handle_t    *obe_zhp = NULL;
1908         zfs_handle_t    *nbe_zhp = NULL;
1909         zfs_handle_t    *z_zhp = NULL;
1910         zoneList_t      zlist = NULL;
1911         zoneBrandList_t *brands = NULL;
1912         boolean_t       mounted_here = B_FALSE;
1913         char            *snap_name = NULL;
1914 
1915         /* If zones are not implemented, then get out. */
1916         if (!z_zones_are_implemented()) {
1917                 return (BE_SUCCESS);
1918         }
1919 
1920         /* Get list of supported brands */
1921         if ((brands = be_get_supported_brandlist()) == NULL) {
1922                 be_print_err(gettext("be_copy_zones: "
1923                     "no supported brands\n"));
1924                 return (BE_SUCCESS);
1925         }
1926 
1927         /* Get handle to origin BE's root dataset */
1928         if ((obe_zhp = zfs_open(g_zfs, obe_root_ds, ZFS_TYPE_FILESYSTEM))
1929             == NULL) {
1930                 be_print_err(gettext("be_copy_zones: failed to open "
1931                     "the origin BE root dataset (%s) for zones processing: "
1932                     "%s\n"), obe_root_ds, libzfs_error_description(g_zfs));
1933                 return (zfs_err_to_be_err(g_zfs));
1934         }
1935 
1936         /* Get handle to newly cloned BE's root dataset */
1937         if ((nbe_zhp = zfs_open(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM))
1938             == NULL) {
1939                 be_print_err(gettext("be_copy_zones: failed to open "
1940                     "the new BE root dataset (%s): %s\n"), nbe_root_ds,
1941                     libzfs_error_description(g_zfs));
1942                 ZFS_CLOSE(obe_zhp);
1943                 return (zfs_err_to_be_err(g_zfs));
1944         }
1945 
1946         /* Get the uuid of the newly cloned parent BE. */


1954         ZFS_CLOSE(nbe_zhp);
1955         uuid_unparse(uu, uu_string);
1956 
1957         /*
1958          * If the origin BE is not mounted, we must mount it here to
1959          * gather data about the non-global zones in it.
1960          */
1961         if (!zfs_is_mounted(obe_zhp, &temp_mntpt)) {
1962                 if ((ret = _be_mount(obe_name, &temp_mntpt,
1963                     BE_MOUNT_FLAG_NULL)) != BE_SUCCESS) {
1964                         be_print_err(gettext("be_copy_zones: failed to "
1965                             "mount the BE (%s) for zones procesing.\n"),
1966                             obe_name);
1967                         goto done;
1968                 }
1969                 mounted_here = B_TRUE;
1970         }
1971 
1972         z_set_zone_root(temp_mntpt);
1973 
1974         /* Get list of supported zones. */
1975         if ((zlist = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) {
1976                 ret = BE_SUCCESS;
1977                 goto done;
1978         }
1979 
1980         for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) {
1981 
1982                 be_fs_list_data_t       fld = { 0 };
1983                 char                    zonepath_ds[MAXPATHLEN];
1984                 char                    *ds = NULL;










1985 
1986                 /* Get zonepath of zone */
1987                 zonepath = z_zlist_get_zonepath(zlist, i);
1988 
1989                 /* Skip zones that aren't at least installed */
1990                 if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED)
1991                         continue;
1992 
1993                 /*
1994                  * Get the dataset of this zonepath.  If its not
1995                  * a dataset, skip it.
1996                  */
1997                 if ((ds = be_get_ds_from_dir(zonepath)) == NULL)
1998                         continue;
1999 
2000                 (void) strlcpy(zonepath_ds, ds, sizeof (zonepath_ds));
2001                 free(ds);
2002                 ds = NULL;
2003 
2004                 /* Get zoneroot directory */


2232 
2233                 /*
2234                  * Update new zone BE's vfstab.
2235                  */
2236                 if ((ret = be_update_zone_vfstab(z_zhp, bt.nbe_name,
2237                     zonepath_ds, zonepath_ds, &fld)) != BE_SUCCESS) {
2238                         be_print_err(gettext("be_copy_zones: "
2239                             "failed to update new BE's vfstab (%s)\n"),
2240                             bt.nbe_name);
2241                         ZFS_CLOSE(z_zhp);
2242                         be_free_fs_list(&fld);
2243                         goto done;
2244                 }
2245 
2246                 be_free_fs_list(&fld);
2247                 ZFS_CLOSE(z_zhp);
2248         }
2249 
2250 done:
2251         free(snap_name);
2252         if (brands != NULL)
2253                 z_free_brand_list(brands);
2254         if (zlist != NULL)
2255                 z_free_zone_list(zlist);
2256 
2257         if (mounted_here)
2258                 (void) _be_unmount(obe_name, 0);
2259 
2260         ZFS_CLOSE(obe_zhp);
2261         return (ret);
2262 }
2263 
2264 /*
2265  * Function:    be_clone_fs_callback
2266  * Description: Callback function used to iterate through a BE's filesystems
2267  *              to clone them for the new BE.
2268  * Parameters:
2269  *              zhp - zfs_handle_t pointer for the filesystem being processed.
2270  *              data - be_transaction_data_t pointer providing information
2271  *                      about original BE and new BE.
2272  * Return:
2273  *              0 - Success




   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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2014 by Delphix. All rights reserved.
  26  * Copyright 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  27  */
  28 
  29 /*
  30  * System includes
  31  */
  32 
  33 #include <assert.h>
  34 #include <ctype.h>
  35 #include <errno.h>
  36 #include <libgen.h>
  37 #include <libintl.h>
  38 #include <libnvpair.h>
  39 #include <libzfs.h>
  40 #include <stdio.h>
  41 #include <stdlib.h>
  42 #include <string.h>
  43 #include <sys/mnttab.h>
  44 #include <sys/mount.h>
  45 #include <sys/stat.h>
  46 #include <sys/types.h>


1602  * Return:
1603  *              BE_SUCCESS - Success
1604  *              be_errno_t - Failure
1605  * Scope:
1606  *              Private
1607  *
1608  * NOTES - Requires that the BE being deleted has no dependent BEs.  If it
1609  *         does, the destroy will fail.
1610  */
1611 static int
1612 be_destroy_zones(char *be_name, char *be_root_ds, be_destroy_data_t *dd)
1613 {
1614         int             i;
1615         int             ret = BE_SUCCESS;
1616         int             force_umnt = BE_UNMOUNT_FLAG_NULL;
1617         char            *zonepath = NULL;
1618         char            *zonename = NULL;
1619         char            *zonepath_ds = NULL;
1620         char            *mp = NULL;
1621         zoneList_t      zlist = NULL;

1622         zfs_handle_t    *zhp = NULL;
1623 
1624         /* If zones are not implemented, then get out. */
1625         if (!z_zones_are_implemented()) {
1626                 return (BE_SUCCESS);
1627         }
1628 







1629         /* Get handle to BE's root dataset */
1630         if ((zhp = zfs_open(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) ==
1631             NULL) {
1632                 be_print_err(gettext("be_destroy_zones: failed to "
1633                     "open BE root dataset (%s): %s\n"), be_root_ds,
1634                     libzfs_error_description(g_zfs));

1635                 return (zfs_err_to_be_err(g_zfs));
1636         }
1637 
1638         /*
1639          * If the global BE is not mounted, we must mount it here to
1640          * gather data about the non-global zones in it.
1641          */
1642         if (!zfs_is_mounted(zhp, &mp)) {
1643                 if ((ret = _be_mount(be_name, &mp,
1644                     BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
1645                         be_print_err(gettext("be_destroy_zones: failed to "
1646                             "mount the BE (%s) for zones processing.\n"),
1647                             be_name);
1648                         ZFS_CLOSE(zhp);

1649                         return (ret);
1650                 }
1651         }
1652         ZFS_CLOSE(zhp);
1653 
1654         z_set_zone_root(mp);
1655         free(mp);
1656 
1657         /* Get list of zones. */
1658         if ((zlist = z_get_nonglobal_branded_zone_list()) == NULL)

1659                 return (BE_SUCCESS);

1660 
1661         /* Unmount the BE before destroying the zones in it. */
1662         if (dd->force_unmount)
1663                 force_umnt = BE_UNMOUNT_FLAG_FORCE;
1664         if ((ret = _be_unmount(be_name, force_umnt)) != BE_SUCCESS) {
1665                 be_print_err(gettext("be_destroy_zones: failed to "
1666                     "unmount the BE (%s)\n"), be_name);
1667                 goto done;
1668         }
1669 
1670         /* Iterate through the zones and destroy them. */
1671         for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) {
1672                 boolean_t auto_create;
1673 
1674                 if (z_zlist_is_zone_auto_create_be(zlist, i, &auto_create) != 0) {
1675                         be_print_err(gettext("be_destroy_zones: failed to get "
1676                             "auto-create-be brand property\n"));
1677                         ret = -1; // XXX
1678                         goto done;
1679                 }
1680 
1681                 if (!auto_create)
1682                         continue;
1683 
1684                 /* Skip zones that aren't at least installed */
1685                 if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED)
1686                         continue;
1687 
1688                 zonepath = z_zlist_get_zonepath(zlist, i);
1689 
1690                 /*
1691                  * Get the dataset of this zonepath.  If its not
1692                  * a dataset, skip it.
1693                  */
1694                 if ((zonepath_ds = be_get_ds_from_dir(zonepath)) == NULL)
1695                         continue;
1696 
1697                 /*
1698                  * Check if this zone is supported based on the
1699                  * dataset of its zonepath.
1700                  */
1701                 if (!be_zone_supported(zonepath_ds)) {
1702                         free(zonepath_ds);
1703                         continue;
1704                 }
1705 
1706                 /* Find the zone BE root datasets for this zone. */
1707                 if ((ret = be_destroy_zone_roots(zonepath_ds, dd))
1708                     != BE_SUCCESS) {
1709                         be_print_err(gettext("be_destroy_zones: failed to "
1710                             "find and destroy zone roots for zone %s\n"),
1711                             zonename);
1712                         free(zonepath_ds);
1713                         goto done;
1714                 }
1715                 free(zonepath_ds);
1716         }
1717 
1718 done:

1719         z_free_zone_list(zlist);
1720 
1721         return (ret);
1722 }
1723 
1724 /*
1725  * Function:    be_destroy_zone_roots
1726  * Description: This function will open the zone's root container dataset
1727  *              and iterate the datasets within, looking for roots that
1728  *              belong to the given global BE and destroying them.
1729  *              If no other zone roots remain in the zone's root container
1730  *              dataset, the function will destroy it and the zone's
1731  *              zonepath dataset as well.
1732  * Parameters:
1733  *              zonepath_ds - pointer to zone's zonepath dataset.
1734  *              dd - pointer to a linked destroy data.
1735  * Returns:
1736  *              BE_SUCCESS - Success
1737  *              be_errno_t - Failure
1738  * Scope:


1890         int             i, num_retries;
1891         int             ret = BE_SUCCESS;
1892         int             iret = 0;
1893         char            *zonename = NULL;
1894         char            *zonepath = NULL;
1895         char            *zone_be_name = NULL;
1896         char            *temp_mntpt = NULL;
1897         char            *new_zone_be_name = NULL;
1898         char            zoneroot[MAXPATHLEN];
1899         char            zoneroot_ds[MAXPATHLEN];
1900         char            zone_container_ds[MAXPATHLEN];
1901         char            new_zoneroot_ds[MAXPATHLEN];
1902         char            ss[MAXPATHLEN];
1903         uuid_t          uu = { 0 };
1904         char            uu_string[UUID_PRINTABLE_STRING_LENGTH] = { 0 };
1905         be_transaction_data_t bt = { 0 };
1906         zfs_handle_t    *obe_zhp = NULL;
1907         zfs_handle_t    *nbe_zhp = NULL;
1908         zfs_handle_t    *z_zhp = NULL;
1909         zoneList_t      zlist = NULL;

1910         boolean_t       mounted_here = B_FALSE;
1911         char            *snap_name = NULL;
1912 
1913         /* If zones are not implemented, then get out. */
1914         if (!z_zones_are_implemented()) {
1915                 return (BE_SUCCESS);
1916         }
1917 







1918         /* Get handle to origin BE's root dataset */
1919         if ((obe_zhp = zfs_open(g_zfs, obe_root_ds, ZFS_TYPE_FILESYSTEM))
1920             == NULL) {
1921                 be_print_err(gettext("be_copy_zones: failed to open "
1922                     "the origin BE root dataset (%s) for zones processing: "
1923                     "%s\n"), obe_root_ds, libzfs_error_description(g_zfs));
1924                 return (zfs_err_to_be_err(g_zfs));
1925         }
1926 
1927         /* Get handle to newly cloned BE's root dataset */
1928         if ((nbe_zhp = zfs_open(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM))
1929             == NULL) {
1930                 be_print_err(gettext("be_copy_zones: failed to open "
1931                     "the new BE root dataset (%s): %s\n"), nbe_root_ds,
1932                     libzfs_error_description(g_zfs));
1933                 ZFS_CLOSE(obe_zhp);
1934                 return (zfs_err_to_be_err(g_zfs));
1935         }
1936 
1937         /* Get the uuid of the newly cloned parent BE. */


1945         ZFS_CLOSE(nbe_zhp);
1946         uuid_unparse(uu, uu_string);
1947 
1948         /*
1949          * If the origin BE is not mounted, we must mount it here to
1950          * gather data about the non-global zones in it.
1951          */
1952         if (!zfs_is_mounted(obe_zhp, &temp_mntpt)) {
1953                 if ((ret = _be_mount(obe_name, &temp_mntpt,
1954                     BE_MOUNT_FLAG_NULL)) != BE_SUCCESS) {
1955                         be_print_err(gettext("be_copy_zones: failed to "
1956                             "mount the BE (%s) for zones procesing.\n"),
1957                             obe_name);
1958                         goto done;
1959                 }
1960                 mounted_here = B_TRUE;
1961         }
1962 
1963         z_set_zone_root(temp_mntpt);
1964 
1965         /* Get list of zones. */
1966         if ((zlist = z_get_nonglobal_branded_zone_list()) == NULL) {
1967                 ret = BE_SUCCESS;
1968                 goto done;
1969         }
1970 
1971         for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) {
1972 
1973                 be_fs_list_data_t       fld = { 0 };
1974                 char                    zonepath_ds[MAXPATHLEN];
1975                 char                    *ds = NULL;
1976                 boolean_t               auto_create;
1977 
1978                 if (z_zlist_is_zone_auto_create_be(zlist, i, &auto_create) != 0) {
1979                         be_print_err(gettext("be_copy_zones: failed to get "
1980                             "auto-create-be brand property\n"));
1981                         ret = -1; // XXX
1982                 }
1983 
1984                 if (!auto_create)
1985                         continue;
1986 
1987                 /* Get zonepath of zone */
1988                 zonepath = z_zlist_get_zonepath(zlist, i);
1989 
1990                 /* Skip zones that aren't at least installed */
1991                 if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED)
1992                         continue;
1993 
1994                 /*
1995                  * Get the dataset of this zonepath.  If its not
1996                  * a dataset, skip it.
1997                  */
1998                 if ((ds = be_get_ds_from_dir(zonepath)) == NULL)
1999                         continue;
2000 
2001                 (void) strlcpy(zonepath_ds, ds, sizeof (zonepath_ds));
2002                 free(ds);
2003                 ds = NULL;
2004 
2005                 /* Get zoneroot directory */


2233 
2234                 /*
2235                  * Update new zone BE's vfstab.
2236                  */
2237                 if ((ret = be_update_zone_vfstab(z_zhp, bt.nbe_name,
2238                     zonepath_ds, zonepath_ds, &fld)) != BE_SUCCESS) {
2239                         be_print_err(gettext("be_copy_zones: "
2240                             "failed to update new BE's vfstab (%s)\n"),
2241                             bt.nbe_name);
2242                         ZFS_CLOSE(z_zhp);
2243                         be_free_fs_list(&fld);
2244                         goto done;
2245                 }
2246 
2247                 be_free_fs_list(&fld);
2248                 ZFS_CLOSE(z_zhp);
2249         }
2250 
2251 done:
2252         free(snap_name);


2253         if (zlist != NULL)
2254                 z_free_zone_list(zlist);
2255 
2256         if (mounted_here)
2257                 (void) _be_unmount(obe_name, 0);
2258 
2259         ZFS_CLOSE(obe_zhp);
2260         return (ret);
2261 }
2262 
2263 /*
2264  * Function:    be_clone_fs_callback
2265  * Description: Callback function used to iterate through a BE's filesystems
2266  *              to clone them for the new BE.
2267  * Parameters:
2268  *              zhp - zfs_handle_t pointer for the filesystem being processed.
2269  *              data - be_transaction_data_t pointer providing information
2270  *                      about original BE and new BE.
2271  * Return:
2272  *              0 - Success