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
|