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