xref: /onnv-gate/usr/src/lib/libbe/common/be_zones.c (revision 13013:3c7681e3e323)
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
be_make_zoneroot(char * zonepath,char * zoneroot,int zoneroot_size)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
be_find_active_zone_root(zfs_handle_t * be_zhp,char * zonepath_ds,char * zoneroot_ds,int zoneroot_ds_size)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
be_find_mounted_zone_root(char * zone_altroot,char * zonepath_ds,char * zoneroot_ds,int zoneroot_ds_size)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
be_zone_supported(char * zonepath_ds)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 *
be_get_supported_brandlist(void)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
be_zone_get_parent_uuid(const char * root_ds,uuid_t * uu)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
be_find_active_zone_root_callback(zfs_handle_t * zhp,void * data)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
be_find_mounted_zone_root_callback(zfs_handle_t * zhp,void * data)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
be_zone_get_active(zfs_handle_t * zhp)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