1*13013Sglenn.lagasse@oracle.com /* 2*13013Sglenn.lagasse@oracle.com * CDDL HEADER START 3*13013Sglenn.lagasse@oracle.com * 4*13013Sglenn.lagasse@oracle.com * The contents of this file are subject to the terms of the 5*13013Sglenn.lagasse@oracle.com * Common Development and Distribution License (the "License"). 6*13013Sglenn.lagasse@oracle.com * You may not use this file except in compliance with the License. 7*13013Sglenn.lagasse@oracle.com * 8*13013Sglenn.lagasse@oracle.com * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*13013Sglenn.lagasse@oracle.com * or http://www.opensolaris.org/os/licensing. 10*13013Sglenn.lagasse@oracle.com * See the License for the specific language governing permissions 11*13013Sglenn.lagasse@oracle.com * and limitations under the License. 12*13013Sglenn.lagasse@oracle.com * 13*13013Sglenn.lagasse@oracle.com * When distributing Covered Code, include this CDDL HEADER in each 14*13013Sglenn.lagasse@oracle.com * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*13013Sglenn.lagasse@oracle.com * If applicable, add the following below this CDDL HEADER, with the 16*13013Sglenn.lagasse@oracle.com * fields enclosed by brackets "[]" replaced with your own identifying 17*13013Sglenn.lagasse@oracle.com * information: Portions Copyright [yyyy] [name of copyright owner] 18*13013Sglenn.lagasse@oracle.com * 19*13013Sglenn.lagasse@oracle.com * CDDL HEADER END 20*13013Sglenn.lagasse@oracle.com */ 21*13013Sglenn.lagasse@oracle.com 22*13013Sglenn.lagasse@oracle.com /* 23*13013Sglenn.lagasse@oracle.com * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24*13013Sglenn.lagasse@oracle.com */ 25*13013Sglenn.lagasse@oracle.com 26*13013Sglenn.lagasse@oracle.com /* 27*13013Sglenn.lagasse@oracle.com * System includes 28*13013Sglenn.lagasse@oracle.com */ 29*13013Sglenn.lagasse@oracle.com #include <assert.h> 30*13013Sglenn.lagasse@oracle.com #include <errno.h> 31*13013Sglenn.lagasse@oracle.com #include <libintl.h> 32*13013Sglenn.lagasse@oracle.com #include <libnvpair.h> 33*13013Sglenn.lagasse@oracle.com #include <libzfs.h> 34*13013Sglenn.lagasse@oracle.com #include <stdio.h> 35*13013Sglenn.lagasse@oracle.com #include <stdlib.h> 36*13013Sglenn.lagasse@oracle.com #include <string.h> 37*13013Sglenn.lagasse@oracle.com #include <sys/mntent.h> 38*13013Sglenn.lagasse@oracle.com #include <sys/mnttab.h> 39*13013Sglenn.lagasse@oracle.com #include <sys/mount.h> 40*13013Sglenn.lagasse@oracle.com #include <sys/stat.h> 41*13013Sglenn.lagasse@oracle.com #include <sys/types.h> 42*13013Sglenn.lagasse@oracle.com #include <sys/vfstab.h> 43*13013Sglenn.lagasse@oracle.com #include <unistd.h> 44*13013Sglenn.lagasse@oracle.com 45*13013Sglenn.lagasse@oracle.com #include <libbe.h> 46*13013Sglenn.lagasse@oracle.com #include <libbe_priv.h> 47*13013Sglenn.lagasse@oracle.com 48*13013Sglenn.lagasse@oracle.com typedef struct active_zone_root_data { 49*13013Sglenn.lagasse@oracle.com uuid_t parent_uuid; 50*13013Sglenn.lagasse@oracle.com char *zoneroot_ds; 51*13013Sglenn.lagasse@oracle.com } active_zone_root_data_t; 52*13013Sglenn.lagasse@oracle.com 53*13013Sglenn.lagasse@oracle.com typedef struct mounted_zone_root_data { 54*13013Sglenn.lagasse@oracle.com char *zone_altroot; 55*13013Sglenn.lagasse@oracle.com char *zoneroot_ds; 56*13013Sglenn.lagasse@oracle.com } mounted_zone_root_data_t; 57*13013Sglenn.lagasse@oracle.com 58*13013Sglenn.lagasse@oracle.com /* Private function prototypes */ 59*13013Sglenn.lagasse@oracle.com static int be_find_active_zone_root_callback(zfs_handle_t *, void *); 60*13013Sglenn.lagasse@oracle.com static int be_find_mounted_zone_root_callback(zfs_handle_t *, void *); 61*13013Sglenn.lagasse@oracle.com static boolean_t be_zone_get_active(zfs_handle_t *); 62*13013Sglenn.lagasse@oracle.com 63*13013Sglenn.lagasse@oracle.com 64*13013Sglenn.lagasse@oracle.com /* ******************************************************************** */ 65*13013Sglenn.lagasse@oracle.com /* Semi-Private Functions */ 66*13013Sglenn.lagasse@oracle.com /* ******************************************************************** */ 67*13013Sglenn.lagasse@oracle.com 68*13013Sglenn.lagasse@oracle.com /* 69*13013Sglenn.lagasse@oracle.com * Function: be_make_zoneroot 70*13013Sglenn.lagasse@oracle.com * Description: Generate a string for a zone's zoneroot given the 71*13013Sglenn.lagasse@oracle.com * zone's zonepath. 72*13013Sglenn.lagasse@oracle.com * Parameters: 73*13013Sglenn.lagasse@oracle.com * zonepath - pointer to zonepath 74*13013Sglenn.lagasse@oracle.com * zoneroot - pointer to buffer to retrn zoneroot in. 75*13013Sglenn.lagasse@oracle.com * zoneroot_size - size of zoneroot 76*13013Sglenn.lagasse@oracle.com * Returns: 77*13013Sglenn.lagasse@oracle.com * None 78*13013Sglenn.lagasse@oracle.com * Scope: 79*13013Sglenn.lagasse@oracle.com * Semi-private (library wise use only) 80*13013Sglenn.lagasse@oracle.com */ 81*13013Sglenn.lagasse@oracle.com void 82*13013Sglenn.lagasse@oracle.com be_make_zoneroot(char *zonepath, char *zoneroot, int zoneroot_size) 83*13013Sglenn.lagasse@oracle.com { 84*13013Sglenn.lagasse@oracle.com (void) snprintf(zoneroot, zoneroot_size, "%s/root", zonepath); 85*13013Sglenn.lagasse@oracle.com } 86*13013Sglenn.lagasse@oracle.com 87*13013Sglenn.lagasse@oracle.com /* 88*13013Sglenn.lagasse@oracle.com * Function: be_find_active_zone_root 89*13013Sglenn.lagasse@oracle.com * Description: This function will find the active zone root of a zone for 90*13013Sglenn.lagasse@oracle.com * a given global BE. It will iterate all of the zone roots 91*13013Sglenn.lagasse@oracle.com * under a zonepath, find the zone roots that belong to the 92*13013Sglenn.lagasse@oracle.com * specified global BE, and return the one that is active. 93*13013Sglenn.lagasse@oracle.com * Parameters: 94*13013Sglenn.lagasse@oracle.com * be_zhp - zfs handle to global BE root dataset. 95*13013Sglenn.lagasse@oracle.com * zonepath_ds - pointer to zone's zonepath dataset. 96*13013Sglenn.lagasse@oracle.com * zoneroot_ds - pointer to a buffer to store the dataset name of 97*13013Sglenn.lagasse@oracle.com * the zone's zoneroot that's currently active for this 98*13013Sglenn.lagasse@oracle.com * given global BE.. 99*13013Sglenn.lagasse@oracle.com * zoneroot-ds_size - size of zoneroot_ds. 100*13013Sglenn.lagasse@oracle.com * Returns: 101*13013Sglenn.lagasse@oracle.com * BE_SUCCESS - Success 102*13013Sglenn.lagasse@oracle.com * be_errno_t - Failure 103*13013Sglenn.lagasse@oracle.com * Scope: 104*13013Sglenn.lagasse@oracle.com * Semi-private (library wide use only) 105*13013Sglenn.lagasse@oracle.com */ 106*13013Sglenn.lagasse@oracle.com int 107*13013Sglenn.lagasse@oracle.com be_find_active_zone_root(zfs_handle_t *be_zhp, char *zonepath_ds, 108*13013Sglenn.lagasse@oracle.com char *zoneroot_ds, int zoneroot_ds_size) 109*13013Sglenn.lagasse@oracle.com { 110*13013Sglenn.lagasse@oracle.com active_zone_root_data_t azr_data = { 0 }; 111*13013Sglenn.lagasse@oracle.com zfs_handle_t *zhp; 112*13013Sglenn.lagasse@oracle.com char zone_container_ds[MAXPATHLEN]; 113*13013Sglenn.lagasse@oracle.com int ret = BE_SUCCESS; 114*13013Sglenn.lagasse@oracle.com 115*13013Sglenn.lagasse@oracle.com /* Get the uuid of the parent global BE */ 116*13013Sglenn.lagasse@oracle.com if ((ret = be_get_uuid(zfs_get_name(be_zhp), &azr_data.parent_uuid)) 117*13013Sglenn.lagasse@oracle.com != BE_SUCCESS) { 118*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_find_active_zone_root: failed to " 119*13013Sglenn.lagasse@oracle.com "get uuid for BE root dataset %s\n"), zfs_get_name(be_zhp)); 120*13013Sglenn.lagasse@oracle.com return (ret); 121*13013Sglenn.lagasse@oracle.com } 122*13013Sglenn.lagasse@oracle.com 123*13013Sglenn.lagasse@oracle.com /* Generate string for the root container dataset for this zone. */ 124*13013Sglenn.lagasse@oracle.com be_make_container_ds(zonepath_ds, zone_container_ds, 125*13013Sglenn.lagasse@oracle.com sizeof (zone_container_ds)); 126*13013Sglenn.lagasse@oracle.com 127*13013Sglenn.lagasse@oracle.com /* Get handle to this zone's root container dataset */ 128*13013Sglenn.lagasse@oracle.com if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM)) 129*13013Sglenn.lagasse@oracle.com == NULL) { 130*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_find_active_zone_root: failed to " 131*13013Sglenn.lagasse@oracle.com "open zone root container dataset (%s): %s\n"), 132*13013Sglenn.lagasse@oracle.com zone_container_ds, libzfs_error_description(g_zfs)); 133*13013Sglenn.lagasse@oracle.com return (zfs_err_to_be_err(g_zfs)); 134*13013Sglenn.lagasse@oracle.com } 135*13013Sglenn.lagasse@oracle.com 136*13013Sglenn.lagasse@oracle.com /* 137*13013Sglenn.lagasse@oracle.com * Iterate through all of this zone's BEs, looking for ones 138*13013Sglenn.lagasse@oracle.com * that belong to the parent global BE, and finding the one 139*13013Sglenn.lagasse@oracle.com * that is marked active. 140*13013Sglenn.lagasse@oracle.com */ 141*13013Sglenn.lagasse@oracle.com if ((ret = zfs_iter_filesystems(zhp, be_find_active_zone_root_callback, 142*13013Sglenn.lagasse@oracle.com &azr_data)) != 0) { 143*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_find_active_zone_root: failed to " 144*13013Sglenn.lagasse@oracle.com "find active zone root in zonepath dataset %s: %s\n"), 145*13013Sglenn.lagasse@oracle.com zonepath_ds, be_err_to_str(ret)); 146*13013Sglenn.lagasse@oracle.com goto done; 147*13013Sglenn.lagasse@oracle.com } 148*13013Sglenn.lagasse@oracle.com 149*13013Sglenn.lagasse@oracle.com if (azr_data.zoneroot_ds != NULL) { 150*13013Sglenn.lagasse@oracle.com (void) strlcpy(zoneroot_ds, azr_data.zoneroot_ds, 151*13013Sglenn.lagasse@oracle.com zoneroot_ds_size); 152*13013Sglenn.lagasse@oracle.com free(azr_data.zoneroot_ds); 153*13013Sglenn.lagasse@oracle.com } else { 154*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_find_active_zone_root: failed to " 155*13013Sglenn.lagasse@oracle.com "find active zone root in zonepath dataset %s\n"), 156*13013Sglenn.lagasse@oracle.com zonepath_ds); 157*13013Sglenn.lagasse@oracle.com ret = BE_ERR_ZONE_NO_ACTIVE_ROOT; 158*13013Sglenn.lagasse@oracle.com } 159*13013Sglenn.lagasse@oracle.com 160*13013Sglenn.lagasse@oracle.com done: 161*13013Sglenn.lagasse@oracle.com ZFS_CLOSE(zhp); 162*13013Sglenn.lagasse@oracle.com return (ret); 163*13013Sglenn.lagasse@oracle.com } 164*13013Sglenn.lagasse@oracle.com 165*13013Sglenn.lagasse@oracle.com /* 166*13013Sglenn.lagasse@oracle.com * Function: be_find_mounted_zone_root 167*13013Sglenn.lagasse@oracle.com * Description: This function will find the dataset mounted as the zoneroot 168*13013Sglenn.lagasse@oracle.com * of a zone for a given mounted global BE. 169*13013Sglenn.lagasse@oracle.com * Parameters: 170*13013Sglenn.lagasse@oracle.com * zone_altroot - path of zoneroot wrt the mounted global BE. 171*13013Sglenn.lagasse@oracle.com * zonepath_ds - dataset of the zone's zonepath. 172*13013Sglenn.lagasse@oracle.com * zoneroot_ds - pointer to a buffer to store the dataset of 173*13013Sglenn.lagasse@oracle.com * the zoneroot that currently mounted for this zone 174*13013Sglenn.lagasse@oracle.com * in the mounted global BE. 175*13013Sglenn.lagasse@oracle.com * zoneroot_ds_size - size of zoneroot_ds 176*13013Sglenn.lagasse@oracle.com * Returns: 177*13013Sglenn.lagasse@oracle.com * BE_SUCCESS - Success 178*13013Sglenn.lagasse@oracle.com * be_errno_t - Failure 179*13013Sglenn.lagasse@oracle.com * Scope: 180*13013Sglenn.lagasse@oracle.com * Semi-private (library wide use only) 181*13013Sglenn.lagasse@oracle.com */ 182*13013Sglenn.lagasse@oracle.com int 183*13013Sglenn.lagasse@oracle.com be_find_mounted_zone_root(char *zone_altroot, char *zonepath_ds, 184*13013Sglenn.lagasse@oracle.com char *zoneroot_ds, int zoneroot_ds_size) 185*13013Sglenn.lagasse@oracle.com { 186*13013Sglenn.lagasse@oracle.com mounted_zone_root_data_t mzr_data = { 0 }; 187*13013Sglenn.lagasse@oracle.com zfs_handle_t *zhp = NULL; 188*13013Sglenn.lagasse@oracle.com char zone_container_ds[MAXPATHLEN]; 189*13013Sglenn.lagasse@oracle.com int ret = BE_SUCCESS; 190*13013Sglenn.lagasse@oracle.com int zret = 0; 191*13013Sglenn.lagasse@oracle.com 192*13013Sglenn.lagasse@oracle.com /* Generate string for the root container dataset for this zone. */ 193*13013Sglenn.lagasse@oracle.com be_make_container_ds(zonepath_ds, zone_container_ds, 194*13013Sglenn.lagasse@oracle.com sizeof (zone_container_ds)); 195*13013Sglenn.lagasse@oracle.com 196*13013Sglenn.lagasse@oracle.com /* Get handle to this zone's root container dataset. */ 197*13013Sglenn.lagasse@oracle.com if ((zhp = zfs_open(g_zfs, zone_container_ds, ZFS_TYPE_FILESYSTEM)) 198*13013Sglenn.lagasse@oracle.com == NULL) { 199*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_find_mounted_zone_root: failed to " 200*13013Sglenn.lagasse@oracle.com "open zone root container dataset (%s): %s\n"), 201*13013Sglenn.lagasse@oracle.com zone_container_ds, libzfs_error_description(g_zfs)); 202*13013Sglenn.lagasse@oracle.com return (zfs_err_to_be_err(g_zfs)); 203*13013Sglenn.lagasse@oracle.com } 204*13013Sglenn.lagasse@oracle.com 205*13013Sglenn.lagasse@oracle.com mzr_data.zone_altroot = zone_altroot; 206*13013Sglenn.lagasse@oracle.com 207*13013Sglenn.lagasse@oracle.com /* 208*13013Sglenn.lagasse@oracle.com * Iterate through all of the zone's BEs, looking for the one 209*13013Sglenn.lagasse@oracle.com * that is currently mounted at the zone altroot in the mounted 210*13013Sglenn.lagasse@oracle.com * global BE. 211*13013Sglenn.lagasse@oracle.com */ 212*13013Sglenn.lagasse@oracle.com if ((zret = zfs_iter_filesystems(zhp, 213*13013Sglenn.lagasse@oracle.com be_find_mounted_zone_root_callback, &mzr_data)) == 0) { 214*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_find_mounted_zone_root: did not " 215*13013Sglenn.lagasse@oracle.com "find mounted zone under altroot zonepath %s\n"), 216*13013Sglenn.lagasse@oracle.com zonepath_ds); 217*13013Sglenn.lagasse@oracle.com ret = BE_ERR_NO_MOUNTED_ZONE; 218*13013Sglenn.lagasse@oracle.com goto done; 219*13013Sglenn.lagasse@oracle.com } else if (zret < 0) { 220*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_find_mounted_zone_root: " 221*13013Sglenn.lagasse@oracle.com "zfs_iter_filesystems failed: %s\n"), 222*13013Sglenn.lagasse@oracle.com libzfs_error_description(g_zfs)); 223*13013Sglenn.lagasse@oracle.com ret = zfs_err_to_be_err(g_zfs); 224*13013Sglenn.lagasse@oracle.com goto done; 225*13013Sglenn.lagasse@oracle.com } 226*13013Sglenn.lagasse@oracle.com 227*13013Sglenn.lagasse@oracle.com if (mzr_data.zoneroot_ds != NULL) { 228*13013Sglenn.lagasse@oracle.com (void) strlcpy(zoneroot_ds, mzr_data.zoneroot_ds, 229*13013Sglenn.lagasse@oracle.com zoneroot_ds_size); 230*13013Sglenn.lagasse@oracle.com free(mzr_data.zoneroot_ds); 231*13013Sglenn.lagasse@oracle.com } 232*13013Sglenn.lagasse@oracle.com 233*13013Sglenn.lagasse@oracle.com done: 234*13013Sglenn.lagasse@oracle.com ZFS_CLOSE(zhp); 235*13013Sglenn.lagasse@oracle.com return (ret); 236*13013Sglenn.lagasse@oracle.com } 237*13013Sglenn.lagasse@oracle.com 238*13013Sglenn.lagasse@oracle.com /* 239*13013Sglenn.lagasse@oracle.com * Function: be_zone_supported 240*13013Sglenn.lagasse@oracle.com * Description: This function will determine if a zone is supported 241*13013Sglenn.lagasse@oracle.com * based on its zonepath dataset. The zonepath dataset 242*13013Sglenn.lagasse@oracle.com * must: 243*13013Sglenn.lagasse@oracle.com * - not be under any global BE root dataset. 244*13013Sglenn.lagasse@oracle.com * - have a root container dataset underneath it. 245*13013Sglenn.lagasse@oracle.com * 246*13013Sglenn.lagasse@oracle.com * Parameters: 247*13013Sglenn.lagasse@oracle.com * zonepath_ds - name of dataset of the zonepath of the 248*13013Sglenn.lagasse@oracle.com * zone to check. 249*13013Sglenn.lagasse@oracle.com * Returns: 250*13013Sglenn.lagasse@oracle.com * B_TRUE - zone is supported 251*13013Sglenn.lagasse@oracle.com * B_FALSE - zone is not supported 252*13013Sglenn.lagasse@oracle.com * Scope: 253*13013Sglenn.lagasse@oracle.com * Semi-private (library wide use only) 254*13013Sglenn.lagasse@oracle.com */ 255*13013Sglenn.lagasse@oracle.com boolean_t 256*13013Sglenn.lagasse@oracle.com be_zone_supported(char *zonepath_ds) 257*13013Sglenn.lagasse@oracle.com { 258*13013Sglenn.lagasse@oracle.com char zone_container_ds[MAXPATHLEN]; 259*13013Sglenn.lagasse@oracle.com int ret = 0; 260*13013Sglenn.lagasse@oracle.com 261*13013Sglenn.lagasse@oracle.com /* 262*13013Sglenn.lagasse@oracle.com * Make sure the dataset for the zonepath is not hierarchically 263*13013Sglenn.lagasse@oracle.com * under any reserved BE root container dataset of any pool. 264*13013Sglenn.lagasse@oracle.com */ 265*13013Sglenn.lagasse@oracle.com if ((ret = zpool_iter(g_zfs, be_check_be_roots_callback, 266*13013Sglenn.lagasse@oracle.com zonepath_ds)) > 0) { 267*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_zone_supported: " 268*13013Sglenn.lagasse@oracle.com "zonepath dataset %s not supported\n"), zonepath_ds); 269*13013Sglenn.lagasse@oracle.com return (B_FALSE); 270*13013Sglenn.lagasse@oracle.com } else if (ret < 0) { 271*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_zone_supported: " 272*13013Sglenn.lagasse@oracle.com "zpool_iter failed: %s\n"), 273*13013Sglenn.lagasse@oracle.com libzfs_error_description(g_zfs)); 274*13013Sglenn.lagasse@oracle.com return (B_FALSE); 275*13013Sglenn.lagasse@oracle.com } 276*13013Sglenn.lagasse@oracle.com 277*13013Sglenn.lagasse@oracle.com /* 278*13013Sglenn.lagasse@oracle.com * Make sure the zonepath has a zone root container dataset 279*13013Sglenn.lagasse@oracle.com * underneath it. 280*13013Sglenn.lagasse@oracle.com */ 281*13013Sglenn.lagasse@oracle.com be_make_container_ds(zonepath_ds, zone_container_ds, 282*13013Sglenn.lagasse@oracle.com sizeof (zone_container_ds)); 283*13013Sglenn.lagasse@oracle.com 284*13013Sglenn.lagasse@oracle.com if (!zfs_dataset_exists(g_zfs, zone_container_ds, 285*13013Sglenn.lagasse@oracle.com ZFS_TYPE_FILESYSTEM)) { 286*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_zone_supported: " 287*13013Sglenn.lagasse@oracle.com "zonepath dataset (%s) does not have a zone root container " 288*13013Sglenn.lagasse@oracle.com "dataset, zone is not supported, skipping ...\n"), 289*13013Sglenn.lagasse@oracle.com zonepath_ds); 290*13013Sglenn.lagasse@oracle.com return (B_FALSE); 291*13013Sglenn.lagasse@oracle.com } 292*13013Sglenn.lagasse@oracle.com 293*13013Sglenn.lagasse@oracle.com return (B_TRUE); 294*13013Sglenn.lagasse@oracle.com } 295*13013Sglenn.lagasse@oracle.com 296*13013Sglenn.lagasse@oracle.com /* 297*13013Sglenn.lagasse@oracle.com * Function: be_get_supported_brandlist 298*13013Sglenn.lagasse@oracle.com * Desciption: This functions retuns a list of supported brands in 299*13013Sglenn.lagasse@oracle.com * a zoneBrandList_t object. 300*13013Sglenn.lagasse@oracle.com * Parameters: 301*13013Sglenn.lagasse@oracle.com * None 302*13013Sglenn.lagasse@oracle.com * Returns: 303*13013Sglenn.lagasse@oracle.com * Failure - NULL if no supported brands found. 304*13013Sglenn.lagasse@oracle.com * Success - pointer to zoneBrandList structure. 305*13013Sglenn.lagasse@oracle.com * Scope: 306*13013Sglenn.lagasse@oracle.com * Semi-private (library wide use only) 307*13013Sglenn.lagasse@oracle.com */ 308*13013Sglenn.lagasse@oracle.com zoneBrandList_t * 309*13013Sglenn.lagasse@oracle.com be_get_supported_brandlist(void) 310*13013Sglenn.lagasse@oracle.com { 311*13013Sglenn.lagasse@oracle.com return (z_make_brand_list(BE_ZONE_SUPPORTED_BRANDS, 312*13013Sglenn.lagasse@oracle.com BE_ZONE_SUPPORTED_BRANDS_DELIM)); 313*13013Sglenn.lagasse@oracle.com } 314*13013Sglenn.lagasse@oracle.com 315*13013Sglenn.lagasse@oracle.com /* 316*13013Sglenn.lagasse@oracle.com * Function: be_zone_get_parent_uuid 317*13013Sglenn.lagasse@oracle.com * Description: This function gets the parentbe property of a zone root 318*13013Sglenn.lagasse@oracle.com * dataset, parsed it into internal uuid format, and returns 319*13013Sglenn.lagasse@oracle.com * it in the uuid_t reference pointer passed in. 320*13013Sglenn.lagasse@oracle.com * Parameters: 321*13013Sglenn.lagasse@oracle.com * root_ds - dataset name of a zone root dataset 322*13013Sglenn.lagasse@oracle.com * uu - pointer to a uuid_t to return the parentbe uuid in 323*13013Sglenn.lagasse@oracle.com * Returns: 324*13013Sglenn.lagasse@oracle.com * BE_SUCCESS - Success 325*13013Sglenn.lagasse@oracle.com * be_errno_t - Failure 326*13013Sglenn.lagasse@oracle.com * Scope: 327*13013Sglenn.lagasse@oracle.com * Private 328*13013Sglenn.lagasse@oracle.com */ 329*13013Sglenn.lagasse@oracle.com int 330*13013Sglenn.lagasse@oracle.com be_zone_get_parent_uuid(const char *root_ds, uuid_t *uu) 331*13013Sglenn.lagasse@oracle.com { 332*13013Sglenn.lagasse@oracle.com zfs_handle_t *zhp = NULL; 333*13013Sglenn.lagasse@oracle.com nvlist_t *userprops = NULL; 334*13013Sglenn.lagasse@oracle.com nvlist_t *propname = NULL; 335*13013Sglenn.lagasse@oracle.com char *uu_string = NULL; 336*13013Sglenn.lagasse@oracle.com int ret = BE_SUCCESS; 337*13013Sglenn.lagasse@oracle.com 338*13013Sglenn.lagasse@oracle.com /* Get handle to zone root dataset */ 339*13013Sglenn.lagasse@oracle.com if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) == NULL) { 340*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_zone_get_parent_uuid: failed to " 341*13013Sglenn.lagasse@oracle.com "open zone root dataset (%s): %s\n"), root_ds, 342*13013Sglenn.lagasse@oracle.com libzfs_error_description(g_zfs)); 343*13013Sglenn.lagasse@oracle.com return (zfs_err_to_be_err(g_zfs)); 344*13013Sglenn.lagasse@oracle.com } 345*13013Sglenn.lagasse@oracle.com 346*13013Sglenn.lagasse@oracle.com /* Get user properties for zone root dataset */ 347*13013Sglenn.lagasse@oracle.com if ((userprops = zfs_get_user_props(zhp)) == NULL) { 348*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_zone_get_parent_uuid: " 349*13013Sglenn.lagasse@oracle.com "failed to get user properties for zone root " 350*13013Sglenn.lagasse@oracle.com "dataset (%s): %s\n"), root_ds, 351*13013Sglenn.lagasse@oracle.com libzfs_error_description(g_zfs)); 352*13013Sglenn.lagasse@oracle.com ret = zfs_err_to_be_err(g_zfs); 353*13013Sglenn.lagasse@oracle.com goto done; 354*13013Sglenn.lagasse@oracle.com } 355*13013Sglenn.lagasse@oracle.com 356*13013Sglenn.lagasse@oracle.com /* Get UUID string from zone's root dataset user properties */ 357*13013Sglenn.lagasse@oracle.com if (nvlist_lookup_nvlist(userprops, BE_ZONE_PARENTBE_PROPERTY, 358*13013Sglenn.lagasse@oracle.com &propname) != 0 || nvlist_lookup_string(propname, ZPROP_VALUE, 359*13013Sglenn.lagasse@oracle.com &uu_string) != 0) { 360*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_zone_get_parent_uuid: failed to " 361*13013Sglenn.lagasse@oracle.com "get parent uuid property from zone root dataset user " 362*13013Sglenn.lagasse@oracle.com "properties.\n")); 363*13013Sglenn.lagasse@oracle.com ret = BE_ERR_ZONE_NO_PARENTBE; 364*13013Sglenn.lagasse@oracle.com goto done; 365*13013Sglenn.lagasse@oracle.com } 366*13013Sglenn.lagasse@oracle.com 367*13013Sglenn.lagasse@oracle.com /* Parse the uuid string into internal format */ 368*13013Sglenn.lagasse@oracle.com if (uuid_parse(uu_string, *uu) != 0 || uuid_is_null(*uu)) { 369*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_zone_get_parent_uuid: failed to " 370*13013Sglenn.lagasse@oracle.com "parse parentuuid\n")); 371*13013Sglenn.lagasse@oracle.com ret = BE_ERR_PARSE_UUID; 372*13013Sglenn.lagasse@oracle.com } 373*13013Sglenn.lagasse@oracle.com 374*13013Sglenn.lagasse@oracle.com done: 375*13013Sglenn.lagasse@oracle.com ZFS_CLOSE(zhp); 376*13013Sglenn.lagasse@oracle.com return (ret); 377*13013Sglenn.lagasse@oracle.com } 378*13013Sglenn.lagasse@oracle.com 379*13013Sglenn.lagasse@oracle.com /* ******************************************************************** */ 380*13013Sglenn.lagasse@oracle.com /* Private Functions */ 381*13013Sglenn.lagasse@oracle.com /* ******************************************************************** */ 382*13013Sglenn.lagasse@oracle.com 383*13013Sglenn.lagasse@oracle.com /* 384*13013Sglenn.lagasse@oracle.com * Function: be_find_active_zone_root_callback 385*13013Sglenn.lagasse@oracle.com * Description: This function is used as a callback to iterate over all of 386*13013Sglenn.lagasse@oracle.com * a zone's root datasets, finding the one that is marked active 387*13013Sglenn.lagasse@oracle.com * for the parent BE specified in the data passed in. The name 388*13013Sglenn.lagasse@oracle.com * of the zone's active root dataset is returned in heap storage 389*13013Sglenn.lagasse@oracle.com * in the active_zone_root_data_t structure passed in, so the 390*13013Sglenn.lagasse@oracle.com * caller is responsible for freeing it. 391*13013Sglenn.lagasse@oracle.com * Parameters: 392*13013Sglenn.lagasse@oracle.com * zhp - zfs_handle_t pointer to current dataset being processed 393*13013Sglenn.lagasse@oracle.com * data - active_zone_root_data_t pointer 394*13013Sglenn.lagasse@oracle.com * Returns: 395*13013Sglenn.lagasse@oracle.com * 0 - Success 396*13013Sglenn.lagasse@oracle.com * >0 - Failure 397*13013Sglenn.lagasse@oracle.com * Scope: 398*13013Sglenn.lagasse@oracle.com * Private 399*13013Sglenn.lagasse@oracle.com */ 400*13013Sglenn.lagasse@oracle.com static int 401*13013Sglenn.lagasse@oracle.com be_find_active_zone_root_callback(zfs_handle_t *zhp, void *data) 402*13013Sglenn.lagasse@oracle.com { 403*13013Sglenn.lagasse@oracle.com active_zone_root_data_t *azr_data = data; 404*13013Sglenn.lagasse@oracle.com uuid_t parent_uuid = { 0 }; 405*13013Sglenn.lagasse@oracle.com int iret = 0; 406*13013Sglenn.lagasse@oracle.com int ret = 0; 407*13013Sglenn.lagasse@oracle.com 408*13013Sglenn.lagasse@oracle.com if ((iret = be_zone_get_parent_uuid(zfs_get_name(zhp), &parent_uuid)) 409*13013Sglenn.lagasse@oracle.com != BE_SUCCESS) { 410*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_find_active_zone_root_callback: " 411*13013Sglenn.lagasse@oracle.com "skipping zone root dataset (%s): %s\n"), 412*13013Sglenn.lagasse@oracle.com zfs_get_name(zhp), be_err_to_str(iret)); 413*13013Sglenn.lagasse@oracle.com goto done; 414*13013Sglenn.lagasse@oracle.com } 415*13013Sglenn.lagasse@oracle.com 416*13013Sglenn.lagasse@oracle.com if (uuid_compare(azr_data->parent_uuid, parent_uuid) == 0) { 417*13013Sglenn.lagasse@oracle.com /* 418*13013Sglenn.lagasse@oracle.com * Found a zone root dataset belonging to the right parent, 419*13013Sglenn.lagasse@oracle.com * check if its active. 420*13013Sglenn.lagasse@oracle.com */ 421*13013Sglenn.lagasse@oracle.com if (be_zone_get_active(zhp)) { 422*13013Sglenn.lagasse@oracle.com /* 423*13013Sglenn.lagasse@oracle.com * Found active zone root dataset, if its already 424*13013Sglenn.lagasse@oracle.com * set in the callback data, that means this 425*13013Sglenn.lagasse@oracle.com * is the second one we've found. Return error. 426*13013Sglenn.lagasse@oracle.com */ 427*13013Sglenn.lagasse@oracle.com if (azr_data->zoneroot_ds != NULL) { 428*13013Sglenn.lagasse@oracle.com ret = BE_ERR_ZONE_MULTIPLE_ACTIVE; 429*13013Sglenn.lagasse@oracle.com goto done; 430*13013Sglenn.lagasse@oracle.com } 431*13013Sglenn.lagasse@oracle.com 432*13013Sglenn.lagasse@oracle.com azr_data->zoneroot_ds = strdup(zfs_get_name(zhp)); 433*13013Sglenn.lagasse@oracle.com if (azr_data->zoneroot_ds == NULL) { 434*13013Sglenn.lagasse@oracle.com ret = BE_ERR_NOMEM; 435*13013Sglenn.lagasse@oracle.com } 436*13013Sglenn.lagasse@oracle.com } 437*13013Sglenn.lagasse@oracle.com } 438*13013Sglenn.lagasse@oracle.com 439*13013Sglenn.lagasse@oracle.com done: 440*13013Sglenn.lagasse@oracle.com ZFS_CLOSE(zhp); 441*13013Sglenn.lagasse@oracle.com return (ret); 442*13013Sglenn.lagasse@oracle.com } 443*13013Sglenn.lagasse@oracle.com 444*13013Sglenn.lagasse@oracle.com /* 445*13013Sglenn.lagasse@oracle.com * Function: be_find_mounted_zone_root_callback 446*13013Sglenn.lagasse@oracle.com * Description: This function is used as a callback to iterate over all of 447*13013Sglenn.lagasse@oracle.com * a zone's root datasets, find the one that is currently 448*13013Sglenn.lagasse@oracle.com * mounted for the parent BE specified in the data passed in. 449*13013Sglenn.lagasse@oracle.com * The name of the zone's mounted root dataset is returned in 450*13013Sglenn.lagasse@oracle.com * heap storage the mounted_zone_data_t structure passed in, 451*13013Sglenn.lagasse@oracle.com * so the caller is responsible for freeing it. 452*13013Sglenn.lagasse@oracle.com * Parameters: 453*13013Sglenn.lagasse@oracle.com * zhp - zfs_handle_t pointer to the current dataset being 454*13013Sglenn.lagasse@oracle.com * processed 455*13013Sglenn.lagasse@oracle.com * data - mounted_zone_data_t pointer 456*13013Sglenn.lagasse@oracle.com * Returns: 457*13013Sglenn.lagasse@oracle.com * 0 - not mounted as zone's root 458*13013Sglenn.lagasse@oracle.com * 1 - this dataset is mounted as zone's root 459*13013Sglenn.lagasse@oracle.com * Scope: 460*13013Sglenn.lagasse@oracle.com * Private 461*13013Sglenn.lagasse@oracle.com */ 462*13013Sglenn.lagasse@oracle.com static int 463*13013Sglenn.lagasse@oracle.com be_find_mounted_zone_root_callback(zfs_handle_t *zhp, void *data) 464*13013Sglenn.lagasse@oracle.com { 465*13013Sglenn.lagasse@oracle.com mounted_zone_root_data_t *mzr_data = data; 466*13013Sglenn.lagasse@oracle.com char *mp = NULL; 467*13013Sglenn.lagasse@oracle.com 468*13013Sglenn.lagasse@oracle.com if (zfs_is_mounted(zhp, &mp) && mp != NULL && 469*13013Sglenn.lagasse@oracle.com strcmp(mp, mzr_data->zone_altroot) == 0) { 470*13013Sglenn.lagasse@oracle.com mzr_data->zoneroot_ds = strdup(zfs_get_name(zhp)); 471*13013Sglenn.lagasse@oracle.com free(mp); 472*13013Sglenn.lagasse@oracle.com return (1); 473*13013Sglenn.lagasse@oracle.com } 474*13013Sglenn.lagasse@oracle.com 475*13013Sglenn.lagasse@oracle.com free(mp); 476*13013Sglenn.lagasse@oracle.com return (0); 477*13013Sglenn.lagasse@oracle.com } 478*13013Sglenn.lagasse@oracle.com 479*13013Sglenn.lagasse@oracle.com /* 480*13013Sglenn.lagasse@oracle.com * Function: be_zone_get_active 481*13013Sglenn.lagasse@oracle.com * Description: This function gets the active property of a zone root 482*13013Sglenn.lagasse@oracle.com * dataset, and returns true if active property is on. 483*13013Sglenn.lagasse@oracle.com * Parameters: 484*13013Sglenn.lagasse@oracle.com * zfs - zfs_handle_t pointer to zone root dataset to check 485*13013Sglenn.lagasse@oracle.com * Returns: 486*13013Sglenn.lagasse@oracle.com * B_TRUE - zone root dataset is active 487*13013Sglenn.lagasse@oracle.com * B_FALSE - zone root dataset is not active 488*13013Sglenn.lagasse@oracle.com * Scope: 489*13013Sglenn.lagasse@oracle.com * Private 490*13013Sglenn.lagasse@oracle.com */ 491*13013Sglenn.lagasse@oracle.com static boolean_t 492*13013Sglenn.lagasse@oracle.com be_zone_get_active(zfs_handle_t *zhp) 493*13013Sglenn.lagasse@oracle.com { 494*13013Sglenn.lagasse@oracle.com nvlist_t *userprops = NULL; 495*13013Sglenn.lagasse@oracle.com nvlist_t *propname = NULL; 496*13013Sglenn.lagasse@oracle.com char *active_str = NULL; 497*13013Sglenn.lagasse@oracle.com 498*13013Sglenn.lagasse@oracle.com /* Get user properties for the zone root dataset */ 499*13013Sglenn.lagasse@oracle.com if ((userprops = zfs_get_user_props(zhp)) == NULL) { 500*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_zone_get_active: " 501*13013Sglenn.lagasse@oracle.com "failed to get user properties for zone root " 502*13013Sglenn.lagasse@oracle.com "dataset (%s): %s\n"), zfs_get_name(zhp), 503*13013Sglenn.lagasse@oracle.com libzfs_error_description(g_zfs)); 504*13013Sglenn.lagasse@oracle.com return (B_FALSE); 505*13013Sglenn.lagasse@oracle.com } 506*13013Sglenn.lagasse@oracle.com 507*13013Sglenn.lagasse@oracle.com /* Get active property from the zone root dataset user properties */ 508*13013Sglenn.lagasse@oracle.com if (nvlist_lookup_nvlist(userprops, BE_ZONE_ACTIVE_PROPERTY, &propname) 509*13013Sglenn.lagasse@oracle.com != 0 || nvlist_lookup_string(propname, ZPROP_VALUE, &active_str) 510*13013Sglenn.lagasse@oracle.com != 0) { 511*13013Sglenn.lagasse@oracle.com return (B_FALSE); 512*13013Sglenn.lagasse@oracle.com } 513*13013Sglenn.lagasse@oracle.com 514*13013Sglenn.lagasse@oracle.com if (strcmp(active_str, "on") == 0) 515*13013Sglenn.lagasse@oracle.com return (B_TRUE); 516*13013Sglenn.lagasse@oracle.com 517*13013Sglenn.lagasse@oracle.com return (B_FALSE); 518*13013Sglenn.lagasse@oracle.com } 519