1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
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, 2015 by Delphix. All rights reserved.
26  * Copyright (c) 2016 Martin Matuska. All rights reserved.
27  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
28  */
29 
30 /*
31  * System includes
32  */
33 
34 #include <assert.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <libgen.h>
38 #include <libintl.h>
39 #include <libnvpair.h>
40 #include <libzfs.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/mnttab.h>
45 #include <sys/mount.h>
46 #include <sys/stat.h>
47 #include <sys/types.h>
48 #include <sys/wait.h>
49 #include <unistd.h>
50 
51 #include <libbe.h>
52 #include <libbe_priv.h>
53 #include <libzfsbootenv.h>
54 
55 /* Library wide variables */
56 libzfs_handle_t *g_zfs = NULL;
57 
58 /* Private function prototypes */
59 static int _be_destroy(const char *, be_destroy_data_t *);
60 static int be_destroy_zones(char *, char *, be_destroy_data_t *);
61 static int be_destroy_zone_roots(char *, be_destroy_data_t *);
62 static int be_destroy_zone_roots_callback(zfs_handle_t *, void *);
63 static int be_copy_zones(char *, char *, char *);
64 static int be_clone_fs_callback(zfs_handle_t *, void *);
65 static int be_destroy_callback(zfs_handle_t *, void *);
66 static int be_send_fs_callback(zfs_handle_t *, void *);
67 static int be_demote_callback(zfs_handle_t *, void *);
68 static int be_demote_find_clone_callback(zfs_handle_t *, void *);
69 static int be_has_snapshot_callback(zfs_handle_t *, void *);
70 static int be_demote_get_one_clone(zfs_handle_t *, void *);
71 static int be_get_snap(char *, char **);
72 static int be_prep_clone_send_fs(zfs_handle_t *, be_transaction_data_t *,
73     char *, int);
74 static boolean_t be_create_container_ds(char *);
75 static char *be_get_zone_be_name(char *root_ds, char *container_ds);
76 static int be_zone_root_exists_callback(zfs_handle_t *, void *);
77 
78 /* ********************************************************************	*/
79 /*			Public Functions				*/
80 /* ********************************************************************	*/
81 
82 /*
83  * Function:	be_init
84  * Description:	Creates the initial datasets for a BE and leaves them
85  *		unpopulated.  The resultant BE can be mounted but can't
86  *		yet be activated or booted.
87  * Parameters:
88  *		be_attrs - pointer to nvlist_t of attributes being passed in.
89  *			The following attributes are used by this function:
90  *
91  *			BE_ATTR_NEW_BE_NAME		*required
92  *			BE_ATTR_NEW_BE_POOL		*required
93  *			BE_ATTR_ZFS_PROPERTIES		*optional
94  *			BE_ATTR_FS_NAMES		*optional
95  *			BE_ATTR_FS_NUM			*optional
96  *			BE_ATTR_SHARED_FS_NAMES		*optional
97  *			BE_ATTR_SHARED_FS_NUM		*optional
98  * Return:
99  *		BE_SUCCESS - Success
100  *		be_errno_t - Failure
101  * Scope:
102  *		Public
103  */
104 int
be_init(nvlist_t * be_attrs)105 be_init(nvlist_t *be_attrs)
106 {
107 	be_transaction_data_t	bt = { 0 };
108 	zpool_handle_t	*zlp;
109 	nvlist_t	*zfs_props = NULL;
110 	char		nbe_root_ds[MAXPATHLEN];
111 	char		child_fs[MAXPATHLEN];
112 	char		**fs_names = NULL;
113 	char		**shared_fs_names = NULL;
114 	uint16_t	fs_num = 0;
115 	uint16_t	shared_fs_num = 0;
116 	int		nelem;
117 	int		i;
118 	int		zret = 0, ret = BE_SUCCESS;
119 
120 	/* Initialize libzfs handle */
121 	if (!be_zfs_init())
122 		return (BE_ERR_INIT);
123 
124 	/* Get new BE name */
125 	if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME, &bt.nbe_name)
126 	    != 0) {
127 		be_print_err(gettext("be_init: failed to lookup "
128 		    "BE_ATTR_NEW_BE_NAME attribute\n"));
129 		return (BE_ERR_INVAL);
130 	}
131 
132 	/* Validate new BE name */
133 	if (!be_valid_be_name(bt.nbe_name)) {
134 		be_print_err(gettext("be_init: invalid BE name %s\n"),
135 		    bt.nbe_name);
136 		return (BE_ERR_INVAL);
137 	}
138 
139 	/* Get zpool name */
140 	if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_POOL, &bt.nbe_zpool)
141 	    != 0) {
142 		be_print_err(gettext("be_init: failed to lookup "
143 		    "BE_ATTR_NEW_BE_POOL attribute\n"));
144 		return (BE_ERR_INVAL);
145 	}
146 
147 	/* Get file system attributes */
148 	nelem = 0;
149 	if (nvlist_lookup_pairs(be_attrs, 0,
150 	    BE_ATTR_FS_NUM, DATA_TYPE_UINT16, &fs_num,
151 	    BE_ATTR_FS_NAMES, DATA_TYPE_STRING_ARRAY, &fs_names, &nelem,
152 	    NULL) != 0) {
153 		be_print_err(gettext("be_init: failed to lookup fs "
154 		    "attributes\n"));
155 		return (BE_ERR_INVAL);
156 	}
157 	if (nelem != fs_num) {
158 		be_print_err(gettext("be_init: size of FS_NAMES array (%d) "
159 		    "does not match FS_NUM (%d)\n"), nelem, fs_num);
160 		return (BE_ERR_INVAL);
161 	}
162 
163 	/* Get shared file system attributes */
164 	nelem = 0;
165 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
166 	    BE_ATTR_SHARED_FS_NUM, DATA_TYPE_UINT16, &shared_fs_num,
167 	    BE_ATTR_SHARED_FS_NAMES, DATA_TYPE_STRING_ARRAY, &shared_fs_names,
168 	    &nelem, NULL) != 0) {
169 		be_print_err(gettext("be_init: failed to lookup "
170 		    "shared fs attributes\n"));
171 		return (BE_ERR_INVAL);
172 	}
173 	if (nelem != shared_fs_num) {
174 		be_print_err(gettext("be_init: size of SHARED_FS_NAMES "
175 		    "array does not match SHARED_FS_NUM\n"));
176 		return (BE_ERR_INVAL);
177 	}
178 
179 	/* Verify that nbe_zpool exists */
180 	if ((zlp = zpool_open(g_zfs, bt.nbe_zpool)) == NULL) {
181 		be_print_err(gettext("be_init: failed to "
182 		    "find existing zpool (%s): %s\n"), bt.nbe_zpool,
183 		    libzfs_error_description(g_zfs));
184 		return (zfs_err_to_be_err(g_zfs));
185 	}
186 	zpool_close(zlp);
187 
188 	/*
189 	 * Verify BE container dataset in nbe_zpool exists.
190 	 * If not, create it.
191 	 */
192 	if (!be_create_container_ds(bt.nbe_zpool))
193 		return (BE_ERR_CREATDS);
194 
195 	/*
196 	 * Verify that nbe_name doesn't already exist in some pool.
197 	 */
198 	if ((zret = zpool_iter(g_zfs, be_exists_callback, bt.nbe_name)) > 0) {
199 		be_print_err(gettext("be_init: BE (%s) already exists\n"),
200 		    bt.nbe_name);
201 		return (BE_ERR_BE_EXISTS);
202 	} else if (zret < 0) {
203 		be_print_err(gettext("be_init: zpool_iter failed: %s\n"),
204 		    libzfs_error_description(g_zfs));
205 		return (zfs_err_to_be_err(g_zfs));
206 	}
207 
208 	/* Generate string for BE's root dataset */
209 	if ((ret = be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds,
210 	    sizeof (nbe_root_ds))) != BE_SUCCESS) {
211 		be_print_err(gettext("%s: failed to get BE container dataset "
212 		    "for %s/%s\n"), __func__, bt.nbe_zpool, bt.nbe_name);
213 		return (ret);
214 	}
215 
216 	/*
217 	 * Create property list for new BE root dataset.  If some
218 	 * zfs properties were already provided by the caller, dup
219 	 * that list.  Otherwise initialize a new property list.
220 	 */
221 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
222 	    BE_ATTR_ZFS_PROPERTIES, DATA_TYPE_NVLIST, &zfs_props, NULL)
223 	    != 0) {
224 		be_print_err(gettext("be_init: failed to lookup "
225 		    "BE_ATTR_ZFS_PROPERTIES attribute\n"));
226 		return (BE_ERR_INVAL);
227 	}
228 	if (zfs_props != NULL) {
229 		/* Make sure its a unique nvlist */
230 		if (!(zfs_props->nvl_nvflag & NV_UNIQUE_NAME) &&
231 		    !(zfs_props->nvl_nvflag & NV_UNIQUE_NAME_TYPE)) {
232 			be_print_err(gettext("be_init: ZFS property list "
233 			    "not unique\n"));
234 			return (BE_ERR_INVAL);
235 		}
236 
237 		/* Dup the list */
238 		if (nvlist_dup(zfs_props, &bt.nbe_zfs_props, 0) != 0) {
239 			be_print_err(gettext("be_init: failed to dup ZFS "
240 			    "property list\n"));
241 			return (BE_ERR_NOMEM);
242 		}
243 	} else {
244 		/* Initialize new nvlist */
245 		if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) {
246 			be_print_err(gettext("be_init: internal "
247 			    "error: out of memory\n"));
248 			return (BE_ERR_NOMEM);
249 		}
250 	}
251 
252 	/* Set the mountpoint property for the root dataset */
253 	if (nvlist_add_string(bt.nbe_zfs_props,
254 	    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), "/") != 0) {
255 		be_print_err(gettext("be_init: internal error "
256 		    "out of memory\n"));
257 		ret = BE_ERR_NOMEM;
258 		goto done;
259 	}
260 
261 	/* Set the 'canmount' property */
262 	if (nvlist_add_string(bt.nbe_zfs_props,
263 	    zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto") != 0) {
264 		be_print_err(gettext("be_init: internal error "
265 		    "out of memory\n"));
266 		ret = BE_ERR_NOMEM;
267 		goto done;
268 	}
269 
270 	/* Create BE root dataset for the new BE */
271 	if (zfs_create(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM,
272 	    bt.nbe_zfs_props) != 0) {
273 		be_print_err(gettext("be_init: failed to "
274 		    "create BE root dataset (%s): %s\n"), nbe_root_ds,
275 		    libzfs_error_description(g_zfs));
276 		ret = zfs_err_to_be_err(g_zfs);
277 		goto done;
278 	}
279 
280 	/* Set UUID for new BE */
281 	if ((ret = be_set_uuid(nbe_root_ds)) != BE_SUCCESS) {
282 		be_print_err(gettext("be_init: failed to "
283 		    "set uuid for new BE\n"));
284 	}
285 
286 	/*
287 	 * Clear the mountpoint property so that the non-shared
288 	 * file systems created below inherit their mountpoints.
289 	 */
290 	(void) nvlist_remove(bt.nbe_zfs_props,
291 	    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), DATA_TYPE_STRING);
292 
293 	/* Create the new BE's non-shared file systems */
294 	for (i = 0; i < fs_num && fs_names[i]; i++) {
295 		/*
296 		 * If fs == "/", skip it;
297 		 * we already created the root dataset
298 		 */
299 		if (strcmp(fs_names[i], "/") == 0)
300 			continue;
301 
302 		/* Generate string for file system */
303 		(void) snprintf(child_fs, sizeof (child_fs), "%s%s",
304 		    nbe_root_ds, fs_names[i]);
305 
306 		/* Create file system */
307 		if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM,
308 		    bt.nbe_zfs_props) != 0) {
309 			be_print_err(gettext("be_init: failed to create "
310 			    "BE's child dataset (%s): %s\n"), child_fs,
311 			    libzfs_error_description(g_zfs));
312 			ret = zfs_err_to_be_err(g_zfs);
313 			goto done;
314 		}
315 	}
316 
317 	/* Create the new BE's shared file systems */
318 	if (shared_fs_num > 0) {
319 		nvlist_t	*props = NULL;
320 
321 		if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
322 			be_print_err(gettext("be_init: nvlist_alloc failed\n"));
323 			ret = BE_ERR_NOMEM;
324 			goto done;
325 		}
326 
327 		for (i = 0; i < shared_fs_num; i++) {
328 			/* Generate string for shared file system */
329 			(void) snprintf(child_fs, sizeof (child_fs), "%s%s",
330 			    bt.nbe_zpool, shared_fs_names[i]);
331 
332 			if (nvlist_add_string(props,
333 			    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
334 			    shared_fs_names[i]) != 0) {
335 				be_print_err(gettext("be_init: "
336 				    "internal error: out of memory\n"));
337 				nvlist_free(props);
338 				ret = BE_ERR_NOMEM;
339 				goto done;
340 			}
341 
342 			/* Create file system if it doesn't already exist */
343 			if (zfs_dataset_exists(g_zfs, child_fs,
344 			    ZFS_TYPE_FILESYSTEM)) {
345 				continue;
346 			}
347 			if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM,
348 			    props) != 0) {
349 				be_print_err(gettext("be_init: failed to "
350 				    "create BE's shared dataset (%s): %s\n"),
351 				    child_fs, libzfs_error_description(g_zfs));
352 				ret = zfs_err_to_be_err(g_zfs);
353 				nvlist_free(props);
354 				goto done;
355 			}
356 		}
357 
358 		nvlist_free(props);
359 	}
360 
361 done:
362 	nvlist_free(bt.nbe_zfs_props);
363 
364 	be_zfs_fini();
365 
366 	return (ret);
367 }
368 
369 /*
370  * Function:	be_destroy
371  * Description:	Destroy a BE and all of its children datasets, snapshots and
372  *		zones that belong to the parent BE.
373  * Parameters:
374  *		be_attrs - pointer to nvlist_t of attributes being passed in.
375  *			The following attributes are used by this function:
376  *
377  *			BE_ATTR_ORIG_BE_NAME		*required
378  *			BE_ATTR_DESTROY_FLAGS		*optional
379  * Return:
380  *		BE_SUCCESS - Success
381  *		be_errno_t - Failure
382  * Scope:
383  *		Public
384  */
385 int
be_destroy(nvlist_t * be_attrs)386 be_destroy(nvlist_t *be_attrs)
387 {
388 	zfs_handle_t		*zhp = NULL;
389 	be_transaction_data_t	bt = { 0 };
390 	be_transaction_data_t	cur_bt = { 0 };
391 	be_destroy_data_t	dd = { 0 };
392 	int			ret = BE_SUCCESS;
393 	uint16_t		flags = 0;
394 	boolean_t		bs_found = B_FALSE;
395 	int			zret;
396 	char			obe_root_ds[MAXPATHLEN];
397 	char			*mp = NULL;
398 
399 	/* Initialize libzfs handle */
400 	if (!be_zfs_init())
401 		return (BE_ERR_INIT);
402 
403 	/* Get name of BE to delete */
404 	if (nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, &bt.obe_name)
405 	    != 0) {
406 		be_print_err(gettext("be_destroy: failed to lookup "
407 		    "BE_ATTR_ORIG_BE_NAME attribute\n"));
408 		return (BE_ERR_INVAL);
409 	}
410 
411 	/*
412 	 * Validate BE name. If valid, then check that the original BE is not
413 	 * the active BE. If it is the 'active' BE then return an error code
414 	 * since we can't destroy the active BE.
415 	 */
416 	if (!be_valid_be_name(bt.obe_name)) {
417 		be_print_err(gettext("be_destroy: invalid BE name %s\n"),
418 		    bt.obe_name);
419 		return (BE_ERR_INVAL);
420 	} else if (bt.obe_name != NULL) {
421 		if ((ret = be_find_current_be(&cur_bt)) != BE_SUCCESS) {
422 			return (ret);
423 		}
424 		if (strcmp(cur_bt.obe_name, bt.obe_name) == 0) {
425 			return (BE_ERR_DESTROY_CURR_BE);
426 		}
427 	}
428 
429 	/* Get destroy flags if provided */
430 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
431 	    BE_ATTR_DESTROY_FLAGS, DATA_TYPE_UINT16, &flags, NULL)
432 	    != 0) {
433 		be_print_err(gettext("be_destroy: failed to lookup "
434 		    "BE_ATTR_DESTROY_FLAGS attribute\n"));
435 		return (BE_ERR_INVAL);
436 	}
437 
438 	dd.destroy_snaps = flags & BE_DESTROY_FLAG_SNAPSHOTS;
439 	dd.force_unmount = flags & BE_DESTROY_FLAG_FORCE_UNMOUNT;
440 
441 	/* Find which zpool obe_name lives in */
442 	if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) {
443 		be_print_err(gettext("be_destroy: failed to find zpool "
444 		    "for BE (%s)\n"), bt.obe_name);
445 		return (BE_ERR_BE_NOENT);
446 	} else if (zret < 0) {
447 		be_print_err(gettext("be_destroy: zpool_iter failed: %s\n"),
448 		    libzfs_error_description(g_zfs));
449 		return (zfs_err_to_be_err(g_zfs));
450 	}
451 
452 	/* Generate string for obe_name's root dataset */
453 	if ((ret = be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds,
454 	    sizeof (obe_root_ds))) != BE_SUCCESS) {
455 		be_print_err(gettext("%s: failed to get BE container dataset "
456 		    "for %s/%s\n"), __func__, bt.obe_zpool, bt.obe_name);
457 		return (ret);
458 	}
459 	bt.obe_root_ds = obe_root_ds;
460 
461 	if (getzoneid() != GLOBAL_ZONEID) {
462 		if (!be_zone_compare_uuids(bt.obe_root_ds)) {
463 			if (be_is_active_on_boot(bt.obe_name)) {
464 				be_print_err(gettext("be_destroy: destroying "
465 				    "active zone root dataset from non-active "
466 				    "global BE is not supported\n"));
467 				return (BE_ERR_NOTSUP);
468 			}
469 		}
470 	}
471 
472 	/*
473 	 * Detect if the BE to destroy has the 'active on boot' property set.
474 	 * If so, set the 'active on boot' property on the the 'active' BE.
475 	 */
476 	if (be_is_active_on_boot(bt.obe_name)) {
477 		if ((ret = be_activate_current_be()) != BE_SUCCESS) {
478 			be_print_err(gettext("be_destroy: failed to "
479 			    "make the current BE 'active on boot'\n"));
480 			return (ret);
481 		}
482 	}
483 
484 	/*
485 	 * Detect if the BE to destroy is referenced in the pool's nextboot
486 	 * field, and unset it if so.
487 	 */
488 	if (getzoneid() == GLOBAL_ZONEID) {
489 		char *nextboot = NULL;
490 
491 		if (lzbe_get_boot_device(bt.obe_zpool, &nextboot) == 0 &&
492 		    nextboot != NULL && strcmp(nextboot, bt.obe_root_ds) == 0) {
493 			if (lzbe_set_boot_device(bt.obe_zpool,
494 			    lzbe_add, "") != 0) {
495 				be_print_err(gettext("be_destroy: failed to "
496 				    "remove temporary activation for "
497 				    "dataset %s on pool %s\n"),
498 				    bt.obe_root_ds, bt.obe_zpool);
499 				free(nextboot);
500 				return (BE_ERR_UNKNOWN);
501 			}
502 		}
503 		free(nextboot);
504 	}
505 
506 	/* Get handle to BE's root dataset */
507 	if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM)) ==
508 	    NULL) {
509 		be_print_err(gettext("be_destroy: failed to "
510 		    "open BE root dataset (%s): %s\n"), bt.obe_root_ds,
511 		    libzfs_error_description(g_zfs));
512 		return (zfs_err_to_be_err(g_zfs));
513 	}
514 
515 	/*
516 	 * Check if BE has snapshots and BE_DESTROY_FLAG_SNAPSHOTS
517 	 * is not set.
518 	 */
519 	(void) zfs_iter_snapshots(zhp, B_FALSE, be_has_snapshot_callback,
520 	    &bs_found);
521 	if (!dd.destroy_snaps && bs_found) {
522 		ZFS_CLOSE(zhp);
523 		return (BE_ERR_SS_EXISTS);
524 	}
525 
526 	/* Get the UUID of the global BE */
527 	if (getzoneid() == GLOBAL_ZONEID) {
528 		if (be_get_uuid(zfs_get_name(zhp),
529 		    &dd.gz_be_uuid) != BE_SUCCESS) {
530 			be_print_err(gettext("be_destroy: BE has no "
531 			"UUID (%s)\n"), zfs_get_name(zhp));
532 		}
533 	}
534 
535 	/*
536 	 * If the global BE is mounted, make sure we've been given the
537 	 * flag to forcibly unmount it.
538 	 */
539 	if (zfs_is_mounted(zhp, &mp)) {
540 		if (!(dd.force_unmount)) {
541 			be_print_err(gettext("be_destroy: "
542 			    "%s is currently mounted at %s, cannot destroy\n"),
543 			    bt.obe_name, mp != NULL ? mp : "<unknown>");
544 
545 			free(mp);
546 			ZFS_CLOSE(zhp);
547 			return (BE_ERR_MOUNTED);
548 		}
549 		free(mp);
550 	}
551 
552 	/*
553 	 * Destroy the non-global zone BE's if we are in the global zone
554 	 * and there is a UUID associated with the global zone BE
555 	 */
556 	if (getzoneid() == GLOBAL_ZONEID && !uuid_is_null(dd.gz_be_uuid)) {
557 		if ((ret = be_destroy_zones(bt.obe_name, bt.obe_root_ds, &dd))
558 		    != BE_SUCCESS) {
559 			be_print_err(gettext("be_destroy: failed to "
560 			    "destroy one or more zones for BE %s\n"),
561 			    bt.obe_name);
562 			goto done;
563 		}
564 	}
565 
566 	/* Unmount the BE if it was mounted */
567 	if (zfs_is_mounted(zhp, NULL)) {
568 		if ((ret = _be_unmount(bt.obe_name, BE_UNMOUNT_FLAG_FORCE))
569 		    != BE_SUCCESS) {
570 			be_print_err(gettext("be_destroy: "
571 			    "failed to unmount %s\n"), bt.obe_name);
572 			ZFS_CLOSE(zhp);
573 			return (ret);
574 		}
575 	}
576 	ZFS_CLOSE(zhp);
577 
578 	/* Destroy this BE */
579 	if ((ret = _be_destroy((const char *)bt.obe_root_ds, &dd))
580 	    != BE_SUCCESS) {
581 		goto done;
582 	}
583 
584 	/* Remove BE's entry from the boot menu */
585 	if (getzoneid() == GLOBAL_ZONEID) {
586 		if ((ret = be_remove_menu(bt.obe_name, bt.obe_zpool, NULL))
587 		    != BE_SUCCESS) {
588 			be_print_err(gettext("be_destroy: failed to "
589 			    "remove BE %s from the boot menu\n"),
590 			    bt.obe_root_ds);
591 			goto done;
592 		}
593 	}
594 
595 done:
596 	be_zfs_fini();
597 
598 	return (ret);
599 }
600 
601 /*
602  * Function:	be_copy
603  * Description:	This function makes a copy of an existing BE.  If the original
604  *		BE and the new BE are in the same pool, it uses zfs cloning to
605  *		create the new BE, otherwise it does a physical copy.
606  *		If the original BE name isn't provided, it uses the currently
607  *		booted BE.  If the new BE name isn't provided, it creates an
608  *		auto named BE and returns that name to the caller.
609  * Parameters:
610  *		be_attrs - pointer to nvlist_t of attributes being passed in.
611  *			The following attributes are used by this function:
612  *
613  *			BE_ATTR_ORIG_BE_NAME		*optional
614  *			BE_ATTR_SNAP_NAME		*optional
615  *			BE_ATTR_NEW_BE_NAME		*optional
616  *			BE_ATTR_NEW_BE_POOL		*optional
617  *			BE_ATTR_NEW_BE_DESC		*optional
618  *			BE_ATTR_ZFS_PROPERTIES		*optional
619  *			BE_ATTR_POLICY			*optional
620  *
621  *			If the BE_ATTR_NEW_BE_NAME was not passed in, upon
622  *			successful BE creation, the following attribute values
623  *			will be returned to the caller by setting them in the
624  *			be_attrs parameter passed in:
625  *
626  *			BE_ATTR_SNAP_NAME
627  *			BE_ATTR_NEW_BE_NAME
628  * Return:
629  *		BE_SUCCESS - Success
630  *		be_errno_t - Failure
631  * Scope:
632  *		Public
633  */
634 int
be_copy(nvlist_t * be_attrs)635 be_copy(nvlist_t *be_attrs)
636 {
637 	be_transaction_data_t	bt = { 0 };
638 	be_fs_list_data_t	fld = { 0 };
639 	zfs_handle_t	*zhp = NULL;
640 	zpool_handle_t	*zphp = NULL;
641 	nvlist_t	*zfs_props = NULL;
642 	uuid_t		uu = { 0 };
643 	uuid_t		parent_uu = { 0 };
644 	char		obe_root_ds[MAXPATHLEN];
645 	char		nbe_root_ds[MAXPATHLEN];
646 	char		obe_root_container[MAXPATHLEN];
647 	char		nbe_root_container[MAXPATHLEN];
648 	char		ss[MAXPATHLEN];
649 	char		*new_mp = NULL;
650 	char		*obe_name = NULL;
651 	boolean_t	autoname = B_FALSE;
652 	boolean_t	be_created = B_FALSE;
653 	int		i;
654 	int		zret;
655 	int		ret = BE_SUCCESS;
656 	struct be_defaults be_defaults;
657 
658 	/* Initialize libzfs handle */
659 	if (!be_zfs_init())
660 		return (BE_ERR_INIT);
661 
662 	/* Get original BE name */
663 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
664 	    BE_ATTR_ORIG_BE_NAME, DATA_TYPE_STRING, &obe_name, NULL) != 0) {
665 		be_print_err(gettext("be_copy: failed to lookup "
666 		    "BE_ATTR_ORIG_BE_NAME attribute\n"));
667 		return (BE_ERR_INVAL);
668 	}
669 
670 	if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) {
671 		return (ret);
672 	}
673 
674 	be_get_defaults(&be_defaults);
675 
676 	/* If original BE name not provided, use current BE */
677 	if (obe_name != NULL) {
678 		bt.obe_name = obe_name;
679 		/* Validate original BE name */
680 		if (!be_valid_be_name(bt.obe_name)) {
681 			be_print_err(gettext("be_copy: "
682 			    "invalid BE name %s\n"), bt.obe_name);
683 			return (BE_ERR_INVAL);
684 		}
685 	}
686 
687 	if (be_defaults.be_deflt_rpool_container) {
688 		if ((zphp = zpool_open(g_zfs, bt.obe_zpool)) == NULL) {
689 			be_print_err(gettext("be_get_node_data: failed to "
690 			    "open rpool (%s): %s\n"), bt.obe_zpool,
691 			    libzfs_error_description(g_zfs));
692 			return (zfs_err_to_be_err(g_zfs));
693 		}
694 		if (be_find_zpool_callback(zphp, &bt) == 0) {
695 			return (BE_ERR_BE_NOENT);
696 		}
697 	} else {
698 		/* Find which zpool obe_name lives in */
699 		if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) ==
700 		    0) {
701 			be_print_err(gettext("be_copy: failed to "
702 			    "find zpool for BE (%s)\n"), bt.obe_name);
703 			return (BE_ERR_BE_NOENT);
704 		} else if (zret < 0) {
705 			be_print_err(gettext("be_copy: "
706 			    "zpool_iter failed: %s\n"),
707 			    libzfs_error_description(g_zfs));
708 			return (zfs_err_to_be_err(g_zfs));
709 		}
710 	}
711 
712 	/* Get snapshot name of original BE if one was provided */
713 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
714 	    BE_ATTR_SNAP_NAME, DATA_TYPE_STRING, &bt.obe_snap_name, NULL)
715 	    != 0) {
716 		be_print_err(gettext("be_copy: failed to lookup "
717 		    "BE_ATTR_SNAP_NAME attribute\n"));
718 		return (BE_ERR_INVAL);
719 	}
720 
721 	/* Get new BE name */
722 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
723 	    BE_ATTR_NEW_BE_NAME, DATA_TYPE_STRING, &bt.nbe_name, NULL)
724 	    != 0) {
725 		be_print_err(gettext("be_copy: failed to lookup "
726 		    "BE_ATTR_NEW_BE_NAME attribute\n"));
727 		return (BE_ERR_INVAL);
728 	}
729 
730 	/* Get zpool name to create new BE in */
731 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
732 	    BE_ATTR_NEW_BE_POOL, DATA_TYPE_STRING, &bt.nbe_zpool, NULL) != 0) {
733 		be_print_err(gettext("be_copy: failed to lookup "
734 		    "BE_ATTR_NEW_BE_POOL attribute\n"));
735 		return (BE_ERR_INVAL);
736 	}
737 
738 	/* Get new BE's description if one was provided */
739 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
740 	    BE_ATTR_NEW_BE_DESC, DATA_TYPE_STRING, &bt.nbe_desc, NULL) != 0) {
741 		be_print_err(gettext("be_copy: failed to lookup "
742 		    "BE_ATTR_NEW_BE_DESC attribute\n"));
743 		return (BE_ERR_INVAL);
744 	}
745 
746 	/* Get BE policy to create this snapshot under */
747 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
748 	    BE_ATTR_POLICY, DATA_TYPE_STRING, &bt.policy, NULL) != 0) {
749 		be_print_err(gettext("be_copy: failed to lookup "
750 		    "BE_ATTR_POLICY attribute\n"));
751 		return (BE_ERR_INVAL);
752 	}
753 
754 	/*
755 	 * Create property list for new BE root dataset.  If some
756 	 * zfs properties were already provided by the caller, dup
757 	 * that list.  Otherwise initialize a new property list.
758 	 */
759 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
760 	    BE_ATTR_ZFS_PROPERTIES, DATA_TYPE_NVLIST, &zfs_props, NULL)
761 	    != 0) {
762 		be_print_err(gettext("be_copy: failed to lookup "
763 		    "BE_ATTR_ZFS_PROPERTIES attribute\n"));
764 		return (BE_ERR_INVAL);
765 	}
766 	if (zfs_props != NULL) {
767 		/* Make sure its a unique nvlist */
768 		if (!(zfs_props->nvl_nvflag & NV_UNIQUE_NAME) &&
769 		    !(zfs_props->nvl_nvflag & NV_UNIQUE_NAME_TYPE)) {
770 			be_print_err(gettext("be_copy: ZFS property list "
771 			    "not unique\n"));
772 			return (BE_ERR_INVAL);
773 		}
774 
775 		/* Dup the list */
776 		if (nvlist_dup(zfs_props, &bt.nbe_zfs_props, 0) != 0) {
777 			be_print_err(gettext("be_copy: "
778 			    "failed to dup ZFS property list\n"));
779 			return (BE_ERR_NOMEM);
780 		}
781 	} else {
782 		/* Initialize new nvlist */
783 		if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) {
784 			be_print_err(gettext("be_copy: internal "
785 			    "error: out of memory\n"));
786 			return (BE_ERR_NOMEM);
787 		}
788 	}
789 
790 	/*
791 	 * If an auto named BE is desired, it must be in the same
792 	 * pool as the original BE.
793 	 */
794 	if (bt.nbe_name == NULL && bt.nbe_zpool != NULL) {
795 		be_print_err(gettext("be_copy: cannot specify pool "
796 		    "name when creating an auto named BE\n"));
797 		ret = BE_ERR_INVAL;
798 		goto done;
799 	}
800 
801 	/*
802 	 * If the zpool name to create new BE in is not provided,
803 	 * create the new BE in the original BE's pool.
804 	 */
805 	if (bt.nbe_zpool == NULL)
806 		bt.nbe_zpool = bt.obe_zpool;
807 
808 	/*
809 	 * If new BE name provided, validate the BE name and then verify
810 	 * that new BE name doesn't already exist in some pool.
811 	 */
812 	if (bt.nbe_name != NULL) {
813 		/* Validate original BE name */
814 		if (!be_valid_be_name(bt.nbe_name)) {
815 			be_print_err(gettext("be_copy: "
816 			    "invalid BE name %s\n"), bt.nbe_name);
817 			ret = BE_ERR_INVAL;
818 			goto done;
819 		}
820 
821 		/* Verify it doesn't already exist */
822 		if (getzoneid() == GLOBAL_ZONEID) {
823 			if ((zret = zpool_iter(g_zfs, be_exists_callback,
824 			    bt.nbe_name)) > 0) {
825 				be_print_err(gettext("be_copy: BE (%s) already "
826 				    "exists\n"), bt.nbe_name);
827 				ret = BE_ERR_BE_EXISTS;
828 				goto done;
829 			} else if (zret < 0) {
830 				be_print_err(gettext("be_copy: zpool_iter "
831 				    "failed: %s\n"),
832 				    libzfs_error_description(g_zfs));
833 				ret = zfs_err_to_be_err(g_zfs);
834 				goto done;
835 			}
836 		} else {
837 			if ((ret = be_make_root_ds(bt.nbe_zpool, bt.nbe_name,
838 			    nbe_root_ds, sizeof (nbe_root_ds))) != BE_SUCCESS) {
839 				be_print_err(gettext("%s: failed to get BE "
840 				    "container dataset for %s/%s\n"), __func__,
841 				    bt.nbe_zpool, bt.nbe_name);
842 				goto done;
843 			}
844 			if (zfs_dataset_exists(g_zfs, nbe_root_ds,
845 			    ZFS_TYPE_FILESYSTEM)) {
846 				be_print_err(gettext("be_copy: BE (%s) already "
847 				    "exists\n"), bt.nbe_name);
848 				ret = BE_ERR_BE_EXISTS;
849 				goto done;
850 			}
851 		}
852 	} else {
853 		/*
854 		 * Generate auto named BE
855 		 */
856 		if ((bt.nbe_name = be_auto_be_name(bt.obe_name))
857 		    == NULL) {
858 			be_print_err(gettext("be_copy: "
859 			    "failed to generate auto BE name\n"));
860 			ret = BE_ERR_AUTONAME;
861 			goto done;
862 		}
863 
864 		autoname = B_TRUE;
865 	}
866 
867 	/* Get root dataset names for obe_name and nbe_name */
868 	if ((ret = be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds,
869 	    sizeof (obe_root_ds))) != BE_SUCCESS) {
870 		be_print_err(gettext("%s: failed to get BE container dataset "
871 		    "for %s/%s\n"), __func__, bt.obe_zpool, bt.obe_name);
872 		goto done;
873 	}
874 	if ((ret = be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds,
875 	    sizeof (nbe_root_ds))) != BE_SUCCESS) {
876 		be_print_err(gettext("%s: failed to get BE container dataset "
877 		    "for %s/%s\n"), __func__, bt.nbe_zpool, bt.nbe_name);
878 		goto done;
879 	}
880 
881 	bt.obe_root_ds = obe_root_ds;
882 	bt.nbe_root_ds = nbe_root_ds;
883 
884 	/*
885 	 * If an existing snapshot name has been provided to create from,
886 	 * verify that it exists for the original BE's root dataset.
887 	 */
888 	if (bt.obe_snap_name != NULL) {
889 
890 		/* Generate dataset name for snapshot to use. */
891 		(void) snprintf(ss, sizeof (ss), "%s@%s", bt.obe_root_ds,
892 		    bt.obe_snap_name);
893 
894 		/* Verify snapshot exists */
895 		if (!zfs_dataset_exists(g_zfs, ss, ZFS_TYPE_SNAPSHOT)) {
896 			be_print_err(gettext("be_copy: "
897 			    "snapshot does not exist (%s): %s\n"), ss,
898 			    libzfs_error_description(g_zfs));
899 			ret = BE_ERR_SS_NOENT;
900 			goto done;
901 		}
902 	} else {
903 		/*
904 		 * Else snapshot name was not provided, generate an
905 		 * auto named snapshot to use as its origin.
906 		 */
907 		if ((ret = _be_create_snapshot(bt.obe_name,
908 		    &bt.obe_snap_name, bt.policy)) != BE_SUCCESS) {
909 			be_print_err(gettext("be_copy: "
910 			    "failed to create auto named snapshot\n"));
911 			goto done;
912 		}
913 
914 		if (nvlist_add_string(be_attrs, BE_ATTR_SNAP_NAME,
915 		    bt.obe_snap_name) != 0) {
916 			be_print_err(gettext("be_copy: "
917 			    "failed to add snap name to be_attrs\n"));
918 			ret = BE_ERR_NOMEM;
919 			goto done;
920 		}
921 	}
922 
923 	/* Get handle to original BE's root dataset. */
924 	if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM))
925 	    == NULL) {
926 		be_print_err(gettext("be_copy: failed to "
927 		    "open BE root dataset (%s): %s\n"), bt.obe_root_ds,
928 		    libzfs_error_description(g_zfs));
929 		ret = zfs_err_to_be_err(g_zfs);
930 		goto done;
931 	}
932 
933 	/* If original BE is currently mounted, record its altroot. */
934 	if (zfs_is_mounted(zhp, &bt.obe_altroot) && bt.obe_altroot == NULL) {
935 		be_print_err(gettext("be_copy: failed to "
936 		    "get altroot of mounted BE %s: %s\n"),
937 		    bt.obe_name, libzfs_error_description(g_zfs));
938 		ret = zfs_err_to_be_err(g_zfs);
939 		goto done;
940 	}
941 
942 	if (strcmp(bt.obe_zpool, bt.nbe_zpool) == 0) {
943 
944 		/* Do clone */
945 
946 		/*
947 		 * Iterate through original BE's datasets and clone
948 		 * them to create new BE.  This call will end up closing
949 		 * the zfs handle passed in whether it succeeds for fails.
950 		 */
951 		if ((ret = be_clone_fs_callback(zhp, &bt)) != 0) {
952 			zhp = NULL;
953 			/* Creating clone BE failed */
954 			if (!autoname || ret != BE_ERR_BE_EXISTS) {
955 				be_print_err(gettext("be_copy: "
956 				    "failed to clone new BE (%s) from "
957 				    "orig BE (%s)\n"),
958 				    bt.nbe_name, bt.obe_name);
959 				ret = BE_ERR_CLONE;
960 				goto done;
961 			}
962 
963 			/*
964 			 * We failed to create the new BE because a BE with
965 			 * the auto-name we generated above has since come
966 			 * into existence.  Regenerate a new auto-name
967 			 * and retry.
968 			 */
969 			for (i = 1; i < BE_AUTO_NAME_MAX_TRY; i++) {
970 
971 				/* Sleep 1 before retrying */
972 				(void) sleep(1);
973 
974 				/* Generate new auto BE name */
975 				free(bt.nbe_name);
976 				if ((bt.nbe_name = be_auto_be_name(bt.obe_name))
977 				    == NULL) {
978 					be_print_err(gettext("be_copy: "
979 					    "failed to generate auto "
980 					    "BE name\n"));
981 					ret = BE_ERR_AUTONAME;
982 					goto done;
983 				}
984 
985 				/*
986 				 * Regenerate string for new BE's
987 				 * root dataset name
988 				 */
989 				if ((ret = be_make_root_ds(bt.nbe_zpool,
990 				    bt.nbe_name, nbe_root_ds,
991 				    sizeof (nbe_root_ds))) != BE_SUCCESS) {
992 					be_print_err(gettext(
993 					    "%s: failed to get BE container "
994 					    "dataset for %s/%s\n"), __func__,
995 					    bt.nbe_zpool, bt.nbe_name);
996 					goto done;
997 				}
998 				bt.nbe_root_ds = nbe_root_ds;
999 
1000 				/*
1001 				 * Get handle to original BE's root dataset.
1002 				 */
1003 				if ((zhp = zfs_open(g_zfs, bt.obe_root_ds,
1004 				    ZFS_TYPE_FILESYSTEM)) == NULL) {
1005 					be_print_err(gettext("be_copy: "
1006 					    "failed to open BE root dataset "
1007 					    "(%s): %s\n"), bt.obe_root_ds,
1008 					    libzfs_error_description(g_zfs));
1009 					ret = zfs_err_to_be_err(g_zfs);
1010 					goto done;
1011 				}
1012 
1013 				/*
1014 				 * Try to clone the BE again.  This
1015 				 * call will end up closing the zfs
1016 				 * handle passed in whether it
1017 				 * succeeds or fails.
1018 				 */
1019 				ret = be_clone_fs_callback(zhp, &bt);
1020 				zhp = NULL;
1021 				if (ret == 0) {
1022 					break;
1023 				} else if (ret != BE_ERR_BE_EXISTS) {
1024 					be_print_err(gettext("be_copy: "
1025 					    "failed to clone new BE "
1026 					    "(%s) from orig BE (%s)\n"),
1027 					    bt.nbe_name, bt.obe_name);
1028 					ret = BE_ERR_CLONE;
1029 					goto done;
1030 				}
1031 			}
1032 
1033 			/*
1034 			 * If we've exhausted the maximum number of
1035 			 * tries, free the auto BE name and return
1036 			 * error.
1037 			 */
1038 			if (i == BE_AUTO_NAME_MAX_TRY) {
1039 				be_print_err(gettext("be_copy: failed "
1040 				    "to create unique auto BE name\n"));
1041 				free(bt.nbe_name);
1042 				bt.nbe_name = NULL;
1043 				ret = BE_ERR_AUTONAME;
1044 				goto done;
1045 			}
1046 		}
1047 		zhp = NULL;
1048 
1049 	} else {
1050 
1051 		/* Do copy (i.e. send BE datasets via zfs_send/recv) */
1052 
1053 		/*
1054 		 * Verify BE container dataset in nbe_zpool exists.
1055 		 * If not, create it.
1056 		 */
1057 		if (!be_create_container_ds(bt.nbe_zpool)) {
1058 			ret = BE_ERR_CREATDS;
1059 			goto done;
1060 		}
1061 
1062 		/*
1063 		 * Iterate through original BE's datasets and send
1064 		 * them to the other pool.  This call will end up closing
1065 		 * the zfs handle passed in whether it succeeds or fails.
1066 		 */
1067 		if ((ret = be_send_fs_callback(zhp, &bt)) != 0) {
1068 			be_print_err(gettext("be_copy: failed to "
1069 			    "send BE (%s) to pool (%s)\n"), bt.obe_name,
1070 			    bt.nbe_zpool);
1071 			ret = BE_ERR_COPY;
1072 			zhp = NULL;
1073 			goto done;
1074 		}
1075 		zhp = NULL;
1076 	}
1077 
1078 	/*
1079 	 * Set flag to note that the dataset(s) for the new BE have been
1080 	 * successfully created so that if a failure happens from this point
1081 	 * on, we know to cleanup these datasets.
1082 	 */
1083 	be_created = B_TRUE;
1084 
1085 	/*
1086 	 * Validate that the new BE is mountable.
1087 	 * Do not attempt to mount non-global zone datasets
1088 	 * since they are not cloned yet.
1089 	 */
1090 	if ((ret = _be_mount(bt.nbe_name, &new_mp, BE_MOUNT_FLAG_NO_ZONES))
1091 	    != BE_SUCCESS) {
1092 		be_print_err(gettext("be_copy: failed to "
1093 		    "mount newly created BE\n"));
1094 		(void) _be_unmount(bt.nbe_name, 0);
1095 		goto done;
1096 	}
1097 
1098 	/* Set UUID for new BE */
1099 	if (getzoneid() == GLOBAL_ZONEID) {
1100 		if (be_set_uuid(bt.nbe_root_ds) != BE_SUCCESS) {
1101 			be_print_err(gettext("be_copy: failed to "
1102 			    "set uuid for new BE\n"));
1103 		}
1104 	} else {
1105 		if ((ret = be_zone_get_parent_uuid(bt.obe_root_ds,
1106 		    &parent_uu)) != BE_SUCCESS) {
1107 			be_print_err(gettext("be_copy: failed to get "
1108 			    "parentbe uuid from orig BE\n"));
1109 			ret = BE_ERR_ZONE_NO_PARENTBE;
1110 			goto done;
1111 		} else if ((ret = be_zone_set_parent_uuid(bt.nbe_root_ds,
1112 		    parent_uu)) != BE_SUCCESS) {
1113 			be_print_err(gettext("be_copy: failed to set "
1114 			    "parentbe uuid for newly created BE\n"));
1115 			goto done;
1116 		}
1117 	}
1118 
1119 	/*
1120 	 * Process zones outside of the private BE namespace.
1121 	 * This has to be done here because we need the uuid set in the
1122 	 * root dataset of the new BE. The uuid is use to set the parentbe
1123 	 * property for the new zones datasets.
1124 	 */
1125 	if (getzoneid() == GLOBAL_ZONEID &&
1126 	    be_get_uuid(bt.obe_root_ds, &uu) == BE_SUCCESS) {
1127 		if ((ret = be_copy_zones(bt.obe_name, bt.obe_root_ds,
1128 		    bt.nbe_root_ds)) != BE_SUCCESS) {
1129 			be_print_err(gettext("be_copy: failed to process "
1130 			    "zones\n"));
1131 			goto done;
1132 		}
1133 	}
1134 
1135 	/*
1136 	 * Generate a list of file systems from the original BE that are
1137 	 * legacy mounted.  We use this list to determine which entries in
1138 	 * vfstab we need to update for the new BE we've just created.
1139 	 */
1140 	if ((ret = be_get_legacy_fs(bt.obe_name, bt.obe_root_ds, NULL, NULL,
1141 	    &fld)) != BE_SUCCESS) {
1142 		be_print_err(gettext("be_copy: failed to "
1143 		    "get legacy mounted file system list for %s\n"),
1144 		    bt.obe_name);
1145 		goto done;
1146 	}
1147 
1148 	/*
1149 	 * Update new BE's vfstab.
1150 	 */
1151 
1152 	if ((ret = be_make_root_container_ds(bt.obe_zpool, obe_root_container,
1153 	    sizeof (obe_root_container))) != BE_SUCCESS) {
1154 		be_print_err(gettext("%s: failed to get BE container dataset "
1155 		    "for %s\n"), __func__, bt.obe_zpool);
1156 		goto done;
1157 	}
1158 	if ((ret = be_make_root_container_ds(bt.nbe_zpool, nbe_root_container,
1159 	    sizeof (nbe_root_container))) != BE_SUCCESS) {
1160 		be_print_err(gettext("%s: failed to get BE container dataset "
1161 		    "for %s\n"), __func__, bt.nbe_zpool);
1162 		goto done;
1163 	}
1164 
1165 	if ((ret = be_update_vfstab(bt.nbe_name, obe_root_container,
1166 	    nbe_root_container, &fld, new_mp)) != BE_SUCCESS) {
1167 		be_print_err(gettext("be_copy: failed to "
1168 		    "update new BE's vfstab (%s)\n"), bt.nbe_name);
1169 		goto done;
1170 	}
1171 
1172 	/* Unmount the new BE */
1173 	if ((ret = _be_unmount(bt.nbe_name, 0)) != BE_SUCCESS) {
1174 		be_print_err(gettext("be_copy: failed to "
1175 		    "unmount newly created BE\n"));
1176 		goto done;
1177 	}
1178 
1179 	/*
1180 	 * Add boot menu entry for newly created clone
1181 	 */
1182 	if (getzoneid() == GLOBAL_ZONEID &&
1183 	    (ret = be_append_menu(bt.nbe_name, bt.nbe_zpool,
1184 	    NULL, bt.obe_root_ds, bt.nbe_desc)) != BE_SUCCESS) {
1185 		be_print_err(gettext("be_copy: failed to "
1186 		    "add BE (%s) to boot menu\n"), bt.nbe_name);
1187 		goto done;
1188 	}
1189 
1190 	/*
1191 	 * If we succeeded in creating an auto named BE, set its policy
1192 	 * type and return the auto generated name to the caller by storing
1193 	 * it in the nvlist passed in by the caller.
1194 	 */
1195 	if (autoname) {
1196 		/* Get handle to new BE's root dataset. */
1197 		if ((zhp = zfs_open(g_zfs, bt.nbe_root_ds,
1198 		    ZFS_TYPE_FILESYSTEM)) == NULL) {
1199 			be_print_err(gettext("be_copy: failed to "
1200 			    "open BE root dataset (%s): %s\n"), bt.nbe_root_ds,
1201 			    libzfs_error_description(g_zfs));
1202 			ret = zfs_err_to_be_err(g_zfs);
1203 			goto done;
1204 		}
1205 
1206 		/*
1207 		 * Set the policy type property into the new BE's root dataset
1208 		 */
1209 		if (bt.policy == NULL) {
1210 			/* If no policy type provided, use default type */
1211 			bt.policy = be_default_policy();
1212 		}
1213 
1214 		if (zfs_prop_set(zhp, BE_POLICY_PROPERTY, bt.policy) != 0) {
1215 			be_print_err(gettext("be_copy: failed to "
1216 			    "set BE policy for %s: %s\n"), bt.nbe_name,
1217 			    libzfs_error_description(g_zfs));
1218 			ret = zfs_err_to_be_err(g_zfs);
1219 			goto done;
1220 		}
1221 
1222 		/*
1223 		 * Return the auto generated name to the caller
1224 		 */
1225 		if (bt.nbe_name) {
1226 			if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_NAME,
1227 			    bt.nbe_name) != 0) {
1228 				be_print_err(gettext("be_copy: failed to "
1229 				    "add snap name to be_attrs\n"));
1230 			}
1231 		}
1232 	}
1233 
1234 done:
1235 	ZFS_CLOSE(zhp);
1236 	be_free_fs_list(&fld);
1237 
1238 	nvlist_free(bt.nbe_zfs_props);
1239 
1240 	free(bt.obe_altroot);
1241 	free(new_mp);
1242 
1243 	/*
1244 	 * If a failure occurred and we already created the datasets for
1245 	 * the new boot environment, destroy them.
1246 	 */
1247 	if (ret != BE_SUCCESS && be_created) {
1248 		be_destroy_data_t	cdd = { 0 };
1249 
1250 		cdd.force_unmount = B_TRUE;
1251 
1252 		be_print_err(gettext("be_copy: "
1253 		    "destroying partially created boot environment\n"));
1254 
1255 		if (getzoneid() == GLOBAL_ZONEID && be_get_uuid(bt.nbe_root_ds,
1256 		    &cdd.gz_be_uuid) == 0)
1257 			(void) be_destroy_zones(bt.nbe_name, bt.nbe_root_ds,
1258 			    &cdd);
1259 
1260 		(void) _be_destroy(bt.nbe_root_ds, &cdd);
1261 	}
1262 
1263 	be_zfs_fini();
1264 
1265 	return (ret);
1266 }
1267 
1268 /* ********************************************************************	*/
1269 /*			Semi-Private Functions				*/
1270 /* ******************************************************************** */
1271 
1272 /*
1273  * Function:	be_find_zpool_callback
1274  * Description:	Callback function used to find the pool that a BE lives in.
1275  * Parameters:
1276  *		zlp - zpool_handle_t pointer for the current pool being
1277  *			looked at.
1278  *		data - be_transaction_data_t pointer providing information
1279  *			about the BE that's being searched for.
1280  *			This function uses the obe_name member of this
1281  *			parameter to use as the BE name to search for.
1282  *			Upon successfully locating the BE, it populates
1283  *			obe_zpool with the pool name that the BE is found in.
1284  * Returns:
1285  *		1 - BE exists in this pool.
1286  *		0 - BE does not exist in this pool.
1287  * Scope:
1288  *		Semi-private (library wide use only)
1289  */
1290 int
be_find_zpool_callback(zpool_handle_t * zlp,void * data)1291 be_find_zpool_callback(zpool_handle_t *zlp, void *data)
1292 {
1293 	be_transaction_data_t	*bt = data;
1294 	const char		*zpool =  zpool_get_name(zlp);
1295 	char			be_root_ds[MAXPATHLEN];
1296 	int			ret = 0;
1297 
1298 	/*
1299 	 * Generate string for the BE's root dataset
1300 	 */
1301 	if (be_make_root_ds(zpool, bt->obe_name, be_root_ds,
1302 	    sizeof (be_root_ds)) != BE_SUCCESS) {
1303 		goto out;
1304 	}
1305 
1306 	/*
1307 	 * Check if dataset exists
1308 	 */
1309 	if (zfs_dataset_exists(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) {
1310 		/* BE's root dataset exists in zpool */
1311 		bt->obe_zpool = strdup(zpool);
1312 		ret = 1;
1313 	}
1314 
1315 out:
1316 	zpool_close(zlp);
1317 	return (ret);
1318 }
1319 
1320 /*
1321  * Function:	be_exists_callback
1322  * Description:	Callback function used to find out if a BE exists.
1323  * Parameters:
1324  *		zlp - zpool_handle_t pointer to the current pool being
1325  *			looked at.
1326  *		data - BE name to look for.
1327  * Return:
1328  *		1 - BE exists in this pool.
1329  *		0 - BE does not exist in this pool.
1330  * Scope:
1331  *		Semi-private (library wide use only)
1332  */
1333 int
be_exists_callback(zpool_handle_t * zlp,void * data)1334 be_exists_callback(zpool_handle_t *zlp, void *data)
1335 {
1336 	const char	*zpool = zpool_get_name(zlp);
1337 	char		*be_name = data;
1338 	char		be_root_ds[MAXPATHLEN];
1339 	int		ret = 0;
1340 
1341 	/*
1342 	 * Generate string for the BE's root dataset
1343 	 */
1344 	if (be_make_root_ds(zpool, be_name, be_root_ds,
1345 	    sizeof (be_root_ds)) != BE_SUCCESS) {
1346 		goto out;
1347 	}
1348 
1349 	/*
1350 	 * Check if dataset exists
1351 	 */
1352 	if (zfs_dataset_exists(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) {
1353 		/* BE's root dataset exists in zpool */
1354 		ret = 1;
1355 	}
1356 
1357 out:
1358 	zpool_close(zlp);
1359 	return (ret);
1360 }
1361 
1362 /*
1363  * Function:	be_has_snapshots_callback
1364  * Description:	Callback function used to find out if a BE has snapshots.
1365  * Parameters:
1366  *		zlp - zpool_handle_t pointer to the current pool being
1367  *			looked at.
1368  *		data - be_snap_found_t pointer.
1369  * Return:
1370  *		1 - BE has no snapshots.
1371  *		0 - BE has snapshots.
1372  * Scope:
1373  *		Private
1374  */
1375 static int
be_has_snapshot_callback(zfs_handle_t * zhp,void * data)1376 be_has_snapshot_callback(zfs_handle_t *zhp, void *data)
1377 {
1378 	boolean_t *bs = data;
1379 	if (zfs_get_name(zhp) == NULL) {
1380 		zfs_close(zhp);
1381 		return (1);
1382 	}
1383 	*bs = B_TRUE;
1384 	zfs_close(zhp);
1385 	return (0);
1386 }
1387 
1388 /*
1389  * Function:	be_set_uuid
1390  * Description:	This function generates a uuid, unparses it into
1391  *		string representation, and sets that string into
1392  *		a zfs user property for a root dataset of a BE.
1393  *		The name of the user property used to store the
1394  *		uuid is org.opensolaris.libbe:uuid
1395  *
1396  * Parameters:
1397  *		root_ds - Root dataset of the BE to set a uuid on.
1398  * Return:
1399  *		be_errno_t - Failure
1400  *		BE_SUCCESS - Success
1401  * Scope:
1402  *		Semi-private (library wide ues only)
1403  */
1404 int
be_set_uuid(char * root_ds)1405 be_set_uuid(char *root_ds)
1406 {
1407 	zfs_handle_t	*zhp = NULL;
1408 	uuid_t		uu = { 0 };
1409 	char		uu_string[UUID_PRINTABLE_STRING_LENGTH] = { 0 };
1410 	int		ret = BE_SUCCESS;
1411 
1412 	/* Generate a UUID and unparse it into string form */
1413 	uuid_generate(uu);
1414 	if (uuid_is_null(uu) != 0) {
1415 		be_print_err(gettext("be_set_uuid: failed to "
1416 		    "generate uuid\n"));
1417 		return (BE_ERR_GEN_UUID);
1418 	}
1419 	uuid_unparse(uu, uu_string);
1420 
1421 	/* Get handle to the BE's root dataset. */
1422 	if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
1423 		be_print_err(gettext("be_set_uuid: failed to "
1424 		    "open BE root dataset (%s): %s\n"), root_ds,
1425 		    libzfs_error_description(g_zfs));
1426 		return (zfs_err_to_be_err(g_zfs));
1427 	}
1428 
1429 	/* Set uuid property for the BE */
1430 	if (zfs_prop_set(zhp, BE_UUID_PROPERTY, uu_string) != 0) {
1431 		be_print_err(gettext("be_set_uuid: failed to "
1432 		    "set uuid property for BE: %s\n"),
1433 		    libzfs_error_description(g_zfs));
1434 		ret = zfs_err_to_be_err(g_zfs);
1435 	}
1436 
1437 	ZFS_CLOSE(zhp);
1438 
1439 	return (ret);
1440 }
1441 
1442 /*
1443  * Function:	be_get_uuid
1444  * Description:	This function gets the uuid string from a BE root
1445  *		dataset, parses it into internal format, and returns
1446  *		it the caller via a reference pointer passed in.
1447  *
1448  * Parameters:
1449  *		rootds - Root dataset of the BE to get the uuid from.
1450  *		uu - reference pointer to a uuid_t to return uuid in.
1451  * Return:
1452  *		be_errno_t - Failure
1453  *		BE_SUCCESS - Success
1454  * Scope:
1455  *		Semi-private (library wide use only)
1456  */
1457 int
be_get_uuid(const char * root_ds,uuid_t * uu)1458 be_get_uuid(const char *root_ds, uuid_t *uu)
1459 {
1460 	zfs_handle_t	*zhp = NULL;
1461 	nvlist_t	*userprops = NULL;
1462 	nvlist_t	*propname = NULL;
1463 	char		*uu_string = NULL;
1464 	int		ret = BE_SUCCESS;
1465 
1466 	/* Get handle to the BE's root dataset. */
1467 	if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
1468 		be_print_err(gettext("be_get_uuid: failed to "
1469 		    "open BE root dataset (%s): %s\n"), root_ds,
1470 		    libzfs_error_description(g_zfs));
1471 		return (zfs_err_to_be_err(g_zfs));
1472 	}
1473 
1474 	/* Get user properties for BE's root dataset */
1475 	if ((userprops = zfs_get_user_props(zhp)) == NULL) {
1476 		be_print_err(gettext("be_get_uuid: failed to "
1477 		    "get user properties for BE root dataset (%s): %s\n"),
1478 		    root_ds, libzfs_error_description(g_zfs));
1479 		ret = zfs_err_to_be_err(g_zfs);
1480 		goto done;
1481 	}
1482 
1483 	/* Get UUID string from BE's root dataset user properties */
1484 	if (nvlist_lookup_nvlist(userprops, BE_UUID_PROPERTY, &propname) != 0 ||
1485 	    nvlist_lookup_string(propname, ZPROP_VALUE, &uu_string) != 0) {
1486 		/*
1487 		 * This probably just means that the BE is simply too old
1488 		 * to have a uuid or that we haven't created a uuid for
1489 		 * this BE yet.
1490 		 */
1491 		be_print_err(gettext("be_get_uuid: failed to "
1492 		    "get uuid property from BE root dataset user "
1493 		    "properties.\n"));
1494 		ret = BE_ERR_NO_UUID;
1495 		goto done;
1496 	}
1497 	/* Parse uuid string into internal format */
1498 	if (uuid_parse(uu_string, *uu) != 0 || uuid_is_null(*uu)) {
1499 		be_print_err(gettext("be_get_uuid: failed to "
1500 		    "parse uuid\n"));
1501 		ret = BE_ERR_PARSE_UUID;
1502 		goto done;
1503 	}
1504 
1505 done:
1506 	ZFS_CLOSE(zhp);
1507 	return (ret);
1508 }
1509 
1510 /* ********************************************************************	*/
1511 /*			Private Functions				*/
1512 /* ********************************************************************	*/
1513 
1514 /*
1515  * Function:	_be_destroy
1516  * Description:	Destroy a BE and all of its children datasets and snapshots.
1517  *		This function is called for both global BEs and non-global BEs.
1518  *		The root dataset of either the global BE or non-global BE to be
1519  *		destroyed is passed in.
1520  * Parameters:
1521  *		root_ds - pointer to the name of the root dataset of the
1522  *			BE to destroy.
1523  *		dd - pointer to a be_destroy_data_t structure.
1524  *
1525  * Return:
1526  *		BE_SUCCESS - Success
1527  *		be_errno_t - Failure
1528  * Scope:
1529  *		Private
1530  */
1531 static int
_be_destroy(const char * root_ds,be_destroy_data_t * dd)1532 _be_destroy(const char *root_ds, be_destroy_data_t *dd)
1533 {
1534 	zfs_handle_t	*zhp = NULL;
1535 	char		origin[MAXPATHLEN];
1536 	char		parent[MAXPATHLEN];
1537 	char		*snap = NULL;
1538 	boolean_t	has_origin = B_FALSE;
1539 	int		ret = BE_SUCCESS;
1540 
1541 	/* Get handle to BE's root dataset */
1542 	if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) ==
1543 	    NULL) {
1544 		be_print_err(gettext("be_destroy: failed to "
1545 		    "open BE root dataset (%s): %s\n"), root_ds,
1546 		    libzfs_error_description(g_zfs));
1547 		return (zfs_err_to_be_err(g_zfs));
1548 	}
1549 
1550 	/*
1551 	 * Demote this BE in case it has dependent clones.  This call
1552 	 * will end up closing the zfs handle passed in whether it
1553 	 * succeeds or fails.
1554 	 */
1555 	if (be_demote_callback(zhp, NULL) != 0) {
1556 		be_print_err(gettext("be_destroy: "
1557 		    "failed to demote BE %s\n"), root_ds);
1558 		return (BE_ERR_DEMOTE);
1559 	}
1560 
1561 	/* Get handle to BE's root dataset */
1562 	if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) ==
1563 	    NULL) {
1564 		be_print_err(gettext("be_destroy: failed to "
1565 		    "open BE root dataset (%s): %s\n"), root_ds,
1566 		    libzfs_error_description(g_zfs));
1567 		return (zfs_err_to_be_err(g_zfs));
1568 	}
1569 
1570 	/*
1571 	 * Get the origin of this BE's root dataset.  This will be used
1572 	 * later to destroy the snapshots originally used to create this BE.
1573 	 */
1574 	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
1575 	    NULL, 0, B_FALSE) == 0) {
1576 		(void) strlcpy(parent, origin, sizeof (parent));
1577 		if (be_get_snap(parent, &snap) != BE_SUCCESS) {
1578 			ZFS_CLOSE(zhp);
1579 			be_print_err(gettext("be_destroy: failed to "
1580 			    "get snapshot name from origin %s\n"), origin);
1581 			return (BE_ERR_INVAL);
1582 		}
1583 		has_origin = B_TRUE;
1584 	}
1585 
1586 	/*
1587 	 * Destroy the BE's root and its hierarchical children.  This call
1588 	 * will end up closing the zfs handle passed in whether it succeeds
1589 	 * or fails.
1590 	 */
1591 	if (be_destroy_callback(zhp, dd) != 0) {
1592 		be_print_err(gettext("be_destroy: failed to "
1593 		    "destroy BE %s\n"), root_ds);
1594 		ret = zfs_err_to_be_err(g_zfs);
1595 		return (ret);
1596 	}
1597 
1598 	/* If BE has an origin */
1599 	if (has_origin) {
1600 
1601 		/*
1602 		 * If origin snapshot doesn't have any other
1603 		 * dependents, delete the origin.
1604 		 */
1605 		if ((zhp = zfs_open(g_zfs, origin, ZFS_TYPE_SNAPSHOT)) ==
1606 		    NULL) {
1607 			be_print_err(gettext("be_destroy: failed to "
1608 			    "open BE's origin (%s): %s\n"), origin,
1609 			    libzfs_error_description(g_zfs));
1610 			ret = zfs_err_to_be_err(g_zfs);
1611 			return (ret);
1612 		}
1613 
1614 		/* If origin has dependents, don't delete it. */
1615 		if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) != 0) {
1616 			ZFS_CLOSE(zhp);
1617 			return (ret);
1618 		}
1619 		ZFS_CLOSE(zhp);
1620 
1621 		/* Get handle to BE's parent's root dataset */
1622 		if ((zhp = zfs_open(g_zfs, parent, ZFS_TYPE_FILESYSTEM)) ==
1623 		    NULL) {
1624 			be_print_err(gettext("be_destroy: failed to "
1625 			    "open BE's parent root dataset (%s): %s\n"), parent,
1626 			    libzfs_error_description(g_zfs));
1627 			ret = zfs_err_to_be_err(g_zfs);
1628 			return (ret);
1629 		}
1630 
1631 		/* Destroy the snapshot origin used to create this BE. */
1632 		/*
1633 		 * The boolean set to B_FALSE and passed to zfs_destroy_snaps()
1634 		 * tells zfs to process and destroy the snapshots now.
1635 		 * Otherwise the call will potentially return where the
1636 		 * snapshot isn't actually destroyed yet, and ZFS is waiting
1637 		 * until all the references to the snapshot have been
1638 		 * released before actually destroying the snapshot.
1639 		 */
1640 		if (zfs_destroy_snaps(zhp, snap, B_FALSE) != 0) {
1641 			be_print_err(gettext("be_destroy: failed to "
1642 			    "destroy original snapshots used to create "
1643 			    "BE: %s\n"), libzfs_error_description(g_zfs));
1644 
1645 			/*
1646 			 * If a failure happened because a clone exists,
1647 			 * don't return a failure to the user.  Above, we're
1648 			 * only checking that the root dataset's origin
1649 			 * snapshot doesn't have dependent clones, but its
1650 			 * possible that a subordinate dataset origin snapshot
1651 			 * has a clone.  We really need to check for that
1652 			 * before trying to destroy the origin snapshot.
1653 			 */
1654 			if (libzfs_errno(g_zfs) != EZFS_EXISTS) {
1655 				ret = zfs_err_to_be_err(g_zfs);
1656 				ZFS_CLOSE(zhp);
1657 				return (ret);
1658 			}
1659 		}
1660 		ZFS_CLOSE(zhp);
1661 	}
1662 
1663 	return (ret);
1664 }
1665 
1666 /*
1667  * Function:	be_destroy_zones
1668  * Description:	Find valid zone's and call be_destroy_zone_roots to destroy its
1669  *		corresponding dataset and all of its children datasets
1670  *		and snapshots.
1671  * Parameters:
1672  *		be_name - name of global boot environment being destroyed
1673  *		be_root_ds - root dataset of global boot environment being
1674  *			destroyed.
1675  *		dd - be_destroy_data_t pointer
1676  * Return:
1677  *		BE_SUCCESS - Success
1678  *		be_errno_t - Failure
1679  * Scope:
1680  *		Private
1681  *
1682  * NOTES - Requires that the BE being deleted has no dependent BEs.  If it
1683  *	   does, the destroy will fail.
1684  */
1685 static int
be_destroy_zones(char * be_name,char * be_root_ds,be_destroy_data_t * dd)1686 be_destroy_zones(char *be_name, char *be_root_ds, be_destroy_data_t *dd)
1687 {
1688 	int		i;
1689 	int		ret = BE_SUCCESS;
1690 	int		force_umnt = BE_UNMOUNT_FLAG_NULL;
1691 	char		*zonepath = NULL;
1692 	char		*zonename = NULL;
1693 	char		*zonepath_ds = NULL;
1694 	char		*mp = NULL;
1695 	zoneList_t	zlist = NULL;
1696 	zoneBrandList_t	*brands = NULL;
1697 	zfs_handle_t	*zhp = NULL;
1698 
1699 	/* If zones are not implemented, then get out. */
1700 	if (!z_zones_are_implemented()) {
1701 		return (BE_SUCCESS);
1702 	}
1703 
1704 	/* Get list of supported brands */
1705 	if ((brands = be_get_supported_brandlist()) == NULL) {
1706 		be_print_err(gettext("be_destroy_zones: "
1707 		    "no supported brands\n"));
1708 		return (BE_SUCCESS);
1709 	}
1710 
1711 	/* Get handle to BE's root dataset */
1712 	if ((zhp = zfs_open(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) ==
1713 	    NULL) {
1714 		be_print_err(gettext("be_destroy_zones: failed to "
1715 		    "open BE root dataset (%s): %s\n"), be_root_ds,
1716 		    libzfs_error_description(g_zfs));
1717 		z_free_brand_list(brands);
1718 		return (zfs_err_to_be_err(g_zfs));
1719 	}
1720 
1721 	/*
1722 	 * If the global BE is not mounted, we must mount it here to
1723 	 * gather data about the non-global zones in it.
1724 	 */
1725 	if (!zfs_is_mounted(zhp, &mp)) {
1726 		if ((ret = _be_mount(be_name, &mp,
1727 		    BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
1728 			be_print_err(gettext("be_destroy_zones: failed to "
1729 			    "mount the BE (%s) for zones processing.\n"),
1730 			    be_name);
1731 			ZFS_CLOSE(zhp);
1732 			z_free_brand_list(brands);
1733 			return (ret);
1734 		}
1735 	}
1736 	ZFS_CLOSE(zhp);
1737 
1738 	z_set_zone_root(mp);
1739 	free(mp);
1740 
1741 	/* Get list of supported zones. */
1742 	if ((zlist = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) {
1743 		z_free_brand_list(brands);
1744 		return (BE_SUCCESS);
1745 	}
1746 
1747 	/* Unmount the BE before destroying the zones in it. */
1748 	if (dd->force_unmount)
1749 		force_umnt = BE_UNMOUNT_FLAG_FORCE;
1750 	if ((ret = _be_unmount(be_name, force_umnt)) != BE_SUCCESS) {
1751 		be_print_err(gettext("be_destroy_zones: failed to "
1752 		    "unmount the BE (%s)\n"), be_name);
1753 		goto done;
1754 	}
1755 
1756 	/* Iterate through the zones and destroy them. */
1757 	for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) {
1758 
1759 		/* Skip zones that aren't at least installed */
1760 		if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED)
1761 			continue;
1762 
1763 		zonepath = z_zlist_get_zonepath(zlist, i);
1764 
1765 		/*
1766 		 * Get the dataset of this zonepath.  If its not
1767 		 * a dataset, skip it.
1768 		 */
1769 		if ((zonepath_ds = be_get_ds_from_dir(zonepath)) == NULL)
1770 			continue;
1771 
1772 		/*
1773 		 * Check if this zone is supported based on the
1774 		 * dataset of its zonepath.
1775 		 */
1776 		if (!be_zone_supported(zonepath_ds)) {
1777 			free(zonepath_ds);
1778 			continue;
1779 		}
1780 
1781 		/* Find the zone BE root datasets for this zone. */
1782 		if ((ret = be_destroy_zone_roots(zonepath_ds, dd))
1783 		    != BE_SUCCESS) {
1784 			be_print_err(gettext("be_destroy_zones: failed to "
1785 			    "find and destroy zone roots for zone %s\n"),
1786 			    zonename);
1787 			free(zonepath_ds);
1788 			goto done;
1789 		}
1790 		free(zonepath_ds);
1791 	}
1792 
1793 done:
1794 	z_free_brand_list(brands);
1795 	z_free_zone_list(zlist);
1796 
1797 	return (ret);
1798 }
1799 
1800 /*
1801  * Function:	be_destroy_zone_roots
1802  * Description:	This function will open the zone's root container dataset
1803  *		and iterate the datasets within, looking for roots that
1804  *		belong to the given global BE and destroying them.
1805  *		If no other zone roots remain in the zone's root container
1806  *		dataset, the function will destroy it and the zone's
1807  *		zonepath dataset as well.
1808  * Parameters:
1809  *		zonepath_ds - pointer to zone's zonepath dataset.
1810  *		dd - pointer to a linked destroy data.
1811  * Returns:
1812  *		BE_SUCCESS - Success
1813  *		be_errno_t - Failure
1814  * Scope:
1815  *		Private
1816  */
1817 static int
be_destroy_zone_roots(char * zonepath_ds,be_destroy_data_t * dd)1818 be_destroy_zone_roots(char *zonepath_ds, be_destroy_data_t *dd)
1819 {
1820 	zfs_handle_t	*zhp;
1821 	char		zone_container_ds[MAXPATHLEN];
1822 	int		ret = BE_SUCCESS;
1823 
1824 	/* Generate string for the root container dataset for this zone. */
1825 	if ((ret = be_make_container_ds(zonepath_ds, zone_container_ds,
1826 	    sizeof (zone_container_ds))) != BE_SUCCESS) {
1827 		be_print_err(gettext("%s: failed to get BE container dataset "
1828 		    "for %s\n"), __func__, zonepath_ds);
1829 		return (ret);
1830 	}
1831 
1832 	/* Get handle to this zone's root container dataset. */
1833 	if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM))
1834 	    == NULL) {
1835 		be_print_err(gettext("be_destroy_zone_roots: failed to "
1836 		    "open zone root container dataset (%s): %s\n"),
1837 		    zone_container_ds, libzfs_error_description(g_zfs));
1838 		return (zfs_err_to_be_err(g_zfs));
1839 	}
1840 
1841 	/*
1842 	 * Iterate through all of this zone's BEs, destroying the ones
1843 	 * that belong to the parent global BE.
1844 	 */
1845 	if ((ret = zfs_iter_filesystems(zhp, be_destroy_zone_roots_callback,
1846 	    dd)) != 0) {
1847 		be_print_err(gettext("be_destroy_zone_roots: failed to "
1848 		    "destroy zone roots under zonepath dataset %s: %s\n"),
1849 		    zonepath_ds, libzfs_error_description(g_zfs));
1850 		ZFS_CLOSE(zhp);
1851 		return (ret);
1852 	}
1853 	ZFS_CLOSE(zhp);
1854 
1855 	/* Get handle to this zone's root container dataset. */
1856 	if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM))
1857 	    == NULL) {
1858 		be_print_err(gettext("be_destroy_zone_roots: failed to "
1859 		    "open zone root container dataset (%s): %s\n"),
1860 		    zone_container_ds, libzfs_error_description(g_zfs));
1861 		return (zfs_err_to_be_err(g_zfs));
1862 	}
1863 
1864 	/*
1865 	 * If there are no more zone roots in this zone's root container,
1866 	 * dataset, destroy it and the zonepath dataset as well.
1867 	 */
1868 	if (zfs_iter_filesystems(zhp, be_zone_root_exists_callback, NULL)
1869 	    == 0) {
1870 		/* Destroy the zone root container dataset */
1871 		if (zfs_unmount(zhp, NULL, MS_FORCE) != 0 ||
1872 		    zfs_destroy(zhp, B_FALSE) != 0) {
1873 			be_print_err(gettext("be_destroy_zone_roots: failed to "
1874 			    "destroy zone root container dataset (%s): %s\n"),
1875 			    zone_container_ds, libzfs_error_description(g_zfs));
1876 			goto done;
1877 		}
1878 		ZFS_CLOSE(zhp);
1879 
1880 		/* Get handle to zonepath dataset */
1881 		if ((zhp = zfs_open(g_zfs, zonepath_ds, ZFS_TYPE_FILESYSTEM))
1882 		    == NULL) {
1883 			be_print_err(gettext("be_destroy_zone_roots: failed to "
1884 			    "open zonepath dataset (%s): %s\n"),
1885 			    zonepath_ds, libzfs_error_description(g_zfs));
1886 			goto done;
1887 		}
1888 
1889 		/* Destroy zonepath dataset */
1890 		if (zfs_unmount(zhp, NULL, MS_FORCE) != 0 ||
1891 		    zfs_destroy(zhp, B_FALSE) != 0) {
1892 			be_print_err(gettext("be_destroy_zone_roots: "
1893 			    "failed to destroy zonepath dataest %s: %s\n"),
1894 			    zonepath_ds, libzfs_error_description(g_zfs));
1895 			goto done;
1896 		}
1897 	}
1898 
1899 done:
1900 	ZFS_CLOSE(zhp);
1901 	return (ret);
1902 }
1903 
1904 /*
1905  * Function:	be_destroy_zone_roots_callback
1906  * Description: This function is used as a callback to iterate over all of
1907  *		a zone's root datasets, finding the one's that
1908  *		correspond to the current BE. The name's
1909  *		of the zone root datasets are then destroyed by _be_destroy().
1910  * Parameters:
1911  *		zhp - zfs_handle_t pointer to current dataset being processed
1912  *		data - be_destroy_data_t pointer
1913  * Returns:
1914  *		0 - Success
1915  *		be_errno_t - Failure
1916  * Scope:
1917  *		Private
1918  */
1919 static int
be_destroy_zone_roots_callback(zfs_handle_t * zhp,void * data)1920 be_destroy_zone_roots_callback(zfs_handle_t *zhp, void *data)
1921 {
1922 	be_destroy_data_t	*dd = data;
1923 	uuid_t			parent_uuid = { 0 };
1924 	int			ret = 0;
1925 
1926 	if (be_zone_get_parent_uuid(zfs_get_name(zhp), &parent_uuid)
1927 	    != BE_SUCCESS) {
1928 		be_print_err(gettext("be_destroy_zone_roots_callback: "
1929 		    "could not get parentuuid for zone root dataset %s\n"),
1930 		    zfs_get_name(zhp));
1931 		ZFS_CLOSE(zhp);
1932 		return (0);
1933 	}
1934 
1935 	if (uuid_compare(dd->gz_be_uuid, parent_uuid) == 0) {
1936 		/*
1937 		 * Found a zone root dataset belonging to the parent
1938 		 * BE being destroyed.  Destroy this zone BE.
1939 		 */
1940 		if ((ret = _be_destroy(zfs_get_name(zhp), dd)) != BE_SUCCESS) {
1941 			be_print_err(gettext("be_destroy_zone_root_callback: "
1942 			    "failed to destroy zone root %s\n"),
1943 			    zfs_get_name(zhp));
1944 			ZFS_CLOSE(zhp);
1945 			return (ret);
1946 		}
1947 	}
1948 	ZFS_CLOSE(zhp);
1949 
1950 	return (ret);
1951 }
1952 
1953 /*
1954  * Function:	be_copy_zones
1955  * Description:	Find valid zones and clone them to create their
1956  *		corresponding datasets for the BE being created.
1957  * Parameters:
1958  *		obe_name - name of source global BE being copied.
1959  *		obe_root_ds - root dataset of source global BE being copied.
1960  *		nbe_root_ds - root dataset of target global BE.
1961  * Return:
1962  *		BE_SUCCESS - Success
1963  *		be_errno_t - Failure
1964  * Scope:
1965  *		Private
1966  */
1967 static int
be_copy_zones(char * obe_name,char * obe_root_ds,char * nbe_root_ds)1968 be_copy_zones(char *obe_name, char *obe_root_ds, char *nbe_root_ds)
1969 {
1970 	int		i, num_retries;
1971 	int		ret = BE_SUCCESS;
1972 	int		iret = 0;
1973 	char		*zonename = NULL;
1974 	char		*zonepath = NULL;
1975 	char		*zone_be_name = NULL;
1976 	char		*temp_mntpt = NULL;
1977 	char		*new_zone_be_name = NULL;
1978 	char		zoneroot[MAXPATHLEN];
1979 	char		zoneroot_ds[MAXPATHLEN];
1980 	char		zone_container_ds[MAXPATHLEN];
1981 	char		new_zoneroot_ds[MAXPATHLEN];
1982 	char		ss[MAXPATHLEN];
1983 	uuid_t		uu = { 0 };
1984 	char		uu_string[UUID_PRINTABLE_STRING_LENGTH] = { 0 };
1985 	be_transaction_data_t bt = { 0 };
1986 	zfs_handle_t	*obe_zhp = NULL;
1987 	zfs_handle_t	*nbe_zhp = NULL;
1988 	zfs_handle_t	*z_zhp = NULL;
1989 	zoneList_t	zlist = NULL;
1990 	zoneBrandList_t	*brands = NULL;
1991 	boolean_t	mounted_here = B_FALSE;
1992 	char		*snap_name = NULL;
1993 
1994 	/* If zones are not implemented, then get out. */
1995 	if (!z_zones_are_implemented()) {
1996 		return (BE_SUCCESS);
1997 	}
1998 
1999 	/* Get list of supported brands */
2000 	if ((brands = be_get_supported_brandlist()) == NULL) {
2001 		be_print_err(gettext("be_copy_zones: "
2002 		    "no supported brands\n"));
2003 		return (BE_SUCCESS);
2004 	}
2005 
2006 	/* Get handle to origin BE's root dataset */
2007 	if ((obe_zhp = zfs_open(g_zfs, obe_root_ds, ZFS_TYPE_FILESYSTEM))
2008 	    == NULL) {
2009 		be_print_err(gettext("be_copy_zones: failed to open "
2010 		    "the origin BE root dataset (%s) for zones processing: "
2011 		    "%s\n"), obe_root_ds, libzfs_error_description(g_zfs));
2012 		return (zfs_err_to_be_err(g_zfs));
2013 	}
2014 
2015 	/* Get handle to newly cloned BE's root dataset */
2016 	if ((nbe_zhp = zfs_open(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM))
2017 	    == NULL) {
2018 		be_print_err(gettext("be_copy_zones: failed to open "
2019 		    "the new BE root dataset (%s): %s\n"), nbe_root_ds,
2020 		    libzfs_error_description(g_zfs));
2021 		ZFS_CLOSE(obe_zhp);
2022 		return (zfs_err_to_be_err(g_zfs));
2023 	}
2024 
2025 	/* Get the uuid of the newly cloned parent BE. */
2026 	if (be_get_uuid(zfs_get_name(nbe_zhp), &uu) != BE_SUCCESS) {
2027 		be_print_err(gettext("be_copy_zones: "
2028 		    "failed to get uuid for BE root "
2029 		    "dataset %s\n"), zfs_get_name(nbe_zhp));
2030 		ZFS_CLOSE(nbe_zhp);
2031 		goto done;
2032 	}
2033 	ZFS_CLOSE(nbe_zhp);
2034 	uuid_unparse(uu, uu_string);
2035 
2036 	/*
2037 	 * If the origin BE is not mounted, we must mount it here to
2038 	 * gather data about the non-global zones in it.
2039 	 */
2040 	if (!zfs_is_mounted(obe_zhp, &temp_mntpt)) {
2041 		if ((ret = _be_mount(obe_name, &temp_mntpt,
2042 		    BE_MOUNT_FLAG_NULL)) != BE_SUCCESS) {
2043 			be_print_err(gettext("be_copy_zones: failed to "
2044 			    "mount the BE (%s) for zones procesing.\n"),
2045 			    obe_name);
2046 			goto done;
2047 		}
2048 		mounted_here = B_TRUE;
2049 	}
2050 
2051 	z_set_zone_root(temp_mntpt);
2052 
2053 	/* Get list of supported zones. */
2054 	if ((zlist = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) {
2055 		ret = BE_SUCCESS;
2056 		goto done;
2057 	}
2058 
2059 	for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) {
2060 
2061 		be_fs_list_data_t	fld = { 0 };
2062 		char			zonepath_ds[MAXPATHLEN];
2063 		char			*ds = NULL;
2064 
2065 		/* Get zonepath of zone */
2066 		zonepath = z_zlist_get_zonepath(zlist, i);
2067 
2068 		/* Skip zones that aren't at least installed */
2069 		if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED)
2070 			continue;
2071 
2072 		/*
2073 		 * Get the dataset of this zonepath.  If its not
2074 		 * a dataset, skip it.
2075 		 */
2076 		if ((ds = be_get_ds_from_dir(zonepath)) == NULL)
2077 			continue;
2078 
2079 		(void) strlcpy(zonepath_ds, ds, sizeof (zonepath_ds));
2080 		free(ds);
2081 		ds = NULL;
2082 
2083 		/* Get zoneroot directory */
2084 		be_make_zoneroot(zonepath, zoneroot, sizeof (zoneroot));
2085 
2086 		/* If zonepath dataset not supported, skip it. */
2087 		if (!be_zone_supported(zonepath_ds)) {
2088 			continue;
2089 		}
2090 
2091 		if ((ret = be_find_active_zone_root(obe_zhp, zonepath_ds,
2092 		    zoneroot_ds, sizeof (zoneroot_ds))) != BE_SUCCESS) {
2093 			be_print_err(gettext("be_copy_zones: "
2094 			    "failed to find active zone root for zone %s "
2095 			    "in BE %s\n"), zonename, obe_name);
2096 			goto done;
2097 		}
2098 
2099 		if ((ret = be_make_container_ds(zonepath_ds, zone_container_ds,
2100 		    sizeof (zone_container_ds))) != BE_SUCCESS) {
2101 			be_print_err(gettext("%s: failed to get BE container "
2102 			    "dataset for %s\n"), __func__, zonepath_ds);
2103 			goto done;
2104 		}
2105 
2106 		if ((z_zhp = zfs_open(g_zfs, zoneroot_ds,
2107 		    ZFS_TYPE_FILESYSTEM)) == NULL) {
2108 			be_print_err(gettext("be_copy_zones: "
2109 			    "failed to open zone root dataset (%s): %s\n"),
2110 			    zoneroot_ds, libzfs_error_description(g_zfs));
2111 			ret = zfs_err_to_be_err(g_zfs);
2112 			goto done;
2113 		}
2114 
2115 		zone_be_name =
2116 		    be_get_zone_be_name(zoneroot_ds, zone_container_ds);
2117 
2118 		if ((new_zone_be_name = be_auto_zone_be_name(zone_container_ds,
2119 		    zone_be_name)) == NULL) {
2120 			be_print_err(gettext("be_copy_zones: failed "
2121 			    "to generate auto name for zone BE.\n"));
2122 			ret = BE_ERR_AUTONAME;
2123 			goto done;
2124 		}
2125 
2126 		if ((snap_name = be_auto_snap_name()) == NULL) {
2127 			be_print_err(gettext("be_copy_zones: failed to "
2128 			    "generate snapshot name for zone BE.\n"));
2129 			ret = BE_ERR_AUTONAME;
2130 			goto done;
2131 		}
2132 
2133 		(void) snprintf(ss, sizeof (ss), "%s@%s", zoneroot_ds,
2134 		    snap_name);
2135 
2136 		if (zfs_snapshot(g_zfs, ss, B_TRUE, NULL) != 0) {
2137 			be_print_err(gettext("be_copy_zones: "
2138 			    "failed to snapshot zone BE (%s): %s\n"),
2139 			    ss, libzfs_error_description(g_zfs));
2140 			if (libzfs_errno(g_zfs) == EZFS_EXISTS)
2141 				ret = BE_ERR_ZONE_SS_EXISTS;
2142 			else
2143 				ret = zfs_err_to_be_err(g_zfs);
2144 
2145 			goto done;
2146 		}
2147 
2148 		(void) snprintf(new_zoneroot_ds, sizeof (new_zoneroot_ds),
2149 		    "%s/%s", zone_container_ds, new_zone_be_name);
2150 
2151 		bt.obe_name = zone_be_name;
2152 		bt.obe_root_ds = zoneroot_ds;
2153 		bt.obe_snap_name = snap_name;
2154 		bt.obe_altroot = temp_mntpt;
2155 		bt.nbe_name = new_zone_be_name;
2156 		bt.nbe_root_ds = new_zoneroot_ds;
2157 
2158 		if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) {
2159 			be_print_err(gettext("be_copy_zones: "
2160 			    "internal error: out of memory\n"));
2161 			ret = BE_ERR_NOMEM;
2162 			goto done;
2163 		}
2164 
2165 		/*
2166 		 * The call to be_clone_fs_callback always closes the
2167 		 * zfs_handle so there's no need to close z_zhp.
2168 		 */
2169 		if ((iret = be_clone_fs_callback(z_zhp, &bt)) != 0) {
2170 			z_zhp = NULL;
2171 			if (iret != BE_ERR_BE_EXISTS) {
2172 				be_print_err(gettext("be_copy_zones: "
2173 				    "failed to create zone BE clone for new "
2174 				    "zone BE %s\n"), new_zone_be_name);
2175 				ret = iret;
2176 				nvlist_free(bt.nbe_zfs_props);
2177 				goto done;
2178 			}
2179 			/*
2180 			 * We failed to create the new zone BE because a zone
2181 			 * BE with the auto-name we generated above has since
2182 			 * come into existence. Regenerate a new auto-name
2183 			 * and retry.
2184 			 */
2185 			for (num_retries = 1;
2186 			    num_retries < BE_AUTO_NAME_MAX_TRY;
2187 			    num_retries++) {
2188 
2189 				/* Sleep 1 before retrying */
2190 				(void) sleep(1);
2191 
2192 				/* Generate new auto zone BE name */
2193 				free(new_zone_be_name);
2194 				if ((new_zone_be_name = be_auto_zone_be_name(
2195 				    zone_container_ds,
2196 				    zone_be_name)) == NULL) {
2197 					be_print_err(gettext("be_copy_zones: "
2198 					    "failed to generate auto name "
2199 					    "for zone BE.\n"));
2200 					ret = BE_ERR_AUTONAME;
2201 					nvlist_free(bt.nbe_zfs_props);
2202 					goto done;
2203 				}
2204 
2205 				(void) snprintf(new_zoneroot_ds,
2206 				    sizeof (new_zoneroot_ds),
2207 				    "%s/%s", zone_container_ds,
2208 				    new_zone_be_name);
2209 				bt.nbe_name = new_zone_be_name;
2210 				bt.nbe_root_ds = new_zoneroot_ds;
2211 
2212 				/*
2213 				 * Get handle to original zone BE's root
2214 				 * dataset.
2215 				 */
2216 				if ((z_zhp = zfs_open(g_zfs, zoneroot_ds,
2217 				    ZFS_TYPE_FILESYSTEM)) == NULL) {
2218 					be_print_err(gettext("be_copy_zones: "
2219 					    "failed to open zone root "
2220 					    "dataset (%s): %s\n"),
2221 					    zoneroot_ds,
2222 					    libzfs_error_description(g_zfs));
2223 					ret = zfs_err_to_be_err(g_zfs);
2224 					nvlist_free(bt.nbe_zfs_props);
2225 					goto done;
2226 				}
2227 
2228 				/*
2229 				 * Try to clone the zone BE again. This
2230 				 * call will end up closing the zfs
2231 				 * handle passed in whether it
2232 				 * succeeds or fails.
2233 				 */
2234 				iret = be_clone_fs_callback(z_zhp, &bt);
2235 				z_zhp = NULL;
2236 				if (iret == 0) {
2237 					break;
2238 				} else if (iret != BE_ERR_BE_EXISTS) {
2239 					be_print_err(gettext("be_copy_zones: "
2240 					    "failed to create zone BE clone "
2241 					    "for new zone BE %s\n"),
2242 					    new_zone_be_name);
2243 					ret = iret;
2244 					nvlist_free(bt.nbe_zfs_props);
2245 					goto done;
2246 				}
2247 			}
2248 			/*
2249 			 * If we've exhausted the maximum number of
2250 			 * tries, free the auto zone BE name and return
2251 			 * error.
2252 			 */
2253 			if (num_retries == BE_AUTO_NAME_MAX_TRY) {
2254 				be_print_err(gettext("be_copy_zones: failed "
2255 				    "to create a unique auto zone BE name\n"));
2256 				free(bt.nbe_name);
2257 				bt.nbe_name = NULL;
2258 				ret = BE_ERR_AUTONAME;
2259 				nvlist_free(bt.nbe_zfs_props);
2260 				goto done;
2261 			}
2262 		}
2263 
2264 		nvlist_free(bt.nbe_zfs_props);
2265 
2266 		z_zhp = NULL;
2267 
2268 		if ((z_zhp = zfs_open(g_zfs, new_zoneroot_ds,
2269 		    ZFS_TYPE_FILESYSTEM)) == NULL) {
2270 			be_print_err(gettext("be_copy_zones: "
2271 			    "failed to open the new zone BE root dataset "
2272 			    "(%s): %s\n"), new_zoneroot_ds,
2273 			    libzfs_error_description(g_zfs));
2274 			ret = zfs_err_to_be_err(g_zfs);
2275 			goto done;
2276 		}
2277 
2278 		if (zfs_prop_set(z_zhp, BE_ZONE_PARENTBE_PROPERTY,
2279 		    uu_string) != 0) {
2280 			be_print_err(gettext("be_copy_zones: "
2281 			    "failed to set parentbe property\n"));
2282 			ZFS_CLOSE(z_zhp);
2283 			ret = zfs_err_to_be_err(g_zfs);
2284 			goto done;
2285 		}
2286 
2287 		if (zfs_prop_set(z_zhp, BE_ZONE_ACTIVE_PROPERTY, "on") != 0) {
2288 			be_print_err(gettext("be_copy_zones: "
2289 			    "failed to set active property\n"));
2290 			ZFS_CLOSE(z_zhp);
2291 			ret = zfs_err_to_be_err(g_zfs);
2292 			goto done;
2293 		}
2294 
2295 		/*
2296 		 * Generate a list of file systems from the original
2297 		 * zone BE that are legacy mounted.  We use this list
2298 		 * to determine which entries in the vfstab we need to
2299 		 * update for the new zone BE we've just created.
2300 		 */
2301 		if ((ret = be_get_legacy_fs(obe_name, obe_root_ds,
2302 		    zoneroot_ds, zoneroot, &fld)) != BE_SUCCESS) {
2303 			be_print_err(gettext("be_copy_zones: "
2304 			    "failed to get legacy mounted file system "
2305 			    "list for zone %s\n"), zonename);
2306 			ZFS_CLOSE(z_zhp);
2307 			goto done;
2308 		}
2309 
2310 		/*
2311 		 * Update new zone BE's vfstab.
2312 		 */
2313 		if ((ret = be_update_zone_vfstab(z_zhp, bt.nbe_name,
2314 		    zonepath_ds, zonepath_ds, &fld)) != BE_SUCCESS) {
2315 			be_print_err(gettext("be_copy_zones: "
2316 			    "failed to update new BE's vfstab (%s)\n"),
2317 			    bt.nbe_name);
2318 			ZFS_CLOSE(z_zhp);
2319 			be_free_fs_list(&fld);
2320 			goto done;
2321 		}
2322 
2323 		be_free_fs_list(&fld);
2324 		ZFS_CLOSE(z_zhp);
2325 	}
2326 
2327 done:
2328 	free(snap_name);
2329 	if (brands != NULL)
2330 		z_free_brand_list(brands);
2331 	if (zlist != NULL)
2332 		z_free_zone_list(zlist);
2333 
2334 	if (mounted_here)
2335 		(void) _be_unmount(obe_name, 0);
2336 
2337 	ZFS_CLOSE(obe_zhp);
2338 	return (ret);
2339 }
2340 
2341 /*
2342  * Function:	be_clone_fs_callback
2343  * Description:	Callback function used to iterate through a BE's filesystems
2344  *		to clone them for the new BE.
2345  * Parameters:
2346  *		zhp - zfs_handle_t pointer for the filesystem being processed.
2347  *		data - be_transaction_data_t pointer providing information
2348  *			about original BE and new BE.
2349  * Return:
2350  *		0 - Success
2351  *		be_errno_t - Failure
2352  * Scope:
2353  *		Private
2354  */
2355 static int
be_clone_fs_callback(zfs_handle_t * zhp,void * data)2356 be_clone_fs_callback(zfs_handle_t *zhp, void *data)
2357 {
2358 	be_transaction_data_t	*bt = data;
2359 	zfs_handle_t	*zhp_ss = NULL;
2360 	char		prop_buf[MAXPATHLEN];
2361 	char		zhp_name[ZFS_MAX_DATASET_NAME_LEN];
2362 	char		clone_ds[MAXPATHLEN];
2363 	char		ss[MAXPATHLEN];
2364 	int		ret = 0;
2365 
2366 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop_buf,
2367 	    ZFS_MAXPROPLEN, NULL, NULL, 0, B_FALSE) != 0) {
2368 		be_print_err(gettext("be_clone_fs_callback: "
2369 		    "failed to get dataset mountpoint (%s): %s\n"),
2370 		    zfs_get_name(zhp), libzfs_error_description(g_zfs));
2371 		ret = zfs_err_to_be_err(g_zfs);
2372 		ZFS_CLOSE(zhp);
2373 		return (ret);
2374 	}
2375 
2376 	if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) != 0 &&
2377 	    strcmp(prop_buf, "legacy") != 0) {
2378 		/*
2379 		 * Since zfs can't currently handle setting the
2380 		 * mountpoint for a zoned dataset we'll have to skip
2381 		 * this dataset. This is because the mountpoint is not
2382 		 * set to "legacy".
2383 		 */
2384 		goto zoned;
2385 	}
2386 	/*
2387 	 * Get a copy of the dataset name from the zfs handle
2388 	 */
2389 	(void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name));
2390 
2391 	/*
2392 	 * Get the clone dataset name and prepare the zfs properties for it.
2393 	 */
2394 	if ((ret = be_prep_clone_send_fs(zhp, bt, clone_ds,
2395 	    sizeof (clone_ds))) != BE_SUCCESS) {
2396 		ZFS_CLOSE(zhp);
2397 		return (ret);
2398 	}
2399 
2400 	/*
2401 	 * Generate the name of the snapshot to use.
2402 	 */
2403 	(void) snprintf(ss, sizeof (ss), "%s@%s", zhp_name,
2404 	    bt->obe_snap_name);
2405 
2406 	/*
2407 	 * Get handle to snapshot.
2408 	 */
2409 	if ((zhp_ss = zfs_open(g_zfs, ss, ZFS_TYPE_SNAPSHOT)) == NULL) {
2410 		be_print_err(gettext("be_clone_fs_callback: "
2411 		    "failed to get handle to snapshot (%s): %s\n"), ss,
2412 		    libzfs_error_description(g_zfs));
2413 		ret = zfs_err_to_be_err(g_zfs);
2414 		ZFS_CLOSE(zhp);
2415 		return (ret);
2416 	}
2417 
2418 	/*
2419 	 * Clone the dataset.
2420 	 */
2421 	if (zfs_clone(zhp_ss, clone_ds, bt->nbe_zfs_props) != 0) {
2422 		be_print_err(gettext("be_clone_fs_callback: "
2423 		    "failed to create clone dataset (%s): %s\n"),
2424 		    clone_ds, libzfs_error_description(g_zfs));
2425 
2426 		ZFS_CLOSE(zhp_ss);
2427 		ZFS_CLOSE(zhp);
2428 
2429 		return (zfs_err_to_be_err(g_zfs));
2430 	}
2431 
2432 	ZFS_CLOSE(zhp_ss);
2433 
2434 zoned:
2435 	/*
2436 	 * Iterate through zhp's children datasets (if any)
2437 	 * and clone them accordingly.
2438 	 */
2439 	if ((ret = zfs_iter_filesystems(zhp, be_clone_fs_callback, bt)) != 0) {
2440 		/*
2441 		 * Error occurred while processing a child dataset.
2442 		 * Destroy this dataset and return error.
2443 		 */
2444 		zfs_handle_t	*d_zhp = NULL;
2445 
2446 		ZFS_CLOSE(zhp);
2447 
2448 		if ((d_zhp = zfs_open(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM))
2449 		    == NULL) {
2450 			return (ret);
2451 		}
2452 
2453 		(void) zfs_destroy(d_zhp, B_FALSE);
2454 		ZFS_CLOSE(d_zhp);
2455 		return (ret);
2456 	}
2457 
2458 	ZFS_CLOSE(zhp);
2459 	return (0);
2460 }
2461 
2462 /*
2463  * Function:	be_send_fs_callback
2464  * Description: Callback function used to iterate through a BE's filesystems
2465  *		to copy them for the new BE.
2466  * Parameters:
2467  *		zhp - zfs_handle_t pointer for the filesystem being processed.
2468  *		data - be_transaction_data_t pointer providing information
2469  *			about original BE and new BE.
2470  * Return:
2471  *		0 - Success
2472  *		be_errnot_t - Failure
2473  * Scope:
2474  *		Private
2475  */
2476 static int
be_send_fs_callback(zfs_handle_t * zhp,void * data)2477 be_send_fs_callback(zfs_handle_t *zhp, void *data)
2478 {
2479 	be_transaction_data_t	*bt = data;
2480 	recvflags_t	flags = { 0 };
2481 	char		zhp_name[ZFS_MAX_DATASET_NAME_LEN];
2482 	char		clone_ds[MAXPATHLEN];
2483 	sendflags_t	send_flags = { 0 };
2484 	int		pid, status, retval;
2485 	int		srpipe[2];
2486 	int		ret = 0;
2487 
2488 	/*
2489 	 * Get a copy of the dataset name from the zfs handle
2490 	 */
2491 	(void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name));
2492 
2493 	/*
2494 	 * Get the clone dataset name and prepare the zfs properties for it.
2495 	 */
2496 	if ((ret = be_prep_clone_send_fs(zhp, bt, clone_ds,
2497 	    sizeof (clone_ds))) != BE_SUCCESS) {
2498 		ZFS_CLOSE(zhp);
2499 		return (ret);
2500 	}
2501 
2502 	/*
2503 	 * Create the new dataset.
2504 	 */
2505 	if (zfs_create(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM, bt->nbe_zfs_props)
2506 	    != 0) {
2507 		be_print_err(gettext("be_send_fs_callback: "
2508 		    "failed to create new dataset '%s': %s\n"),
2509 		    clone_ds, libzfs_error_description(g_zfs));
2510 		ret = zfs_err_to_be_err(g_zfs);
2511 		ZFS_CLOSE(zhp);
2512 		return (ret);
2513 	}
2514 
2515 	/*
2516 	 * Destination file system is already created
2517 	 * hence we need to set the force flag on
2518 	 */
2519 	flags.force = B_TRUE;
2520 
2521 	/*
2522 	 * Initiate the pipe to be used for the send and recv
2523 	 */
2524 	if (pipe(srpipe) != 0) {
2525 		int err = errno;
2526 		be_print_err(gettext("be_send_fs_callback: failed to "
2527 		    "open pipe\n"));
2528 		ZFS_CLOSE(zhp);
2529 		return (errno_to_be_err(err));
2530 	}
2531 
2532 	/*
2533 	 * Fork off a child to send the dataset
2534 	 */
2535 	if ((pid = fork()) == -1) {
2536 		int err = errno;
2537 		be_print_err(gettext("be_send_fs_callback: failed to fork\n"));
2538 		(void) close(srpipe[0]);
2539 		(void) close(srpipe[1]);
2540 		ZFS_CLOSE(zhp);
2541 		return (errno_to_be_err(err));
2542 	} else if (pid == 0) { /* child process */
2543 		(void) close(srpipe[0]);
2544 
2545 		/* Send dataset */
2546 		if (zfs_send(zhp, NULL, bt->obe_snap_name, &send_flags,
2547 		    srpipe[1], NULL, NULL, NULL) != 0) {
2548 			_exit(1);
2549 		}
2550 		ZFS_CLOSE(zhp);
2551 
2552 		_exit(0);
2553 	}
2554 
2555 	(void) close(srpipe[1]);
2556 
2557 	/* Receive dataset */
2558 	if (zfs_receive(g_zfs, clone_ds, NULL, &flags, srpipe[0], NULL) != 0) {
2559 		be_print_err(gettext("be_send_fs_callback: failed to "
2560 		    "recv dataset (%s)\n"), clone_ds);
2561 	}
2562 	(void) close(srpipe[0]);
2563 
2564 	/* wait for child to exit */
2565 	do {
2566 		retval = waitpid(pid, &status, 0);
2567 		if (retval == -1) {
2568 			status = 0;
2569 		}
2570 	} while (retval != pid);
2571 
2572 	if (WEXITSTATUS(status) != 0) {
2573 		be_print_err(gettext("be_send_fs_callback: failed to "
2574 		    "send dataset (%s)\n"), zhp_name);
2575 		ZFS_CLOSE(zhp);
2576 		return (BE_ERR_ZFS);
2577 	}
2578 
2579 
2580 	/*
2581 	 * Iterate through zhp's children datasets (if any)
2582 	 * and send them accordingly.
2583 	 */
2584 	if ((ret = zfs_iter_filesystems(zhp, be_send_fs_callback, bt)) != 0) {
2585 		/*
2586 		 * Error occurred while processing a child dataset.
2587 		 * Destroy this dataset and return error.
2588 		 */
2589 		zfs_handle_t	*d_zhp = NULL;
2590 
2591 		ZFS_CLOSE(zhp);
2592 
2593 		if ((d_zhp = zfs_open(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM))
2594 		    == NULL) {
2595 			return (ret);
2596 		}
2597 
2598 		(void) zfs_destroy(d_zhp, B_FALSE);
2599 		ZFS_CLOSE(d_zhp);
2600 		return (ret);
2601 	}
2602 
2603 	ZFS_CLOSE(zhp);
2604 	return (0);
2605 }
2606 
2607 /*
2608  * Function:	be_destroy_callback
2609  * Description:	Callback function used to destroy a BEs children datasets
2610  *		and snapshots.
2611  * Parameters:
2612  *		zhp - zfs_handle_t pointer to the filesystem being processed.
2613  *		data - Not used.
2614  * Returns:
2615  *		0 - Success
2616  *		be_errno_t - Failure
2617  * Scope:
2618  *		Private
2619  */
2620 static int
be_destroy_callback(zfs_handle_t * zhp,void * data)2621 be_destroy_callback(zfs_handle_t *zhp, void *data)
2622 {
2623 	be_destroy_data_t	*dd = data;
2624 	int ret = 0;
2625 
2626 	/*
2627 	 * Iterate down this file system's hierarchical children
2628 	 * and destroy them first.
2629 	 */
2630 	if ((ret = zfs_iter_filesystems(zhp, be_destroy_callback, dd)) != 0) {
2631 		ZFS_CLOSE(zhp);
2632 		return (ret);
2633 	}
2634 
2635 	if (dd->destroy_snaps) {
2636 		/*
2637 		 * Iterate through this file system's snapshots and
2638 		 * destroy them before destroying the file system itself.
2639 		 */
2640 		if ((ret = zfs_iter_snapshots(zhp, B_FALSE, be_destroy_callback,
2641 		    dd))
2642 		    != 0) {
2643 			ZFS_CLOSE(zhp);
2644 			return (ret);
2645 		}
2646 	}
2647 
2648 	/* Attempt to unmount the dataset before destroying it */
2649 	if (dd->force_unmount) {
2650 		if ((ret = zfs_unmount(zhp, NULL, MS_FORCE)) != 0) {
2651 			be_print_err(gettext("be_destroy_callback: "
2652 			    "failed to unmount %s: %s\n"), zfs_get_name(zhp),
2653 			    libzfs_error_description(g_zfs));
2654 			ret = zfs_err_to_be_err(g_zfs);
2655 			ZFS_CLOSE(zhp);
2656 			return (ret);
2657 		}
2658 	}
2659 
2660 	if (zfs_destroy(zhp, B_FALSE) != 0) {
2661 		be_print_err(gettext("be_destroy_callback: "
2662 		    "failed to destroy %s: %s\n"), zfs_get_name(zhp),
2663 		    libzfs_error_description(g_zfs));
2664 		ret = zfs_err_to_be_err(g_zfs);
2665 		ZFS_CLOSE(zhp);
2666 		return (ret);
2667 	}
2668 
2669 	ZFS_CLOSE(zhp);
2670 	return (0);
2671 }
2672 
2673 /*
2674  * Function:	be_demote_callback
2675  * Description:	This callback function is used to iterate through the file
2676  *		systems of a BE, looking for the right clone to promote such
2677  *		that this file system is left without any dependent clones.
2678  *		If the file system has no dependent clones, it doesn't need
2679  *		to get demoted, and the function will return success.
2680  *
2681  *		The demotion will be done in two passes.  The first pass
2682  *		will attempt to find the youngest snapshot that has a clone
2683  *		that is part of some other BE.  The second pass will attempt
2684  *		to find the youngest snapshot that has a clone that is not
2685  *		part of a BE.  Doing this helps ensure the aggregated set of
2686  *		file systems that compose a BE stay coordinated wrt BE
2687  *		snapshots and BE dependents.  It also prevents a random user
2688  *		generated clone of a BE dataset to become the parent of other
2689  *		BE datasets after demoting this dataset.
2690  *
2691  * Parameters:
2692  *		zhp - zfs_handle_t pointer to the current file system being
2693  *			processed.
2694  *		data - not used.
2695  * Return:
2696  *		0 - Success
2697  *		be_errno_t - Failure
2698  * Scope:
2699  *		Private
2700  */
2701 static int
2702 /* LINTED */
be_demote_callback(zfs_handle_t * zhp,void * data)2703 be_demote_callback(zfs_handle_t *zhp, void *data)
2704 {
2705 	be_demote_data_t	dd = { 0 };
2706 	int			i, ret = 0;
2707 
2708 	/*
2709 	 * Initialize be_demote_data for the first pass - this will find a
2710 	 * clone in another BE, if one exists.
2711 	 */
2712 	dd.find_in_BE = B_TRUE;
2713 
2714 	for (i = 0; i < 2; i++) {
2715 
2716 		if (zfs_iter_snapshots(zhp, B_FALSE,
2717 		    be_demote_find_clone_callback, &dd) != 0) {
2718 			be_print_err(gettext("be_demote_callback: "
2719 			    "failed to iterate snapshots for %s: %s\n"),
2720 			    zfs_get_name(zhp), libzfs_error_description(g_zfs));
2721 			ret = zfs_err_to_be_err(g_zfs);
2722 			ZFS_CLOSE(zhp);
2723 			return (ret);
2724 		}
2725 		if (dd.clone_zhp != NULL) {
2726 			/* Found the clone to promote.  Promote it. */
2727 			if (zfs_promote(dd.clone_zhp) != 0) {
2728 				be_print_err(gettext("be_demote_callback: "
2729 				    "failed to promote %s: %s\n"),
2730 				    zfs_get_name(dd.clone_zhp),
2731 				    libzfs_error_description(g_zfs));
2732 				ret = zfs_err_to_be_err(g_zfs);
2733 				ZFS_CLOSE(dd.clone_zhp);
2734 				ZFS_CLOSE(zhp);
2735 				return (ret);
2736 			}
2737 
2738 			ZFS_CLOSE(dd.clone_zhp);
2739 		}
2740 
2741 		/*
2742 		 * Reinitialize be_demote_data for the second pass.
2743 		 * This will find a user created clone outside of any BE
2744 		 * namespace, if one exists.
2745 		 */
2746 		dd.clone_zhp = NULL;
2747 		dd.origin_creation = 0;
2748 		dd.snapshot = NULL;
2749 		dd.find_in_BE = B_FALSE;
2750 	}
2751 
2752 	/* Iterate down this file system's children and demote them */
2753 	if ((ret = zfs_iter_filesystems(zhp, be_demote_callback, NULL)) != 0) {
2754 		ZFS_CLOSE(zhp);
2755 		return (ret);
2756 	}
2757 
2758 	ZFS_CLOSE(zhp);
2759 	return (0);
2760 }
2761 
2762 /*
2763  * Function:	be_demote_find_clone_callback
2764  * Description:	This callback function is used to iterate through the
2765  *		snapshots of a dataset, looking for the youngest snapshot
2766  *		that has a clone.  If found, it returns a reference to the
2767  *		clone back to the caller in the callback data.
2768  * Parameters:
2769  *		zhp - zfs_handle_t pointer to current snapshot being looked at
2770  *		data - be_demote_data_t pointer used to store the clone that
2771  *			is found.
2772  * Returns:
2773  *		0 - Successfully iterated through all snapshots.
2774  *		1 - Failed to iterate through all snapshots.
2775  * Scope:
2776  *		Private
2777  */
2778 static int
be_demote_find_clone_callback(zfs_handle_t * zhp,void * data)2779 be_demote_find_clone_callback(zfs_handle_t *zhp, void *data)
2780 {
2781 	be_demote_data_t	*dd = data;
2782 	time_t			snap_creation;
2783 	int			zret = 0;
2784 
2785 	/* If snapshot has no clones, no need to look at it */
2786 	if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) == 0) {
2787 		ZFS_CLOSE(zhp);
2788 		return (0);
2789 	}
2790 
2791 	dd->snapshot = zfs_get_name(zhp);
2792 
2793 	/* Get the creation time of this snapshot */
2794 	snap_creation = (time_t)zfs_prop_get_int(zhp, ZFS_PROP_CREATION);
2795 
2796 	/*
2797 	 * If this snapshot's creation time is greater than (or younger than)
2798 	 * the current youngest snapshot found, iterate this snapshot to
2799 	 * check if it has a clone that we're looking for.
2800 	 */
2801 	if (snap_creation >= dd->origin_creation) {
2802 		/*
2803 		 * Iterate the dependents of this snapshot to find a
2804 		 * a clone that's a direct dependent.
2805 		 */
2806 		if ((zret = zfs_iter_dependents(zhp, B_FALSE,
2807 		    be_demote_get_one_clone, dd)) == -1) {
2808 			be_print_err(gettext("be_demote_find_clone_callback: "
2809 			    "failed to iterate dependents of %s\n"),
2810 			    zfs_get_name(zhp));
2811 			ZFS_CLOSE(zhp);
2812 			return (1);
2813 		} else if (zret == 1) {
2814 			/*
2815 			 * Found a clone, update the origin_creation time
2816 			 * in the callback data.
2817 			 */
2818 			dd->origin_creation = snap_creation;
2819 		}
2820 	}
2821 
2822 	ZFS_CLOSE(zhp);
2823 	return (0);
2824 }
2825 
2826 /*
2827  * Function:	be_demote_get_one_clone
2828  * Description:	This callback function is used to iterate through a
2829  *		snapshot's dependencies to find a filesystem that is a
2830  *		direct clone of the snapshot being iterated.
2831  * Parameters:
2832  *		zhp - zfs_handle_t pointer to current dataset being looked at
2833  *		data - be_demote_data_t pointer used to store the clone
2834  *			that is found, and also provides flag to note
2835  *			whether or not the clone filesystem being searched
2836  *			for needs to be found in a BE dataset hierarchy.
2837  * Return:
2838  *		1 - Success, found clone and its also a BE's root dataset.
2839  *		0 - Failure, clone not found.
2840  * Scope:
2841  *		Private
2842  */
2843 static int
be_demote_get_one_clone(zfs_handle_t * zhp,void * data)2844 be_demote_get_one_clone(zfs_handle_t *zhp, void *data)
2845 {
2846 	be_demote_data_t	*dd = data;
2847 	char			origin[ZFS_MAX_DATASET_NAME_LEN];
2848 	char			ds_path[ZFS_MAX_DATASET_NAME_LEN];
2849 
2850 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
2851 		ZFS_CLOSE(zhp);
2852 		return (0);
2853 	}
2854 
2855 	(void) strlcpy(ds_path, zfs_get_name(zhp), sizeof (ds_path));
2856 
2857 	/*
2858 	 * Make sure this is a direct clone of the snapshot
2859 	 * we're iterating.
2860 	 */
2861 	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
2862 	    NULL, 0, B_FALSE) != 0) {
2863 		be_print_err(gettext("be_demote_get_one_clone: "
2864 		    "failed to get origin of %s: %s\n"), ds_path,
2865 		    libzfs_error_description(g_zfs));
2866 		ZFS_CLOSE(zhp);
2867 		return (0);
2868 	}
2869 	if (strcmp(origin, dd->snapshot) != 0) {
2870 		ZFS_CLOSE(zhp);
2871 		return (0);
2872 	}
2873 
2874 	if (dd->find_in_BE) {
2875 		if ((zpool_iter(g_zfs, be_check_be_roots_callback, ds_path))
2876 		    > 0) {
2877 			if (dd->clone_zhp != NULL)
2878 				ZFS_CLOSE(dd->clone_zhp);
2879 			dd->clone_zhp = zhp;
2880 			return (1);
2881 		}
2882 
2883 		ZFS_CLOSE(zhp);
2884 		return (0);
2885 	}
2886 
2887 	if (dd->clone_zhp != NULL)
2888 		ZFS_CLOSE(dd->clone_zhp);
2889 
2890 	dd->clone_zhp = zhp;
2891 	return (1);
2892 }
2893 
2894 /*
2895  * Function:	be_get_snap
2896  * Description:	This function takes a snapshot dataset name and separates
2897  *		out the parent dataset portion from the snapshot name.
2898  *		I.e. it finds the '@' in the snapshot dataset name and
2899  *		replaces it with a '\0'.
2900  * Parameters:
2901  *		origin - char pointer to a snapshot dataset name.  Its
2902  *			contents will be modified by this function.
2903  *		*snap - pointer to a char pointer.  Will be set to the
2904  *			snapshot name portion upon success.
2905  * Return:
2906  *		BE_SUCCESS - Success
2907  *		1 - Failure
2908  * Scope:
2909  *		Private
2910  */
2911 static int
be_get_snap(char * origin,char ** snap)2912 be_get_snap(char *origin, char **snap)
2913 {
2914 	char	*cp;
2915 
2916 	/*
2917 	 * Separate out the origin's dataset and snapshot portions by
2918 	 * replacing the @ with a '\0'
2919 	 */
2920 	cp = strrchr(origin, '@');
2921 	if (cp != NULL) {
2922 		if (cp[1] != '\0') {
2923 			cp[0] = '\0';
2924 			*snap = cp+1;
2925 		} else {
2926 			return (1);
2927 		}
2928 	} else {
2929 		return (1);
2930 	}
2931 
2932 	return (BE_SUCCESS);
2933 }
2934 
2935 /*
2936  * Function:	be_create_container_ds
2937  * Description:	This function checks that the zpool passed has the BE
2938  *		container dataset, and if not, then creates it.
2939  * Parameters:
2940  *		zpool - name of pool to create BE container dataset in.
2941  * Return:
2942  *		B_TRUE - Successfully created BE container dataset, or it
2943  *			already existed.
2944  *		B_FALSE - Failed to create container dataset.
2945  * Scope:
2946  *		Private
2947  */
2948 static boolean_t
be_create_container_ds(char * zpool)2949 be_create_container_ds(char *zpool)
2950 {
2951 	nvlist_t	*props = NULL;
2952 	char		be_container_ds[MAXPATHLEN];
2953 
2954 	/* Generate string for BE container dataset for this pool */
2955 	if (be_make_container_ds(zpool, be_container_ds,
2956 	    sizeof (be_container_ds)) != BE_SUCCESS) {
2957 		be_print_err(gettext("%s: failed to get BE container dataset "
2958 		    "for %s\n"), __func__, zpool);
2959 		return (B_FALSE);
2960 	}
2961 
2962 	if (!zfs_dataset_exists(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM)) {
2963 
2964 		if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
2965 			be_print_err(gettext("be_create_container_ds: "
2966 			    "nvlist_alloc failed\n"));
2967 			return (B_FALSE);
2968 		}
2969 
2970 		if (nvlist_add_string(props,
2971 		    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
2972 		    ZFS_MOUNTPOINT_LEGACY) != 0) {
2973 			be_print_err(gettext("be_create_container_ds: "
2974 			    "internal error: out of memory\n"));
2975 			nvlist_free(props);
2976 			return (B_FALSE);
2977 		}
2978 
2979 		if (nvlist_add_string(props,
2980 		    zfs_prop_to_name(ZFS_PROP_CANMOUNT), "off") != 0) {
2981 			be_print_err(gettext("be_create_container_ds: "
2982 			    "internal error: out of memory\n"));
2983 			nvlist_free(props);
2984 			return (B_FALSE);
2985 		}
2986 
2987 		if (zfs_create(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM,
2988 		    props) != 0) {
2989 			be_print_err(gettext("be_create_container_ds: "
2990 			    "failed to create container dataset (%s): %s\n"),
2991 			    be_container_ds, libzfs_error_description(g_zfs));
2992 			nvlist_free(props);
2993 			return (B_FALSE);
2994 		}
2995 
2996 		nvlist_free(props);
2997 	}
2998 
2999 	return (B_TRUE);
3000 }
3001 
3002 /*
3003  * Function:	be_prep_clone_send_fs
3004  * Description:	This function takes a zfs handle to a dataset from the
3005  *		original BE, and generates the name of the clone dataset
3006  *		to create for the new BE.  It also prepares the zfs
3007  *		properties to be used for the new BE.
3008  * Parameters:
3009  *		zhp - pointer to zfs_handle_t of the file system being
3010  *			cloned/copied.
3011  *		bt - be_transaction_data pointer providing information
3012  *			about the original BE and new BE.
3013  *		clone_ds - buffer to store the name of the dataset
3014  *			for the new BE.
3015  *		clone_ds_len - length of clone_ds buffer
3016  * Return:
3017  *		BE_SUCCESS - Success
3018  *		be_errno_t - Failure
3019  * Scope:
3020  *		Private
3021  */
3022 static int
be_prep_clone_send_fs(zfs_handle_t * zhp,be_transaction_data_t * bt,char * clone_ds,int clone_ds_len)3023 be_prep_clone_send_fs(zfs_handle_t *zhp, be_transaction_data_t *bt,
3024     char *clone_ds, int clone_ds_len)
3025 {
3026 	zprop_source_t	sourcetype;
3027 	char		source[ZFS_MAX_DATASET_NAME_LEN];
3028 	char		zhp_name[ZFS_MAX_DATASET_NAME_LEN];
3029 	char		mountpoint[MAXPATHLEN];
3030 	char		*child_fs = NULL;
3031 	char		*zhp_mountpoint = NULL;
3032 	int		err = 0;
3033 
3034 	/*
3035 	 * Get a copy of the dataset name zfs_name from zhp
3036 	 */
3037 	(void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name));
3038 
3039 	/*
3040 	 * Get file system name relative to the root.
3041 	 */
3042 	if (strncmp(zhp_name, bt->obe_root_ds, strlen(bt->obe_root_ds))
3043 	    == 0) {
3044 		child_fs = zhp_name + strlen(bt->obe_root_ds);
3045 
3046 		/*
3047 		 * if child_fs is NULL, this means we're processing the
3048 		 * root dataset itself; set child_fs to the empty string.
3049 		 */
3050 		if (child_fs == NULL)
3051 			child_fs = "";
3052 	} else {
3053 		return (BE_ERR_INVAL);
3054 	}
3055 
3056 	/*
3057 	 * Generate the name of the clone file system.
3058 	 */
3059 	(void) snprintf(clone_ds, clone_ds_len, "%s%s", bt->nbe_root_ds,
3060 	    child_fs);
3061 
3062 	/* Get the mountpoint and source properties of the existing dataset */
3063 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
3064 	    sizeof (mountpoint), &sourcetype, source, sizeof (source),
3065 	    B_FALSE) != 0) {
3066 		be_print_err(gettext("be_prep_clone_send_fs: "
3067 		    "failed to get mountpoint for (%s): %s\n"),
3068 		    zhp_name, libzfs_error_description(g_zfs));
3069 		return (zfs_err_to_be_err(g_zfs));
3070 	}
3071 
3072 	/*
3073 	 * Workaround for 6668667 where a mountpoint property of "/" comes
3074 	 * back as "".
3075 	 */
3076 	if (strcmp(mountpoint, "") == 0) {
3077 		(void) snprintf(mountpoint, sizeof (mountpoint), "/");
3078 	}
3079 
3080 	/*
3081 	 * Figure out what to set as the mountpoint for the new dataset.
3082 	 * If the source of the mountpoint property is local, use the
3083 	 * mountpoint value itself.  Otherwise, remove it from the
3084 	 * zfs properties list so that it gets inherited.
3085 	 */
3086 	if (sourcetype & ZPROP_SRC_LOCAL) {
3087 		/*
3088 		 * If the BE that this file system is a part of is
3089 		 * currently mounted, strip off the BE altroot portion
3090 		 * from the mountpoint.
3091 		 */
3092 		zhp_mountpoint = mountpoint;
3093 
3094 		if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
3095 		    bt->obe_altroot != NULL && strcmp(bt->obe_altroot,
3096 		    "/") != 0 && zfs_is_mounted(zhp, NULL)) {
3097 
3098 			int altroot_len = strlen(bt->obe_altroot);
3099 
3100 			if (strncmp(bt->obe_altroot, mountpoint, altroot_len)
3101 			    == 0) {
3102 				if (mountpoint[altroot_len] == '/')
3103 					zhp_mountpoint = mountpoint +
3104 					    altroot_len;
3105 				else if (mountpoint[altroot_len] == '\0')
3106 					(void) snprintf(mountpoint,
3107 					    sizeof (mountpoint), "/");
3108 			}
3109 		}
3110 
3111 		if (nvlist_add_string(bt->nbe_zfs_props,
3112 		    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
3113 		    zhp_mountpoint) != 0) {
3114 			be_print_err(gettext("be_prep_clone_send_fs: "
3115 			    "internal error: out of memory\n"));
3116 			return (BE_ERR_NOMEM);
3117 		}
3118 	} else {
3119 		err = nvlist_remove_all(bt->nbe_zfs_props,
3120 		    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT));
3121 		if (err != 0 && err != ENOENT) {
3122 			be_print_err(gettext("be_prep_clone_send_fs: "
3123 			    "failed to remove mountpoint from "
3124 			    "nvlist\n"));
3125 			return (BE_ERR_INVAL);
3126 		}
3127 	}
3128 
3129 	/*
3130 	 * Set the 'canmount' property
3131 	 */
3132 	if (nvlist_add_string(bt->nbe_zfs_props,
3133 	    zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto") != 0) {
3134 		be_print_err(gettext("be_prep_clone_send_fs: "
3135 		    "internal error: out of memory\n"));
3136 		return (BE_ERR_NOMEM);
3137 	}
3138 
3139 	return (BE_SUCCESS);
3140 }
3141 
3142 /*
3143  * Function:	be_get_zone_be_name
3144  * Description:	This function takes the zones root dataset, the container
3145  *		dataset and returns the zones BE name based on the zone
3146  *		root dataset.
3147  * Parameters:
3148  *		root_ds - the zones root dataset.
3149  *		container_ds - the container dataset for the zone.
3150  * Returns:
3151  *		char * - the BE name of this zone based on the root dataset.
3152  */
3153 static char *
be_get_zone_be_name(char * root_ds,char * container_ds)3154 be_get_zone_be_name(char *root_ds, char *container_ds)
3155 {
3156 	return (root_ds + (strlen(container_ds) + 1));
3157 }
3158 
3159 /*
3160  * Function:	be_zone_root_exists_callback
3161  * Description:	This callback function is used to determine if a
3162  *		zone root container dataset has any children.  It always
3163  *		returns 1, signifying a hierarchical child of the zone
3164  *		root container dataset has been traversed and therefore
3165  *		it has children.
3166  * Parameters:
3167  *		zhp - zfs_handle_t pointer to current dataset being processed.
3168  *		data - not used.
3169  * Returns:
3170  *		1 - dataset exists
3171  * Scope:
3172  *		Private
3173  */
3174 static int
3175 /* LINTED */
be_zone_root_exists_callback(zfs_handle_t * zhp,void * data)3176 be_zone_root_exists_callback(zfs_handle_t *zhp, void *data)
3177 {
3178 	ZFS_CLOSE(zhp);
3179 	return (1);
3180 }
3181