f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * CDDL HEADER START
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The contents of this file are subject to the terms of the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Common Development and Distribution License (the "License").
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * You may not use this file except in compliance with the License.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * or http://www.opensolaris.org/os/licensing.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * See the License for the specific language governing permissions
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and limitations under the License.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * When distributing Covered Code, include this CDDL HEADER in each
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If applicable, add the following below this CDDL HEADER, with the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * fields enclosed by brackets "[]" replaced with your own identifying
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * information: Portions Copyright [yyyy] [name of copyright owner]
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * CDDL HEADER END
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska * Copyright (c) 2016 Martin Matuska. All rights reserved.
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin */
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * System includes
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <assert.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <ctype.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <errno.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libgen.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libintl.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libnvpair.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libzfs.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <stdio.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <stdlib.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <string.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/mnttab.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/mount.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/stat.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/types.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <sys/wait.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <unistd.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libbe.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse#include <libbe_priv.h>
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Library wide variables */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasselibzfs_handle_t *g_zfs = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Private function prototypes */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int _be_destroy(const char *, be_destroy_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_destroy_zones(char *, char *, be_destroy_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_destroy_zone_roots(char *, be_destroy_data_t *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_destroy_zone_roots_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_copy_zones(char *, char *, char *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_clone_fs_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_destroy_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_send_fs_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_demote_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_demote_find_clone_callback(zfs_handle_t *, void *);
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Ereminstatic int be_has_snapshot_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_demote_get_one_clone(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_get_snap(char *, char **);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_prep_clone_send_fs(zfs_handle_t *, be_transaction_data_t *,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *, int);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic boolean_t be_create_container_ds(char *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic char *be_get_zone_be_name(char *root_ds, char *container_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int be_zone_root_exists_callback(zfs_handle_t *, void *);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Public Functions */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_init
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Creates the initial datasets for a BE and leaves them
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * unpopulated. The resultant BE can be mounted but can't
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * yet be activated or booted.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_attrs - pointer to nvlist_t of attributes being passed in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The following attributes are used by this function:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_NEW_BE_NAME *required
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_NEW_BE_POOL *required
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_ZFS_PROPERTIES *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_FS_NAMES *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_FS_NUM *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_SHARED_FS_NAMES *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_SHARED_FS_NUM *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Public
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_init(nvlist_t *be_attrs)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t bt = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zpool_handle_t *zlp;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_t *zfs_props = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char nbe_root_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char child_fs[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char **fs_names = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char **shared_fs_names = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uint16_t fs_num = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uint16_t shared_fs_num = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int nelem;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int i;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int zret = 0, ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Initialize libzfs handle */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zfs_init())
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INIT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get new BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME, &bt.nbe_name)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_NEW_BE_NAME attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Validate new BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_valid_be_name(bt.nbe_name)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: invalid BE name %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get zpool name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_POOL, &bt.nbe_zpool)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_NEW_BE_POOL attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get file system attributes */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nelem = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, 0,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_FS_NUM, DATA_TYPE_UINT16, &fs_num,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_FS_NAMES, DATA_TYPE_STRING_ARRAY, &fs_names, &nelem,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to lookup fs "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "attributes\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nelem != fs_num) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: size of FS_NAMES array (%d) "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "does not match FS_NUM (%d)\n"), nelem, fs_num);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get shared file system attributes */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nelem = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_SHARED_FS_NUM, DATA_TYPE_UINT16, &shared_fs_num,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_SHARED_FS_NAMES, DATA_TYPE_STRING_ARRAY, &shared_fs_names,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &nelem, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "shared fs attributes\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nelem != shared_fs_num) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: size of SHARED_FS_NAMES "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "array does not match SHARED_FS_NUM\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Verify that nbe_zpool exists */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zlp = zpool_open(g_zfs, bt.nbe_zpool)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "find existing zpool (%s): %s\n"), bt.nbe_zpool,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zpool_close(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Verify BE container dataset in nbe_zpool exists.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If not, create it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_create_container_ds(bt.nbe_zpool))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_CREATDS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Verify that nbe_name doesn't already exist in some pool.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zret = zpool_iter(g_zfs, be_exists_callback, bt.nbe_name)) > 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: BE (%s) already exists\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_BE_EXISTS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (zret < 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: zpool_iter failed: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (nbe_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Create property list for new BE root dataset. If some
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zfs properties were already provided by the caller, dup
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * that list. Otherwise initialize a new property list.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_ZFS_PROPERTIES, DATA_TYPE_NVLIST, &zfs_props, NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_ZFS_PROPERTIES attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_props != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Make sure its a unique nvlist */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!(zfs_props->nvl_nvflag & NV_UNIQUE_NAME) &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse !(zfs_props->nvl_nvflag & NV_UNIQUE_NAME_TYPE)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: ZFS property list "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "not unique\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Dup the list */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_dup(zfs_props, &bt.nbe_zfs_props, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to dup ZFS "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "property list\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Initialize new nvlist */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: internal "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "error: out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set the mountpoint property for the root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(bt.nbe_zfs_props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), "/") != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: internal error "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NOMEM;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set the 'canmount' property */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(bt.nbe_zfs_props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto") != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: internal error "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NOMEM;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Create BE root dataset for the new BE */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_create(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_zfs_props) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "create BE root dataset (%s): %s\n"), nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set UUID for new BE */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_set_uuid(nbe_root_ds)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "set uuid for new BE\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Clear the mountpoint property so that the non-shared
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * file systems created below inherit their mountpoints.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) nvlist_remove(bt.nbe_zfs_props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), DATA_TYPE_STRING);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Create the new BE's non-shared file systems */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (i = 0; i < fs_num && fs_names[i]; i++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If fs == "/", skip it;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * we already created the root dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(fs_names[i], "/") == 0)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for file system */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(child_fs, sizeof (child_fs), "%s%s",
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nbe_root_ds, fs_names[i]);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Create file system */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_zfs_props) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to create "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE's child dataset (%s): %s\n"), child_fs,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Create the new BE's shared file systems */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (shared_fs_num > 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_t *props = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: nvlist_alloc failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NOMEM;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (i = 0; i < shared_fs_num; i++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for shared file system */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(child_fs, sizeof (child_fs), "%s%s",
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_zpool, shared_fs_names[i]);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse shared_fs_names[i]) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "internal error: out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_free(props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NOMEM;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Create file system if it doesn't already exist */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_dataset_exists(g_zfs, child_fs,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_TYPE_FILESYSTEM)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_create(g_zfs, child_fs, ZFS_TYPE_FILESYSTEM,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse props) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_init: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "create BE's shared dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse child_fs, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_free(props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_free(props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(bt.nbe_zfs_props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_zfs_fini();
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_destroy
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Destroy a BE and all of its children datasets, snapshots and
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zones that belong to the parent BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_attrs - pointer to nvlist_t of attributes being passed in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The following attributes are used by this function:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_ORIG_BE_NAME *required
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_DESTROY_FLAGS *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Public
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_destroy(nvlist_t *be_attrs)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t bt = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t cur_bt = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_destroy_data_t dd = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uint16_t flags = 0;
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin boolean_t bs_found = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int zret;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char obe_root_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *mp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Initialize libzfs handle */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zfs_init())
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INIT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get name of BE to delete */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, &bt.obe_name)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_ORIG_BE_NAME attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Validate BE name. If valid, then check that the original BE is not
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the active BE. If it is the 'active' BE then return an error code
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * since we can't destroy the active BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_valid_be_name(bt.obe_name)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: invalid BE name %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (bt.obe_name != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_find_current_be(&cur_bt)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(cur_bt.obe_name, bt.obe_name) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_DESTROY_CURR_BE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get destroy flags if provided */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_DESTROY_FLAGS, DATA_TYPE_UINT16, &flags, NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_DESTROY_FLAGS attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd.destroy_snaps = flags & BE_DESTROY_FLAG_SNAPSHOTS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd.force_unmount = flags & BE_DESTROY_FLAG_FORCE_UNMOUNT;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Find which zpool obe_name lives in */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to find zpool "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "for BE (%s)\n"), bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_BE_NOENT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (zret < 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: zpool_iter failed: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for obe_name's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (obe_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_root_ds = obe_root_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (getzoneid() != GLOBAL_ZONEID) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (!be_zone_compare_uuids(bt.obe_root_ds)) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (be_is_active_on_boot(bt.obe_name)) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_destroy: destroying "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "active zone root dataset from non-active "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "global BE is not supported\n"));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin return (BE_ERR_NOTSUP);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Detect if the BE to destroy has the 'active on boot' property set.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If so, set the 'active on boot' property on the the 'active' BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_is_active_on_boot(bt.obe_name)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_activate_current_be()) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "make the current BE 'active on boot'\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM)) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), bt.obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin /*
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * Check if BE has snapshots and BE_DESTROY_FLAG_SNAPSHOTS
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * is not set.
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin */
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska (void) zfs_iter_snapshots(zhp, B_FALSE, be_has_snapshot_callback,
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska &bs_found);
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin if (!dd.destroy_snaps && bs_found) {
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin ZFS_CLOSE(zhp);
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin return (BE_ERR_SS_EXISTS);
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin }
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get the UUID of the global BE */
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (getzoneid() == GLOBAL_ZONEID) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (be_get_uuid(zfs_get_name(zhp),
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin &dd.gz_be_uuid) != BE_SUCCESS) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_destroy: BE has no "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "UUID (%s)\n"), zfs_get_name(zhp));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the global BE is mounted, make sure we've been given the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * flag to forcibly unmount it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_is_mounted(zhp, &mp)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!(dd.force_unmount)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s is currently mounted at %s, cannot destroy\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_name, mp != NULL ? mp : "<unknown>");
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_MOUNTED);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Destroy the non-global zone BE's if we are in the global zone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and there is a UUID associated with the global zone BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getzoneid() == GLOBAL_ZONEID && !uuid_is_null(dd.gz_be_uuid)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_destroy_zones(bt.obe_name, bt.obe_root_ds, &dd))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "destroy one or more zones for BE %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount the BE if it was mounted */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_is_mounted(zhp, NULL)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_unmount(bt.obe_name, BE_UNMOUNT_FLAG_FORCE))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to unmount %s\n"), bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Destroy this BE */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_destroy((const char *)bt.obe_root_ds, &dd))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Remove BE's entry from the boot menu */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getzoneid() == GLOBAL_ZONEID) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_remove_menu(bt.obe_name, bt.obe_zpool, NULL))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "remove BE %s from the boot menu\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_root_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_zfs_fini();
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_copy
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function makes a copy of an existing BE. If the original
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE and the new BE are in the same pool, it uses zfs cloning to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * create the new BE, otherwise it does a physical copy.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the original BE name isn't provided, it uses the currently
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * booted BE. If the new BE name isn't provided, it creates an
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * auto named BE and returns that name to the caller.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_attrs - pointer to nvlist_t of attributes being passed in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The following attributes are used by this function:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_ORIG_BE_NAME *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_SNAP_NAME *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_NEW_BE_NAME *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_NEW_BE_POOL *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_NEW_BE_DESC *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_ZFS_PROPERTIES *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_POLICY *optional
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the BE_ATTR_NEW_BE_NAME was not passed in, upon
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * successful BE creation, the following attribute values
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will be returned to the caller by setting them in the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_attrs parameter passed in:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_SNAP_NAME
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_ATTR_NEW_BE_NAME
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Public
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_copy(nvlist_t *be_attrs)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t bt = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_fs_list_data_t fld = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp = NULL;
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin zpool_handle_t *zphp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_t *zfs_props = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_t uu = { 0 };
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin uuid_t parent_uu = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char obe_root_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char nbe_root_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char ss[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *new_mp = NULL;
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin char *obe_name = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t autoname = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t be_created = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int i;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int zret;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin struct be_defaults be_defaults;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Initialize libzfs handle */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zfs_init())
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INIT);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get original BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin BE_ATTR_ORIG_BE_NAME, DATA_TYPE_STRING, &obe_name, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_ORIG_BE_NAME attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) {
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin return (ret);
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin }
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin be_get_defaults(&be_defaults);
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If original BE name not provided, use current BE */
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin if (obe_name != NULL) {
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin bt.obe_name = obe_name;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Validate original BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_valid_be_name(bt.obe_name)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "invalid BE name %s\n"), bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin if (be_defaults.be_deflt_rpool_container) {
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin if ((zphp = zpool_open(g_zfs, bt.obe_zpool)) == NULL) {
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin be_print_err(gettext("be_get_node_data: failed to "
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin "open rpool (%s): %s\n"), bt.obe_zpool,
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin libzfs_error_description(g_zfs));
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin return (zfs_err_to_be_err(g_zfs));
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin }
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin if (be_find_zpool_callback(zphp, &bt) == 0) {
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin return (BE_ERR_BE_NOENT);
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin }
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin } else {
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin /* Find which zpool obe_name lives in */
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) ==
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin 0) {
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin be_print_err(gettext("be_copy: failed to "
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin "find zpool for BE (%s)\n"), bt.obe_name);
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin return (BE_ERR_BE_NOENT);
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin } else if (zret < 0) {
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin be_print_err(gettext("be_copy: "
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin "zpool_iter failed: %s\n"),
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin libzfs_error_description(g_zfs));
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin return (zfs_err_to_be_err(g_zfs));
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get snapshot name of original BE if one was provided */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_SNAP_NAME, DATA_TYPE_STRING, &bt.obe_snap_name, NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_SNAP_NAME attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get new BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_NEW_BE_NAME, DATA_TYPE_STRING, &bt.nbe_name, NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_NEW_BE_NAME attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get zpool name to create new BE in */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_NEW_BE_POOL, DATA_TYPE_STRING, &bt.nbe_zpool, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_NEW_BE_POOL attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get new BE's description if one was provided */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_NEW_BE_DESC, DATA_TYPE_STRING, &bt.nbe_desc, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_NEW_BE_DESC attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get BE policy to create this snapshot under */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_POLICY, DATA_TYPE_STRING, &bt.policy, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_POLICY attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Create property list for new BE root dataset. If some
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zfs properties were already provided by the caller, dup
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * that list. Otherwise initialize a new property list.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_ATTR_ZFS_PROPERTIES, DATA_TYPE_NVLIST, &zfs_props, NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to lookup "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE_ATTR_ZFS_PROPERTIES attribute\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_props != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Make sure its a unique nvlist */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!(zfs_props->nvl_nvflag & NV_UNIQUE_NAME) &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse !(zfs_props->nvl_nvflag & NV_UNIQUE_NAME_TYPE)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: ZFS property list "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "not unique\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Dup the list */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_dup(zfs_props, &bt.nbe_zfs_props, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to dup ZFS property list\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Initialize new nvlist */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: internal "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "error: out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If new BE name provided, validate the BE name and then verify
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * that new BE name doesn't already exist in some pool.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (bt.nbe_name) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Validate original BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_valid_be_name(bt.nbe_name)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "invalid BE name %s\n"), bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_INVAL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Verify it doesn't already exist */
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (getzoneid() == GLOBAL_ZONEID) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if ((zret = zpool_iter(g_zfs, be_exists_callback,
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin bt.nbe_name)) > 0) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_copy: BE (%s) already "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "exists\n"), bt.nbe_name);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ret = BE_ERR_BE_EXISTS;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin goto done;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin } else if (zret < 0) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_copy: zpool_iter "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "failed: %s\n"),
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin libzfs_error_description(g_zfs));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ret = zfs_err_to_be_err(g_zfs);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin goto done;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin } else {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds,
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin sizeof (nbe_root_ds));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (zfs_dataset_exists(g_zfs, nbe_root_ds,
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ZFS_TYPE_FILESYSTEM)) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_copy: BE (%s) already "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "exists\n"), bt.nbe_name);
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ret = BE_ERR_BE_EXISTS;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin goto done;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If an auto named BE is desired, it must be in the same
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * pool is the original BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (bt.nbe_zpool != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: cannot specify pool "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "name when creating an auto named BE\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_INVAL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Generate auto named BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((bt.nbe_name = be_auto_be_name(bt.obe_name))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to generate auto BE name\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_AUTONAME;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse autoname = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If zpool name to create new BE in is not provided,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * create new BE in original BE's pool.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (bt.nbe_zpool == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_zpool = bt.obe_zpool;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get root dataset names for obe_name and nbe_name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (obe_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(bt.nbe_zpool, bt.nbe_name, nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (nbe_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_root_ds = obe_root_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_root_ds = nbe_root_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If an existing snapshot name has been provided to create from,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * verify that it exists for the original BE's root dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (bt.obe_snap_name != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate dataset name for snapshot to use. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(ss, sizeof (ss), "%s@%s", bt.obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_snap_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Verify snapshot exists */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_dataset_exists(g_zfs, ss, ZFS_TYPE_SNAPSHOT)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "snapshot does not exist (%s): %s\n"), ss,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_SS_NOENT;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Else snapshot name was not provided, generate an
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * auto named snapshot to use as its origin.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_create_snapshot(bt.obe_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &bt.obe_snap_name, bt.policy)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to create auto named snapshot\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(be_attrs, BE_ATTR_SNAP_NAME,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_snap_name) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to add snap name to be_attrs\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NOMEM;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to original BE's root dataset. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), bt.obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If original BE is currently mounted, record its altroot. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_is_mounted(zhp, &bt.obe_altroot) && bt.obe_altroot == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get altroot of mounted BE %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_name, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(bt.obe_zpool, bt.nbe_zpool) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Do clone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate through original BE's datasets and clone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * them to create new BE. This call will end up closing
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the zfs handle passed in whether it succeeds for fails.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_clone_fs_callback(zhp, &bt)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Creating clone BE failed */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!autoname || ret != BE_ERR_BE_EXISTS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to clone new BE (%s) from "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "orig BE (%s)\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name, bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_CLONE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * We failed to create the new BE because a BE with
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the auto-name we generated above has since come
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * into existence. Regenerate a new auto-name
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and retry.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (i = 1; i < BE_AUTO_NAME_MAX_TRY; i++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Sleep 1 before retrying */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) sleep(1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate new auto BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((bt.nbe_name = be_auto_be_name(bt.obe_name))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to generate auto "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE name\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_AUTONAME;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Regenerate string for new BE's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root dataset name
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(bt.nbe_zpool, bt.nbe_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nbe_root_ds, sizeof (nbe_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_root_ds = nbe_root_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get handle to original BE's root dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, bt.obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to open BE root dataset "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "(%s): %s\n"), bt.obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Try to clone the BE again. This
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * call will end up closing the zfs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * handle passed in whether it
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * succeeds or fails.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = be_clone_fs_callback(zhp, &bt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse break;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (ret != BE_ERR_BE_EXISTS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to clone new BE "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "(%s) from orig BE (%s)\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name, bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_CLONE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If we've exhausted the maximum number of
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * tries, free the auto BE name and return
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * error.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (i == BE_AUTO_NAME_MAX_TRY) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "to create unique auto BE name\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_AUTONAME;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Do copy (i.e. send BE datasets via zfs_send/recv) */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Verify BE container dataset in nbe_zpool exists.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If not, create it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_create_container_ds(bt.nbe_zpool)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_CREATDS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate through original BE's datasets and send
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * them to the other pool. This call will end up closing
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the zfs handle passed in whether it succeeds or fails.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_send_fs_callback(zhp, &bt)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "send BE (%s) to pool (%s)\n"), bt.obe_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_zpool);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_COPY;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Set flag to note that the dataset(s) for the new BE have been
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * successfully created so that if a failure happens from this point
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * on, we know to cleanup these datasets.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_created = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Validate that the new BE is mountable.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Do not attempt to mount non-global zone datasets
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * since they are not cloned yet.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_mount(bt.nbe_name, &new_mp, BE_MOUNT_FLAG_NO_ZONES))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount newly created BE\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) _be_unmount(bt.nbe_name, 0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set UUID for new BE */
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (getzoneid() == GLOBAL_ZONEID) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if (be_set_uuid(bt.nbe_root_ds) != BE_SUCCESS) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_copy: failed to "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "set uuid for new BE\n"));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin } else {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin if ((ret = be_zone_get_parent_uuid(bt.obe_root_ds,
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin &parent_uu)) != BE_SUCCESS) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_copy: failed to get "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "parentbe uuid from orig BE\n"));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin ret = BE_ERR_ZONE_NO_PARENTBE;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin goto done;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin } else if ((ret = be_zone_set_parent_uuid(bt.nbe_root_ds,
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin parent_uu)) != BE_SUCCESS) {
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin be_print_err(gettext("be_copy: failed to set "
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin "parentbe uuid for newly created BE\n"));
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin goto done;
7e0e2549bfaa531aff576083ab0c07f84fa8fb27Alexander Eremin }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Process zones outside of the private BE namespace.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * This has to be done here because we need the uuid set in the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root dataset of the new BE. The uuid is use to set the parentbe
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * property for the new zones datasets.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getzoneid() == GLOBAL_ZONEID &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_get_uuid(bt.obe_root_ds, &uu) == BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_copy_zones(bt.obe_name, bt.obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_root_ds)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to process "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "zones\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Generate a list of file systems from the original BE that are
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * legacy mounted. We use this list to determine which entries in
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * vfstab we need to update for the new BE we've just created.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_get_legacy_fs(bt.obe_name, bt.obe_root_ds, NULL, NULL,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &fld)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get legacy mounted file system list for %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Update new BE's vfstab.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_update_vfstab(bt.nbe_name, bt.obe_zpool, bt.nbe_zpool,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &fld, new_mp)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "update new BE's vfstab (%s)\n"), bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount the new BE */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_unmount(bt.nbe_name, 0)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount newly created BE\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Add boot menu entry for newly created clone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getzoneid() == GLOBAL_ZONEID &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (ret = be_append_menu(bt.nbe_name, bt.nbe_zpool,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL, bt.obe_root_ds, bt.nbe_desc)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "add BE (%s) to boot menu\n"), bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If we succeeded in creating an auto named BE, set its policy
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * type and return the auto generated name to the caller by storing
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it in the nvlist passed in by the caller.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (autoname) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to new BE's root dataset. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, bt.nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), bt.nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Set the policy type property into the new BE's root dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (bt.policy == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If no policy type provided, use default type */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.policy = be_default_policy();
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, BE_POLICY_PROPERTY, bt.policy) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "set BE policy for %s: %s\n"), bt.nbe_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return the auto generated name to the caller
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (bt.nbe_name) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_NAME,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "add snap name to be_attrs\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_free_fs_list(&fld);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(bt.nbe_zfs_props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(bt.obe_altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(new_mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If a failure occurred and we already created the datasets for
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the new boot environment, destroy them.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (ret != BE_SUCCESS && be_created) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_destroy_data_t cdd = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse cdd.force_unmount = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "destroying partially created boot environment\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (getzoneid() == GLOBAL_ZONEID && be_get_uuid(bt.nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &cdd.gz_be_uuid) == 0)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) be_destroy_zones(bt.nbe_name, bt.nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse &cdd);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) _be_destroy(bt.nbe_root_ds, &cdd);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_zfs_fini();
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Semi-Private Functions */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_find_zpool_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to find the pool that a BE lives in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zlp - zpool_handle_t pointer for the current pool being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * looked at.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_transaction_data_t pointer providing information
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * about the BE that's being searched for.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * This function uses the obe_name member of this
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * parameter to use as the BE name to search for.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Upon successfully locating the BE, it populates
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * obe_zpool with the pool name that the BE is found in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - BE exists in this pool.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - BE does not exist in this pool.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_find_zpool_callback(zpool_handle_t *zlp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t *bt = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse const char *zpool = zpool_get_name(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char be_root_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Generate string for the BE's root dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(zpool, bt->obe_name, be_root_ds, sizeof (be_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Check if dataset exists
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_dataset_exists(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* BE's root dataset exists in zpool */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt->obe_zpool = strdup(zpool);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zpool_close(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zpool_close(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_exists_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to find out if a BE exists.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zlp - zpool_handle_t pointer to the current pool being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * looked at.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - BE name to look for.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - BE exists in this pool.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - BE does not exist in this pool.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_exists_callback(zpool_handle_t *zlp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse const char *zpool = zpool_get_name(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *be_name = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char be_root_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Generate string for the BE's root dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_root_ds(zpool, be_name, be_root_ds, sizeof (be_root_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Check if dataset exists
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_dataset_exists(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* BE's root dataset exists in zpool */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zpool_close(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zpool_close(zlp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin/*
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * Function: be_has_snapshots_callback
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * Description: Callback function used to find out if a BE has snapshots.
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * Parameters:
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * zlp - zpool_handle_t pointer to the current pool being
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * looked at.
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * data - be_snap_found_t pointer.
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * Return:
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * 1 - BE has no snapshots.
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * 0 - BE has snapshots.
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * Scope:
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin * Private
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin */
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Ereminstatic int
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Ereminbe_has_snapshot_callback(zfs_handle_t *zhp, void *data)
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin{
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin boolean_t *bs = data;
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin if (zfs_get_name(zhp) == NULL) {
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin zfs_close(zhp);
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin return (1);
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin }
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin *bs = B_TRUE;
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin zfs_close(zhp);
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin return (0);
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin}
5ee7c79303f6cc727e2df5f1c7332c0f4c9832a3Alexander Eremin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_set_uuid
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function generates a uuid, unparses it into
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * string representation, and sets that string into
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a zfs user property for a root dataset of a BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The name of the user property used to store the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * uuid is org.opensolaris.libbe:uuid
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root_ds - Root dataset of the BE to set a uuid on.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide ues only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_set_uuid(char *root_ds)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_t uu = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char uu_string[UUID_PRINTABLE_STRING_LENGTH] = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate a UUID and unparse it into string form */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_generate(uu);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (uuid_is_null(uu) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_set_uuid: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "generate uuid\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_GEN_UUID);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_unparse(uu, uu_string);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to the BE's root dataset. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_set_uuid: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Set uuid property for the BE */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(zhp, BE_UUID_PROPERTY, uu_string) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_set_uuid: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "set uuid property for BE: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_get_uuid
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function gets the uuid string from a BE root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset, parses it into internal format, and returns
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it the caller via a reference pointer passed in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * rootds - Root dataset of the BE to get the uuid from.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * uu - reference pointer to a uuid_t to return uuid in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Semi-private (library wide use only)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasseint
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_get_uuid(const char *root_ds, uuid_t *uu)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_t *userprops = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_t *propname = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *uu_string = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to the BE's root dataset. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_uuid: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get user properties for BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((userprops = zfs_get_user_props(zhp)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_uuid: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get user properties for BE root dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse root_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get UUID string from BE's root dataset user properties */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_lookup_nvlist(userprops, BE_UUID_PROPERTY, &propname) != 0 ||
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_lookup_string(propname, ZPROP_VALUE, &uu_string) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * This probably just means that the BE is simply too old
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to have a uuid or that we haven't created a uuid for
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * this BE yet.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_uuid: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get uuid property from BE root dataset user "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "properties.\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NO_UUID;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Parse uuid string into internal format */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (uuid_parse(uu_string, *uu) != 0 || uuid_is_null(*uu)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_get_uuid: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "parse uuid\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_PARSE_UUID;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* Private Functions */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* ******************************************************************** */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: _be_destroy
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Destroy a BE and all of its children datasets and snapshots.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * This function is called for both global BEs and non-global BEs.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The root dataset of either the global BE or non-global BE to be
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * destroyed is passed in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root_ds - pointer to the name of the root dataset of the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE to destroy.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dd - pointer to a be_destroy_data_t structure.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse_be_destroy(const char *root_ds, be_destroy_data_t *dd)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char origin[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char parent[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *snap = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t has_origin = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Demote this BE in case it has dependent clones. This call
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will end up closing the zfs handle passed in whether it
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * succeeds or fails.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_demote_callback(zhp, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to demote BE %s\n"), root_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_DEMOTE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get the origin of this BE's root dataset. This will be used
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * later to destroy the snapshots originally used to create this BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL, 0, B_FALSE) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(parent, origin, sizeof (parent));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_get_snap(parent, &snap) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "get snapshot name from origin %s\n"), origin);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse has_origin = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Destroy the BE's root and its hierarchical children. This call
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will end up closing the zfs handle passed in whether it succeeds
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * or fails.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_destroy_callback(zhp, dd) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "destroy BE %s\n"), root_ds);
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin ret = zfs_err_to_be_err(g_zfs);
de1ab35c09a8c3ae1b531c0a613d2cc1c61cee9dAlexander Eremin return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If BE has an origin */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (has_origin) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If origin snapshot doesn't have any other
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dependents, delete the origin.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, origin, ZFS_TYPE_SNAPSHOT)) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE's origin (%s): %s\n"), origin,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If origin has dependents, don't delete it. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to BE's parent's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, parent, ZFS_TYPE_FILESYSTEM)) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE's parent root dataset (%s): %s\n"), parent,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Destroy the snapshot origin used to create this BE. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The boolean set to B_FALSE and passed to zfs_destroy_snaps()
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * tells zfs to process and destroy the snapshots now.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Otherwise the call will potentially return where the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * snapshot isn't actually destroyed yet, and ZFS is waiting
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * until all the references to the snapshot have been
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * released before actually destroying the snapshot.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_destroy_snaps(zhp, snap, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "destroy original snapshots used to create "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "BE: %s\n"), libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If a failure happened because a clone exists,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * don't return a failure to the user. Above, we're
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * only checking that the root dataset's origin
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * snapshot doesn't have dependent clones, but its
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * possible that a subordinate dataset origin snapshot
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * has a clone. We really need to check for that
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * before trying to destroy the origin snapshot.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (libzfs_errno(g_zfs) != EZFS_EXISTS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_destroy_zones
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Find valid zone's and call be_destroy_zone_roots to destroy its
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * corresponding dataset and all of its children datasets
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and snapshots.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_name - name of global boot environment being destroyed
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_root_ds - root dataset of global boot environment being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * destroyed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dd - be_destroy_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * NOTES - Requires that the BE being deleted has no dependent BEs. If it
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * does, the destroy will fail.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_destroy_zones(char *be_name, char *be_root_ds, be_destroy_data_t *dd)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int i;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int force_umnt = BE_UNMOUNT_FLAG_NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonename = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath_ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *mp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneList_t zlist = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneBrandList_t *brands = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If zones are not implemented, then get out. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!z_zones_are_implemented()) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get list of supported brands */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((brands = be_get_supported_brandlist()) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "no supported brands\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, be_root_ds, ZFS_TYPE_FILESYSTEM)) ==
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zones: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open BE root dataset (%s): %s\n"), be_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the global BE is not mounted, we must mount it here to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * gather data about the non-global zones in it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_is_mounted(zhp, &mp)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_mount(be_name, &mp,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zones: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount the BE (%s) for zones processing.\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_set_zone_root(mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(mp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get list of supported zones. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zlist = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Unmount the BE before destroying the zones in it. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (dd->force_unmount)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse force_umnt = BE_UNMOUNT_FLAG_FORCE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_unmount(be_name, force_umnt)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zones: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "unmount the BE (%s)\n"), be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate through the zones and destroy them. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Skip zones that aren't at least installed */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath = z_zlist_get_zonepath(zlist, i);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get the dataset of this zonepath. If its not
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a dataset, skip it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zonepath_ds = be_get_ds_from_dir(zonepath)) == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Check if this zone is supported based on the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset of its zonepath.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zone_supported(zonepath_ds)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Find the zone BE root datasets for this zone. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_destroy_zone_roots(zonepath_ds, dd))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zones: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "find and destroy zone roots for zone %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonename);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(zonepath_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_zone_list(zlist);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_destroy_zone_roots
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function will open the zone's root container dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and iterate the datasets within, looking for roots that
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * belong to the given global BE and destroying them.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If no other zone roots remain in the zone's root container
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset, the function will destroy it and the zone's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonepath dataset as well.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zonepath_ds - pointer to zone's zonepath dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dd - pointer to a linked destroy data.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_destroy_zone_roots(char *zonepath_ds, be_destroy_data_t *dd)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zone_container_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for the root container dataset for this zone. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_container_ds(zonepath_ds, zone_container_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (zone_container_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to this zone's root container dataset. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zone_roots: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open zone root container dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_container_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate through all of this zone's BEs, destroying the ones
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * that belong to the parent global BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, be_destroy_zone_roots_callback,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zone_roots: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "destroy zone roots under zonepath dataset %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to this zone's root container dataset. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zone_roots: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open zone root container dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_container_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If there are no more zone roots in this zone's root container,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset, destroy it and the zonepath dataset as well.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_iter_filesystems(zhp, be_zone_root_exists_callback, NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Destroy the zone root container dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_unmount(zhp, NULL, MS_FORCE) != 0 ||
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_destroy(zhp, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zone_roots: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "destroy zone root container dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_container_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to zonepath dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp = zfs_open(g_zfs, zonepath_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zone_roots: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open zonepath dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Destroy zonepath dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_unmount(zhp, NULL, MS_FORCE) != 0 ||
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_destroy(zhp, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zone_roots: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to destroy zonepath dataest %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_destroy_zone_roots_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function is used as a callback to iterate over all of
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a zone's root datasets, finding the one's that
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * correspond to the current BE. The name's
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * of the zone root datasets are then destroyed by _be_destroy().
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to current dataset being processed
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_destroy_data_t pointer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_destroy_zone_roots_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_destroy_data_t *dd = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_t parent_uuid = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_zone_get_parent_uuid(zfs_get_name(zhp), &parent_uuid)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zone_roots_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "could not get parentuuid for zone root dataset %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (uuid_compare(dd->gz_be_uuid, parent_uuid) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Found a zone root dataset belonging to the parent
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE being destroyed. Destroy this zone BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_destroy(zfs_get_name(zhp), dd)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_zone_root_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to destroy zone root %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_copy_zones
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Find valid zones and clone them to create their
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * corresponding datasets for the BE being created.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * obe_name - name of source global BE being copied.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * obe_root_ds - root dataset of source global BE being copied.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * nbe_root_ds - root dataset of target global BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_copy_zones(char *obe_name, char *obe_root_ds, char *nbe_root_ds)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int i, num_retries;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int iret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonename = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zonepath = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zone_be_name = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *temp_mntpt = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *new_zone_be_name = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zoneroot[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zoneroot_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zone_container_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char new_zoneroot_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char ss[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_t uu = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char uu_string[UUID_PRINTABLE_STRING_LENGTH] = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t bt = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *obe_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *nbe_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *z_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneList_t zlist = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneBrandList_t *brands = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse boolean_t mounted_here = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *snap_name = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If zones are not implemented, then get out. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!z_zones_are_implemented()) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get list of supported brands */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((brands = be_get_supported_brandlist()) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "no supported brands\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to origin BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((obe_zhp = zfs_open(g_zfs, obe_root_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: failed to open "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "the origin BE root dataset (%s) for zones processing: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s\n"), obe_root_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get handle to newly cloned BE's root dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((nbe_zhp = zfs_open(g_zfs, nbe_root_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: failed to open "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "the new BE root dataset (%s): %s\n"), nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(obe_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get the uuid of the newly cloned parent BE. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (be_get_uuid(zfs_get_name(nbe_zhp), &uu) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get uuid for BE root "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "dataset %s\n"), zfs_get_name(nbe_zhp));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(nbe_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(nbe_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uuid_unparse(uu, uu_string);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the origin BE is not mounted, we must mount it here to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * gather data about the non-global zones in it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_is_mounted(obe_zhp, &temp_mntpt)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = _be_mount(obe_name, &temp_mntpt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse BE_MOUNT_FLAG_NULL)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "mount the BE (%s) for zones procesing.\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse mounted_here = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_set_zone_root(temp_mntpt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get list of supported zones. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zlist = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_SUCCESS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (i = 0; (zonename = z_zlist_get_zonename(zlist, i)) != NULL; i++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_fs_list_data_t fld = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char zonepath_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get zonepath of zone */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath = z_zlist_get_zonepath(zlist, i);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Skip zones that aren't at least installed */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (z_zlist_get_current_state(zlist, i) < ZONE_STATE_INSTALLED)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get the dataset of this zonepath. If its not
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a dataset, skip it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ds = be_get_ds_from_dir(zonepath)) == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(zonepath_ds, ds, sizeof (zonepath_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ds = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get zoneroot directory */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_zoneroot(zonepath, zoneroot, sizeof (zoneroot));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If zonepath dataset not supported, skip it. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!be_zone_supported(zonepath_ds)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse continue;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_find_active_zone_root(obe_zhp, zonepath_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds, sizeof (zoneroot_ds))) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to find active zone root for zone %s "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "in BE %s\n"), zonename, obe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_container_ds(zonepath_ds, zone_container_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (zone_container_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((z_zhp = zfs_open(g_zfs, zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to open zone root dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_be_name =
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_get_zone_be_name(zoneroot_ds, zone_container_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((new_zone_be_name = be_auto_zone_be_name(zone_container_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_be_name)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: failed "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "to generate auto name for zone BE.\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_AUTONAME;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((snap_name = be_auto_snap_name()) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "generate snapshot name for zone BE.\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_AUTONAME;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(ss, sizeof (ss), "%s@%s", zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse snap_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_snapshot(g_zfs, ss, B_TRUE, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to snapshot zone BE (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ss, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (libzfs_errno(g_zfs) == EZFS_EXISTS)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_ZONE_SS_EXISTS;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse else
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(new_zoneroot_ds, sizeof (new_zoneroot_ds),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s/%s", zone_container_ds, new_zone_be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_name = zone_be_name;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_root_ds = zoneroot_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_snap_name = snap_name;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.obe_altroot = temp_mntpt;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name = new_zone_be_name;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_root_ds = new_zoneroot_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_alloc(&bt.nbe_zfs_props, NV_UNIQUE_NAME, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "internal error: out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_NOMEM;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The call to be_clone_fs_callback always closes the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zfs_handle so there's no need to close z_zhp.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((iret = be_clone_fs_callback(z_zhp, &bt)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (iret != BE_ERR_BE_EXISTS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to create zone BE clone for new "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "zone BE %s\n"), new_zone_be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = iret;
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(bt.nbe_zfs_props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * We failed to create the new zone BE because a zone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE with the auto-name we generated above has since
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * come into existence. Regenerate a new auto-name
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and retry.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (num_retries = 1;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse num_retries < BE_AUTO_NAME_MAX_TRY;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse num_retries++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Sleep 1 before retrying */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) sleep(1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate new auto zone BE name */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(new_zone_be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((new_zone_be_name = be_auto_zone_be_name(
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_container_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zone_be_name)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to generate auto name "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "for zone BE.\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_AUTONAME;
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(bt.nbe_zfs_props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(new_zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (new_zoneroot_ds),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "%s/%s", zone_container_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse new_zone_be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name = new_zone_be_name;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_root_ds = new_zoneroot_ds;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get handle to original zone BE's root
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((z_zhp = zfs_open(g_zfs, zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to open zone root "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(bt.nbe_zfs_props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Try to clone the zone BE again. This
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * call will end up closing the zfs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * handle passed in whether it
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * succeeds or fails.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse iret = be_clone_fs_callback(z_zhp, &bt);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (iret == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse break;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (iret != BE_ERR_BE_EXISTS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to create zone BE clone "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "for new zone BE %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse new_zone_be_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = iret;
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(bt.nbe_zfs_props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If we've exhausted the maximum number of
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * tries, free the auto zone BE name and return
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * error.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (num_retries == BE_AUTO_NAME_MAX_TRY) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: failed "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "to create a unique auto zone BE name\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = BE_ERR_AUTONAME;
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(bt.nbe_zfs_props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(bt.nbe_zfs_props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((z_zhp = zfs_open(g_zfs, new_zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_TYPE_FILESYSTEM)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to open the new zone BE root dataset "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "(%s): %s\n"), new_zoneroot_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(z_zhp, BE_ZONE_PARENTBE_PROPERTY,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse uu_string) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to set parentbe property\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(z_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_set(z_zhp, BE_ZONE_ACTIVE_PROPERTY, "on") != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to set active property\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(z_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Generate a list of file systems from the original
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zone BE that are legacy mounted. We use this list
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to determine which entries in the vfstab we need to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * update for the new zone BE we've just created.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_get_legacy_fs(obe_name, obe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zoneroot_ds, zoneroot, &fld)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get legacy mounted file system "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "list for zone %s\n"), zonename);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(z_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Update new zone BE's vfstab.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_update_zone_vfstab(z_zhp, bt.nbe_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zonepath_ds, zonepath_ds, &fld)) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_copy_zones: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to update new BE's vfstab (%s)\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt.nbe_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(z_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_free_fs_list(&fld);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto done;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_free_fs_list(&fld);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(z_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassedone:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse free(snap_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (brands != NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_brand_list(brands);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zlist != NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse z_free_zone_list(zlist);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mounted_here)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) _be_unmount(obe_name, 0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(obe_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_clone_fs_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to iterate through a BE's filesystems
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to clone them for the new BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer for the filesystem being processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_transaction_data_t pointer providing information
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * about original BE and new BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_clone_fs_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t *bt = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *zhp_ss = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char prop_buf[MAXPATHLEN];
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char zhp_name[ZFS_MAX_DATASET_NAME_LEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char clone_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char ss[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, prop_buf,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_MAXPROPLEN, NULL, NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_clone_fs_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get dataset mountpoint (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) != 0 &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse strcmp(prop_buf, "legacy") != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Since zfs can't currently handle setting the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint for a zoned dataset we'll have to skip
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * this dataset. This is because the mountpoint is not
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * set to "legacy".
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse goto zoned;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get a copy of the dataset name from the zfs handle
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get the clone dataset name and prepare the zfs properties for it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_prep_clone_send_fs(zhp, bt, clone_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (clone_ds))) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Generate the name of the snapshot to use.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(ss, sizeof (ss), "%s@%s", zhp_name,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt->obe_snap_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get handle to snapshot.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zhp_ss = zfs_open(g_zfs, ss, ZFS_TYPE_SNAPSHOT)) == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_clone_fs_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get handle to snapshot (%s): %s\n"), ss,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Clone the dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_clone(zhp_ss, clone_ds, bt->nbe_zfs_props) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_clone_fs_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to create clone dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse clone_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp_ss);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp_ss);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassezoned:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate through zhp's children datasets (if any)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and clone them accordingly.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, be_clone_fs_callback, bt)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Error occurred while processing a child dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Destroy this dataset and return error.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *d_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((d_zhp = zfs_open(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) zfs_destroy(d_zhp, B_FALSE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(d_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_send_fs_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to iterate through a BE's filesystems
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to copy them for the new BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer for the filesystem being processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_transaction_data_t pointer providing information
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * about original BE and new BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errnot_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_send_fs_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_transaction_data_t *bt = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse recvflags_t flags = { 0 };
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char zhp_name[ZFS_MAX_DATASET_NAME_LEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char clone_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sendflags_t send_flags = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int pid, status, retval;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int srpipe[2];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get a copy of the dataset name from the zfs handle
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get the clone dataset name and prepare the zfs properties for it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = be_prep_clone_send_fs(zhp, bt, clone_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (clone_ds))) != BE_SUCCESS) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Create the new dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_create(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM, bt->nbe_zfs_props)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_send_fs_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to create new dataset '%s': %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse clone_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Destination file system is already created
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * hence we need to set the force flag on
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse flags.force = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Initiate the pipe to be used for the send and recv
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (pipe(srpipe) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_send_fs_callback: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "open pipe\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (errno_to_be_err(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Fork off a child to send the dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((pid = fork()) == -1) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int err = errno;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_send_fs_callback: failed to fork\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) close(srpipe[0]);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) close(srpipe[1]);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (errno_to_be_err(err));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (pid == 0) { /* child process */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) close(srpipe[0]);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Send dataset */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (zfs_send(zhp, NULL, bt->obe_snap_name, &send_flags,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse srpipe[1], NULL, NULL, NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse _exit(1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse _exit(0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) close(srpipe[1]);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Receive dataset */
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie if (zfs_receive(g_zfs, clone_ds, NULL, &flags, srpipe[0], NULL) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_send_fs_callback: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "recv dataset (%s)\n"), clone_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) close(srpipe[0]);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* wait for child to exit */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse do {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse retval = waitpid(pid, &status, 0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (retval == -1) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse status = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } while (retval != pid);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (WEXITSTATUS(status) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_send_fs_callback: failed to "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "send dataset (%s)\n"), zhp_name);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_ZFS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate through zhp's children datasets (if any)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and send them accordingly.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, be_send_fs_callback, bt)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Error occurred while processing a child dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Destroy this dataset and return error.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_handle_t *d_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((d_zhp = zfs_open(g_zfs, clone_ds, ZFS_TYPE_FILESYSTEM))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) zfs_destroy(d_zhp, B_FALSE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(d_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_destroy_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: Callback function used to destroy a BEs children datasets
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and snapshots.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to the filesystem being processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - Not used.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_destroy_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_destroy_data_t *dd = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate down this file system's hierarchical children
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * and destroy them first.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, be_destroy_callback, dd)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (dd->destroy_snaps) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate through this file system's snapshots and
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * destroy them before destroying the file system itself.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska if ((ret = zfs_iter_snapshots(zhp, B_FALSE, be_destroy_callback,
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska dd))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Attempt to unmount the dataset before destroying it */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (dd->force_unmount) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_unmount(zhp, NULL, MS_FORCE)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to unmount %s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_destroy(zhp, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_destroy_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to destroy %s: %s\n"), zfs_get_name(zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_demote_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This callback function is used to iterate through the file
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * systems of a BE, looking for the right clone to promote such
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * that this file system is left without any dependent clones.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the file system has no dependent clones, it doesn't need
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to get demoted, and the function will return success.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * The demotion will be done in two passes. The first pass
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * will attempt to find the youngest snapshot that has a clone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * that is part of some other BE. The second pass will attempt
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to find the youngest snapshot that has a clone that is not
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * part of a BE. Doing this helps ensure the aggregated set of
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * file systems that compose a BE stay coordinated wrt BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * snapshots and BE dependents. It also prevents a random user
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * generated clone of a BE dataset to become the parent of other
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE datasets after demoting this dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to the current file system being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - not used.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* LINTED */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_demote_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_demote_data_t dd = { 0 };
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int i, ret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Initialize be_demote_data for the first pass - this will find a
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * clone in another BE, if one exists.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd.find_in_BE = B_TRUE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse for (i = 0; i < 2; i++) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska if (zfs_iter_snapshots(zhp, B_FALSE,
0d8fa8f8eba3ea46bc79d73445009505d1dd5d7dMartin Matuska be_demote_find_clone_callback, &dd) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_demote_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to iterate snapshots for %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp), libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (dd.clone_zhp != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Found the clone to promote. Promote it. */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_promote(dd.clone_zhp) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_demote_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to promote %s: %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(dd.clone_zhp),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ret = zfs_err_to_be_err(g_zfs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(dd.clone_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(dd.clone_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Reinitialize be_demote_data for the second pass.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * This will find a user created clone outside of any BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * namespace, if one exists.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd.clone_zhp = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd.origin_creation = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd.snapshot = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd.find_in_BE = B_FALSE;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Iterate down this file system's children and demote them */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((ret = zfs_iter_filesystems(zhp, be_demote_callback, NULL)) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (ret);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_demote_find_clone_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This callback function is used to iterate through the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * snapshots of a dataset, looking for the youngest snapshot
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * that has a clone. If found, it returns a reference to the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * clone back to the caller in the callback data.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to current snapshot being looked at
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_demote_data_t pointer used to store the clone that
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * is found.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Successfully iterated through all snapshots.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - Failed to iterate through all snapshots.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_demote_find_clone_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_demote_data_t *dd = data;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse time_t snap_creation;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int zret = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* If snapshot has no clones, no need to look at it */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES) == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd->snapshot = zfs_get_name(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get the creation time of this snapshot */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse snap_creation = (time_t)zfs_prop_get_int(zhp, ZFS_PROP_CREATION);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If this snapshot's creation time is greater than (or younger than)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * the current youngest snapshot found, iterate this snapshot to
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * check if it has a clone that we're looking for.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (snap_creation >= dd->origin_creation) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Iterate the dependents of this snapshot to find a
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * a clone that's a direct dependent.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zret = zfs_iter_dependents(zhp, B_FALSE,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_demote_get_one_clone, dd)) == -1) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_demote_find_clone_callback: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to iterate dependents of %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_get_name(zhp));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else if (zret == 1) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Found a clone, update the origin_creation time
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * in the callback data.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd->origin_creation = snap_creation;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_demote_get_one_clone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This callback function is used to iterate through a
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * snapshot's dependencies to find a filesystem that is a
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * direct clone of the snapshot being iterated.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to current dataset being looked at
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - be_demote_data_t pointer used to store the clone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * that is found, and also provides flag to note
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * whether or not the clone filesystem being searched
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * for needs to be found in a BE dataset hierarchy.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - Success, found clone and its also a BE's root dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 0 - Failure, clone not found.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_demote_get_one_clone(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_demote_data_t *dd = data;
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char origin[ZFS_MAX_DATASET_NAME_LEN];
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char ds_path[ZFS_MAX_DATASET_NAME_LEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(ds_path, zfs_get_name(zhp), sizeof (ds_path));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Make sure this is a direct clone of the snapshot
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * we're iterating.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse NULL, 0, B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_demote_get_one_clone: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get origin of %s: %s\n"), ds_path,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(origin, dd->snapshot) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (dd->find_in_BE) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if ((zpool_iter(g_zfs, be_check_be_roots_callback, ds_path))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse > 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (dd->clone_zhp != NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(dd->clone_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd->clone_zhp = zhp;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (0);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (dd->clone_zhp != NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(dd->clone_zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse dd->clone_zhp = zhp;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_get_snap
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function takes a snapshot dataset name and separates
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * out the parent dataset portion from the snapshot name.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * I.e. it finds the '@' in the snapshot dataset name and
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * replaces it with a '\0'.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * origin - char pointer to a snapshot dataset name. Its
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * contents will be modified by this function.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * *snap - pointer to a char pointer. Will be set to the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * snapshot name portion upon success.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_get_snap(char *origin, char **snap)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *cp;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Separate out the origin's dataset and snapshot portions by
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * replacing the @ with a '\0'
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse cp = strrchr(origin, '@');
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (cp != NULL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (cp[1] != NULL && cp[1] != '\0') {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse cp[0] = '\0';
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse *snap = cp+1;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_create_container_ds
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function checks that the zpool passed has the BE
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * container dataset, and if not, then creates it.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zpool - name of pool to create BE container dataset in.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * B_TRUE - Successfully created BE container dataset, or it
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * already existed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * B_FALSE - Failed to create container dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic boolean_t
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_create_container_ds(char *zpool)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_t *props = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char be_container_ds[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Generate string for BE container dataset for this pool */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_make_container_ds(zpool, be_container_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (be_container_ds));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (!zfs_dataset_exists(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_create_container_ds: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "nvlist_alloc failed\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (B_FALSE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_MOUNTPOINT_LEGACY) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_create_container_ds: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "internal error: out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_free(props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (B_FALSE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_CANMOUNT), "off") != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_create_container_ds: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "internal error: out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_free(props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (B_FALSE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_create(g_zfs, be_container_ds, ZFS_TYPE_FILESYSTEM,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse props) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_create_container_ds: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to create container dataset (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_container_ds, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_free(props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (B_FALSE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse nvlist_free(props);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (B_TRUE);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_prep_clone_send_fs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function takes a zfs handle to a dataset from the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * original BE, and generates the name of the clone dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * to create for the new BE. It also prepares the zfs
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * properties to be used for the new BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - pointer to zfs_handle_t of the file system being
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * cloned/copied.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * bt - be_transaction_data pointer providing information
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * about the original BE and new BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * clone_ds - buffer to store the name of the dataset
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * for the new BE.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * clone_ds_len - length of clone_ds buffer
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Return:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * BE_SUCCESS - Success
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * be_errno_t - Failure
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_prep_clone_send_fs(zfs_handle_t *zhp, be_transaction_data_t *bt,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *clone_ds, int clone_ds_len)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zprop_source_t sourcetype;
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char source[ZFS_MAX_DATASET_NAME_LEN];
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char zhp_name[ZFS_MAX_DATASET_NAME_LEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char mountpoint[MAXPATHLEN];
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *child_fs = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse char *zhp_mountpoint = NULL;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int err = 0;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get a copy of the dataset name zfs_name from zhp
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) strlcpy(zhp_name, zfs_get_name(zhp), sizeof (zhp_name));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Get file system name relative to the root.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strncmp(zhp_name, bt->obe_root_ds, strlen(bt->obe_root_ds))
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse child_fs = zhp_name + strlen(bt->obe_root_ds);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * if child_fs is NULL, this means we're processing the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root dataset itself; set child_fs to the empty string.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (child_fs == NULL)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse child_fs = "";
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Generate the name of the clone file system.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(clone_ds, clone_ds_len, "%s%s", bt->nbe_root_ds,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse child_fs);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /* Get the mountpoint and source properties of the existing dataset */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), &sourcetype, source, sizeof (source),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse B_FALSE) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_prep_clone_send_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to get mountpoint for (%s): %s\n"),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_name, libzfs_error_description(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (zfs_err_to_be_err(g_zfs));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Workaround for 6668667 where a mountpoint property of "/" comes
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * back as "".
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(mountpoint, "") == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(mountpoint, sizeof (mountpoint), "/");
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Figure out what to set as the mountpoint for the new dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the source of the mountpoint property is local, use the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * mountpoint value itself. Otherwise, remove it from the
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zfs properties list so that it gets inherited.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (sourcetype & ZPROP_SRC_LOCAL) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * If the BE that this file system is a part of is
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * currently mounted, strip off the BE altroot portion
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * from the mountpoint.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint = mountpoint;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse bt->obe_altroot != NULL && strcmp(bt->obe_altroot,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "/") != 0 && zfs_is_mounted(zhp, NULL)) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse int altroot_len = strlen(bt->obe_altroot);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (strncmp(bt->obe_altroot, mountpoint, altroot_len)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse == 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (mountpoint[altroot_len] == '/')
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint = mountpoint +
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse altroot_len;
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse else if (mountpoint[altroot_len] == '\0')
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse (void) snprintf(mountpoint,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse sizeof (mountpoint), "/");
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(bt->nbe_zfs_props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zhp_mountpoint) != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_prep_clone_send_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "internal error: out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse } else {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse err = nvlist_remove_all(bt->nbe_zfs_props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_MOUNTPOINT));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (err != 0 && err != ENOENT) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_prep_clone_send_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "failed to remove mountpoint from "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "nvlist\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_INVAL);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse /*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Set the 'canmount' property
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse if (nvlist_add_string(bt->nbe_zfs_props,
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse zfs_prop_to_name(ZFS_PROP_CANMOUNT), "noauto") != 0) {
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse be_print_err(gettext("be_prep_clone_send_fs: "
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse "internal error: out of memory\n"));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_ERR_NOMEM);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse }
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (BE_SUCCESS);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_get_zone_be_name
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This function takes the zones root dataset, the container
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * dataset and returns the zones BE name based on the zone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root_ds - the zones root dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * container_ds - the container dataset for the zone.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * char * - the BE name of this zone based on the root dataset.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic char *
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_get_zone_be_name(char *root_ds, char *container_ds)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (root_ds + (strlen(container_ds) + 1));
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/*
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Function: be_zone_root_exists_callback
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Description: This callback function is used to determine if a
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zone root container dataset has any children. It always
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * returns 1, signifying a hierarchical child of the zone
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * root container dataset has been traversed and therefore
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * it has children.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Parameters:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * zhp - zfs_handle_t pointer to current dataset being processed.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * data - not used.
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Returns:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * 1 - dataset exists
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Scope:
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse * Private
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassestatic int
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse/* LINTED */
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagassebe_zone_root_exists_callback(zfs_handle_t *zhp, void *data)
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse{
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse ZFS_CLOSE(zhp);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse return (1);
f169c0eae91b2ee787cf8d6dcf8edd9159d4c9e2Glenn Lagasse}