335 /* Create file system if it doesn't already exist */
336 if (zfs_dataset_exists(g_zfs, child_fs,
337 ZFS_TYPE_FILESYSTEM)) {
338 continue;
339 }
340 if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM,
341 props) != 0) {
342 be_print_err(gettext("be_init: failed to "
343 "create BE's shared dataset (%s): %s\n"),
344 child_fs, libzfs_error_description(g_zfs));
345 ret = zfs_err_to_be_err(g_zfs);
346 nvlist_free(props);
347 goto done;
348 }
349 }
350
351 nvlist_free(props);
352 }
353
354 done:
355 if (bt.nbe_zfs_props != NULL)
356 nvlist_free(bt.nbe_zfs_props);
357
358 be_zfs_fini();
359
360 return (ret);
361 }
362
363 /*
364 * Function: be_destroy
365 * Description: Destroy a BE and all of its children datasets, snapshots and
366 * zones that belong to the parent BE.
367 * Parameters:
368 * be_attrs - pointer to nvlist_t of attributes being passed in.
369 * The following attributes are used by this function:
370 *
371 * BE_ATTR_ORIG_BE_NAME *required
372 * BE_ATTR_DESTROY_FLAGS *optional
373 * Return:
374 * BE_SUCCESS - Success
375 * be_errno_t - Failure
1150 ret = zfs_err_to_be_err(g_zfs);
1151 goto done;
1152 }
1153
1154 /*
1155 * Return the auto generated name to the caller
1156 */
1157 if (bt.nbe_name) {
1158 if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_NAME,
1159 bt.nbe_name) != 0) {
1160 be_print_err(gettext("be_copy: failed to "
1161 "add snap name to be_attrs\n"));
1162 }
1163 }
1164 }
1165
1166 done:
1167 ZFS_CLOSE(zhp);
1168 be_free_fs_list(&fld);
1169
1170 if (bt.nbe_zfs_props != NULL)
1171 nvlist_free(bt.nbe_zfs_props);
1172
1173 free(bt.obe_altroot);
1174 free(new_mp);
1175
1176 /*
1177 * If a failure occurred and we already created the datasets for
1178 * the new boot environment, destroy them.
1179 */
1180 if (ret != BE_SUCCESS && be_created) {
1181 be_destroy_data_t cdd = { 0 };
1182
1183 cdd.force_unmount = B_TRUE;
1184
1185 be_print_err(gettext("be_copy: "
1186 "destroying partially created boot environment\n"));
1187
1188 if (getzoneid() == GLOBAL_ZONEID && be_get_uuid(bt.nbe_root_ds,
1189 &cdd.gz_be_uuid) == 0)
1190 (void) be_destroy_zones(bt.nbe_name, bt.nbe_root_ds,
2073 bt.nbe_root_ds = new_zoneroot_ds;
2074
2075 if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) {
2076 be_print_err(gettext("be_copy_zones: "
2077 "internal error: out of memory\n"));
2078 ret = BE_ERR_NOMEM;
2079 goto done;
2080 }
2081
2082 /*
2083 * The call to be_clone_fs_callback always closes the
2084 * zfs_handle so there's no need to close z_zhp.
2085 */
2086 if ((iret = be_clone_fs_callback(z_zhp, &bt)) != 0) {
2087 z_zhp = NULL;
2088 if (iret != BE_ERR_BE_EXISTS) {
2089 be_print_err(gettext("be_copy_zones: "
2090 "failed to create zone BE clone for new "
2091 "zone BE %s\n"), new_zone_be_name);
2092 ret = iret;
2093 if (bt.nbe_zfs_props != NULL)
2094 nvlist_free(bt.nbe_zfs_props);
2095 goto done;
2096 }
2097 /*
2098 * We failed to create the new zone BE because a zone
2099 * BE with the auto-name we generated above has since
2100 * come into existence. Regenerate a new auto-name
2101 * and retry.
2102 */
2103 for (num_retries = 1;
2104 num_retries < BE_AUTO_NAME_MAX_TRY;
2105 num_retries++) {
2106
2107 /* Sleep 1 before retrying */
2108 (void) sleep(1);
2109
2110 /* Generate new auto zone BE name */
2111 free(new_zone_be_name);
2112 if ((new_zone_be_name = be_auto_zone_be_name(
2113 zone_container_ds,
2114 zone_be_name)) == NULL) {
2115 be_print_err(gettext("be_copy_zones: "
2116 "failed to generate auto name "
2117 "for zone BE.\n"));
2118 ret = BE_ERR_AUTONAME;
2119 if (bt.nbe_zfs_props != NULL)
2120 nvlist_free(bt.nbe_zfs_props);
2121 goto done;
2122 }
2123
2124 (void) snprintf(new_zoneroot_ds,
2125 sizeof (new_zoneroot_ds),
2126 "%s/%s", zone_container_ds,
2127 new_zone_be_name);
2128 bt.nbe_name = new_zone_be_name;
2129 bt.nbe_root_ds = new_zoneroot_ds;
2130
2131 /*
2132 * Get handle to original zone BE's root
2133 * dataset.
2134 */
2135 if ((z_zhp = zfs_open(g_zfs, zoneroot_ds,
2136 ZFS_TYPE_FILESYSTEM)) == NULL) {
2137 be_print_err(gettext("be_copy_zones: "
2138 "failed to open zone root "
2139 "dataset (%s): %s\n"),
2140 zoneroot_ds,
2141 libzfs_error_description(g_zfs));
2142 ret = zfs_err_to_be_err(g_zfs);
2143 if (bt.nbe_zfs_props != NULL)
2144 nvlist_free(bt.nbe_zfs_props);
2145 goto done;
2146 }
2147
2148 /*
2149 * Try to clone the zone BE again. This
2150 * call will end up closing the zfs
2151 * handle passed in whether it
2152 * succeeds or fails.
2153 */
2154 iret = be_clone_fs_callback(z_zhp, &bt);
2155 z_zhp = NULL;
2156 if (iret == 0) {
2157 break;
2158 } else if (iret != BE_ERR_BE_EXISTS) {
2159 be_print_err(gettext("be_copy_zones: "
2160 "failed to create zone BE clone "
2161 "for new zone BE %s\n"),
2162 new_zone_be_name);
2163 ret = iret;
2164 if (bt.nbe_zfs_props != NULL)
2165 nvlist_free(bt.nbe_zfs_props);
2166 goto done;
2167 }
2168 }
2169 /*
2170 * If we've exhausted the maximum number of
2171 * tries, free the auto zone BE name and return
2172 * error.
2173 */
2174 if (num_retries == BE_AUTO_NAME_MAX_TRY) {
2175 be_print_err(gettext("be_copy_zones: failed "
2176 "to create a unique auto zone BE name\n"));
2177 free(bt.nbe_name);
2178 bt.nbe_name = NULL;
2179 ret = BE_ERR_AUTONAME;
2180 if (bt.nbe_zfs_props != NULL)
2181 nvlist_free(bt.nbe_zfs_props);
2182 goto done;
2183 }
2184 }
2185
2186 if (bt.nbe_zfs_props != NULL)
2187 nvlist_free(bt.nbe_zfs_props);
2188
2189 z_zhp = NULL;
2190
2191 if ((z_zhp = zfs_open(g_zfs, new_zoneroot_ds,
2192 ZFS_TYPE_FILESYSTEM)) == NULL) {
2193 be_print_err(gettext("be_copy_zones: "
2194 "failed to open the new zone BE root dataset "
2195 "(%s): %s\n"), new_zoneroot_ds,
2196 libzfs_error_description(g_zfs));
2197 ret = zfs_err_to_be_err(g_zfs);
2198 goto done;
2199 }
2200
2201 if (zfs_prop_set(z_zhp, BE_ZONE_PARENTBE_PROPERTY,
2202 uu_string) != 0) {
2203 be_print_err(gettext("be_copy_zones: "
2204 "failed to set parentbe property\n"));
2205 ZFS_CLOSE(z_zhp);
2206 ret = zfs_err_to_be_err(g_zfs);
|
335 /* Create file system if it doesn't already exist */
336 if (zfs_dataset_exists(g_zfs, child_fs,
337 ZFS_TYPE_FILESYSTEM)) {
338 continue;
339 }
340 if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM,
341 props) != 0) {
342 be_print_err(gettext("be_init: failed to "
343 "create BE's shared dataset (%s): %s\n"),
344 child_fs, libzfs_error_description(g_zfs));
345 ret = zfs_err_to_be_err(g_zfs);
346 nvlist_free(props);
347 goto done;
348 }
349 }
350
351 nvlist_free(props);
352 }
353
354 done:
355 nvlist_free(bt.nbe_zfs_props);
356
357 be_zfs_fini();
358
359 return (ret);
360 }
361
362 /*
363 * Function: be_destroy
364 * Description: Destroy a BE and all of its children datasets, snapshots and
365 * zones that belong to the parent BE.
366 * Parameters:
367 * be_attrs - pointer to nvlist_t of attributes being passed in.
368 * The following attributes are used by this function:
369 *
370 * BE_ATTR_ORIG_BE_NAME *required
371 * BE_ATTR_DESTROY_FLAGS *optional
372 * Return:
373 * BE_SUCCESS - Success
374 * be_errno_t - Failure
1149 ret = zfs_err_to_be_err(g_zfs);
1150 goto done;
1151 }
1152
1153 /*
1154 * Return the auto generated name to the caller
1155 */
1156 if (bt.nbe_name) {
1157 if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_NAME,
1158 bt.nbe_name) != 0) {
1159 be_print_err(gettext("be_copy: failed to "
1160 "add snap name to be_attrs\n"));
1161 }
1162 }
1163 }
1164
1165 done:
1166 ZFS_CLOSE(zhp);
1167 be_free_fs_list(&fld);
1168
1169 nvlist_free(bt.nbe_zfs_props);
1170
1171 free(bt.obe_altroot);
1172 free(new_mp);
1173
1174 /*
1175 * If a failure occurred and we already created the datasets for
1176 * the new boot environment, destroy them.
1177 */
1178 if (ret != BE_SUCCESS && be_created) {
1179 be_destroy_data_t cdd = { 0 };
1180
1181 cdd.force_unmount = B_TRUE;
1182
1183 be_print_err(gettext("be_copy: "
1184 "destroying partially created boot environment\n"));
1185
1186 if (getzoneid() == GLOBAL_ZONEID && be_get_uuid(bt.nbe_root_ds,
1187 &cdd.gz_be_uuid) == 0)
1188 (void) be_destroy_zones(bt.nbe_name, bt.nbe_root_ds,
2071 bt.nbe_root_ds = new_zoneroot_ds;
2072
2073 if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) {
2074 be_print_err(gettext("be_copy_zones: "
2075 "internal error: out of memory\n"));
2076 ret = BE_ERR_NOMEM;
2077 goto done;
2078 }
2079
2080 /*
2081 * The call to be_clone_fs_callback always closes the
2082 * zfs_handle so there's no need to close z_zhp.
2083 */
2084 if ((iret = be_clone_fs_callback(z_zhp, &bt)) != 0) {
2085 z_zhp = NULL;
2086 if (iret != BE_ERR_BE_EXISTS) {
2087 be_print_err(gettext("be_copy_zones: "
2088 "failed to create zone BE clone for new "
2089 "zone BE %s\n"), new_zone_be_name);
2090 ret = iret;
2091 nvlist_free(bt.nbe_zfs_props);
2092 goto done;
2093 }
2094 /*
2095 * We failed to create the new zone BE because a zone
2096 * BE with the auto-name we generated above has since
2097 * come into existence. Regenerate a new auto-name
2098 * and retry.
2099 */
2100 for (num_retries = 1;
2101 num_retries < BE_AUTO_NAME_MAX_TRY;
2102 num_retries++) {
2103
2104 /* Sleep 1 before retrying */
2105 (void) sleep(1);
2106
2107 /* Generate new auto zone BE name */
2108 free(new_zone_be_name);
2109 if ((new_zone_be_name = be_auto_zone_be_name(
2110 zone_container_ds,
2111 zone_be_name)) == NULL) {
2112 be_print_err(gettext("be_copy_zones: "
2113 "failed to generate auto name "
2114 "for zone BE.\n"));
2115 ret = BE_ERR_AUTONAME;
2116 nvlist_free(bt.nbe_zfs_props);
2117 goto done;
2118 }
2119
2120 (void) snprintf(new_zoneroot_ds,
2121 sizeof (new_zoneroot_ds),
2122 "%s/%s", zone_container_ds,
2123 new_zone_be_name);
2124 bt.nbe_name = new_zone_be_name;
2125 bt.nbe_root_ds = new_zoneroot_ds;
2126
2127 /*
2128 * Get handle to original zone BE's root
2129 * dataset.
2130 */
2131 if ((z_zhp = zfs_open(g_zfs, zoneroot_ds,
2132 ZFS_TYPE_FILESYSTEM)) == NULL) {
2133 be_print_err(gettext("be_copy_zones: "
2134 "failed to open zone root "
2135 "dataset (%s): %s\n"),
2136 zoneroot_ds,
2137 libzfs_error_description(g_zfs));
2138 ret = zfs_err_to_be_err(g_zfs);
2139 nvlist_free(bt.nbe_zfs_props);
2140 goto done;
2141 }
2142
2143 /*
2144 * Try to clone the zone BE again. This
2145 * call will end up closing the zfs
2146 * handle passed in whether it
2147 * succeeds or fails.
2148 */
2149 iret = be_clone_fs_callback(z_zhp, &bt);
2150 z_zhp = NULL;
2151 if (iret == 0) {
2152 break;
2153 } else if (iret != BE_ERR_BE_EXISTS) {
2154 be_print_err(gettext("be_copy_zones: "
2155 "failed to create zone BE clone "
2156 "for new zone BE %s\n"),
2157 new_zone_be_name);
2158 ret = iret;
2159 nvlist_free(bt.nbe_zfs_props);
2160 goto done;
2161 }
2162 }
2163 /*
2164 * If we've exhausted the maximum number of
2165 * tries, free the auto zone BE name and return
2166 * error.
2167 */
2168 if (num_retries == BE_AUTO_NAME_MAX_TRY) {
2169 be_print_err(gettext("be_copy_zones: failed "
2170 "to create a unique auto zone BE name\n"));
2171 free(bt.nbe_name);
2172 bt.nbe_name = NULL;
2173 ret = BE_ERR_AUTONAME;
2174 nvlist_free(bt.nbe_zfs_props);
2175 goto done;
2176 }
2177 }
2178
2179 nvlist_free(bt.nbe_zfs_props);
2180
2181 z_zhp = NULL;
2182
2183 if ((z_zhp = zfs_open(g_zfs, new_zoneroot_ds,
2184 ZFS_TYPE_FILESYSTEM)) == NULL) {
2185 be_print_err(gettext("be_copy_zones: "
2186 "failed to open the new zone BE root dataset "
2187 "(%s): %s\n"), new_zoneroot_ds,
2188 libzfs_error_description(g_zfs));
2189 ret = zfs_err_to_be_err(g_zfs);
2190 goto done;
2191 }
2192
2193 if (zfs_prop_set(z_zhp, BE_ZONE_PARENTBE_PROPERTY,
2194 uu_string) != 0) {
2195 be_print_err(gettext("be_copy_zones: "
2196 "failed to set parentbe property\n"));
2197 ZFS_CLOSE(z_zhp);
2198 ret = zfs_err_to_be_err(g_zfs);
|