17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
599653d4eSeschrock  * Common Development and Distribution License (the "License").
699653d4eSeschrock  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <fcntl.h>
277c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
343e1bd7a2Ssjelinek #include <libintl.h>
353e1bd7a2Ssjelinek #include <locale.h>
363e1bd7a2Ssjelinek #include <sys/debug.h>
37181c2f42Smmusante #include <strings.h>
38181c2f42Smmusante #include <sys/stat.h>
39181c2f42Smmusante #include <sys/swap.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include "libdiskmgt.h"
427c478bd9Sstevel@tonic-gate #include "disks_private.h"
437c478bd9Sstevel@tonic-gate #include "partition.h"
447c478bd9Sstevel@tonic-gate 
45181c2f42Smmusante #define	ANY_ZPOOL_USE(who) \
46181c2f42Smmusante 	(((who) == DM_WHO_ZPOOL_FORCE) || \
47181c2f42Smmusante 	((who) == DM_WHO_ZPOOL) || \
48181c2f42Smmusante 	((who) == DM_WHO_ZPOOL_SPARE))
493e1bd7a2Ssjelinek 
50181c2f42Smmusante extern	char	*getfullblkname();
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate extern dm_desc_type_t drive_assoc_types[];
537c478bd9Sstevel@tonic-gate extern dm_desc_type_t bus_assoc_types[];
547c478bd9Sstevel@tonic-gate extern dm_desc_type_t controller_assoc_types[];
557c478bd9Sstevel@tonic-gate extern dm_desc_type_t media_assoc_types[];
567c478bd9Sstevel@tonic-gate extern dm_desc_type_t slice_assoc_types[];
577c478bd9Sstevel@tonic-gate extern dm_desc_type_t partition_assoc_types[];
587c478bd9Sstevel@tonic-gate extern dm_desc_type_t path_assoc_types[];
597c478bd9Sstevel@tonic-gate extern dm_desc_type_t alias_assoc_types[];
607c478bd9Sstevel@tonic-gate 
613e1bd7a2Ssjelinek 
627c478bd9Sstevel@tonic-gate static dm_descriptor_t *ptr_array_to_desc_array(descriptor_t **ptrs, int *errp);
637c478bd9Sstevel@tonic-gate static descriptor_t **desc_array_to_ptr_array(dm_descriptor_t *da, int *errp);
643e1bd7a2Ssjelinek static int build_usage_string(char *dname, char *by, char *data, char **use,
653e1bd7a2Ssjelinek 	int *found, int *errp);
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate void
687c478bd9Sstevel@tonic-gate dm_free_descriptor(dm_descriptor_t desc)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	if (desc == NULL) {
73*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return;
747c478bd9Sstevel@tonic-gate 	}
7569fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	cache_wlock();
787c478bd9Sstevel@tonic-gate 	cache_free_descriptor(dp);
797c478bd9Sstevel@tonic-gate 	cache_unlock();
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate void
837c478bd9Sstevel@tonic-gate dm_free_descriptors(dm_descriptor_t *desc_list)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	descriptor_t	**dp;
867c478bd9Sstevel@tonic-gate 	int		error;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	if (desc_list == NULL) {
89*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return;
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate 	dp = desc_array_to_ptr_array(desc_list, &error);
927c478bd9Sstevel@tonic-gate 	if (error != 0) {
93*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		free(desc_list);
94*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return;
957c478bd9Sstevel@tonic-gate 	}
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	cache_wlock();
987c478bd9Sstevel@tonic-gate 	cache_free_descriptors(dp);
997c478bd9Sstevel@tonic-gate 	cache_unlock();
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1037c478bd9Sstevel@tonic-gate void
1047c478bd9Sstevel@tonic-gate dm_free_name(char *name)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate 	free(name);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate dm_descriptor_t *
1107c478bd9Sstevel@tonic-gate dm_get_associated_descriptors(dm_descriptor_t desc, dm_desc_type_t type,
1117c478bd9Sstevel@tonic-gate     int *errp)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate 	descriptor_t **descs = NULL;
1147c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 
11769fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	cache_wlock();
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
122*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		cache_unlock();
123*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = EBADF;
124*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
1257c478bd9Sstevel@tonic-gate 	}
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
1287c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
129*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		cache_unlock();
130*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = ENODEV;
131*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
1327c478bd9Sstevel@tonic-gate 	}
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	switch (dp->type) {
1357c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
136*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = drive_get_assoc_descriptors(dp, type, errp);
137*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1387c478bd9Sstevel@tonic-gate 	case DM_BUS:
139*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = bus_get_assoc_descriptors(dp, type, errp);
140*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1417c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
142*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = controller_get_assoc_descriptors(dp, type, errp);
143*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1447c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
145*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = media_get_assoc_descriptors(dp, type, errp);
146*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1477c478bd9Sstevel@tonic-gate 	case DM_SLICE:
148*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = slice_get_assoc_descriptors(dp, type, errp);
149*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1507c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
151*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = partition_get_assoc_descriptors(dp, type, errp);
152*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1537c478bd9Sstevel@tonic-gate 	case DM_PATH:
154*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = path_get_assoc_descriptors(dp, type, errp);
155*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1567c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
157*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = alias_get_assoc_descriptors(dp, type, errp);
158*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1597c478bd9Sstevel@tonic-gate 	default:
160*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = EINVAL;
161*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	cache_unlock();
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	return (ptr_array_to_desc_array(descs, errp));
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate dm_desc_type_t *
1707c478bd9Sstevel@tonic-gate dm_get_associated_types(dm_desc_type_t type)
1717c478bd9Sstevel@tonic-gate {
1727c478bd9Sstevel@tonic-gate 	switch (type) {
1737c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
174*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (drive_assoc_types);
1757c478bd9Sstevel@tonic-gate 	case DM_BUS:
176*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (bus_assoc_types);
1777c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
178*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (controller_assoc_types);
1797c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
180*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (media_assoc_types);
1817c478bd9Sstevel@tonic-gate 	case DM_SLICE:
182*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (slice_assoc_types);
1837c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
184*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (partition_assoc_types);
1857c478bd9Sstevel@tonic-gate 	case DM_PATH:
186*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (path_assoc_types);
1877c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
188*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (alias_assoc_types);
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	return (NULL);
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate nvlist_t *
1957c478bd9Sstevel@tonic-gate dm_get_attributes(dm_descriptor_t desc, int *errp)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
1987c478bd9Sstevel@tonic-gate 	nvlist_t	*attrs = NULL;
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 
20169fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	cache_rlock();
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
206*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		cache_unlock();
207*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = EBADF;
208*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
2127c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
213*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		cache_unlock();
214*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = ENODEV;
215*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	switch (dp->type) {
2197c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
220*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		attrs = drive_get_attributes(dp, errp);
221*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2227c478bd9Sstevel@tonic-gate 	case DM_BUS:
223*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		attrs = bus_get_attributes(dp, errp);
224*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2257c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
226*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		attrs = controller_get_attributes(dp, errp);
227*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2287c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
229*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		attrs = media_get_attributes(dp, errp);
230*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2317c478bd9Sstevel@tonic-gate 	case DM_SLICE:
232*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		attrs = slice_get_attributes(dp, errp);
233*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2347c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
235*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		attrs = partition_get_attributes(dp, errp);
236*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2377c478bd9Sstevel@tonic-gate 	case DM_PATH:
238*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		attrs = path_get_attributes(dp, errp);
239*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2407c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
241*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		attrs = alias_get_attributes(dp, errp);
242*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2437c478bd9Sstevel@tonic-gate 	default:
244*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = EINVAL;
245*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	cache_unlock();
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	return (attrs);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate dm_descriptor_t
2547c478bd9Sstevel@tonic-gate dm_get_descriptor_by_name(dm_desc_type_t desc_type, char *name, int *errp)
2557c478bd9Sstevel@tonic-gate {
2567c478bd9Sstevel@tonic-gate 	dm_descriptor_t desc = NULL;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	cache_wlock();
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	switch (desc_type) {
2627c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
263*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		desc = (uintptr_t)drive_get_descriptor_by_name(name, errp);
264*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2657c478bd9Sstevel@tonic-gate 	case DM_BUS:
266*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		desc = (uintptr_t)bus_get_descriptor_by_name(name, errp);
267*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2687c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
269*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		desc = (uintptr_t)controller_get_descriptor_by_name(name,
270*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		    errp);
271*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2727c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
273*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		desc = (uintptr_t)media_get_descriptor_by_name(name, errp);
274*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2757c478bd9Sstevel@tonic-gate 	case DM_SLICE:
276*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		desc = (uintptr_t)slice_get_descriptor_by_name(name, errp);
277*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2787c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
279*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		desc = (uintptr_t)partition_get_descriptor_by_name(name,
280*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		    errp);
281*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2827c478bd9Sstevel@tonic-gate 	case DM_PATH:
283*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		desc = (uintptr_t)path_get_descriptor_by_name(name, errp);
284*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2857c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
286*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		desc = (uintptr_t)alias_get_descriptor_by_name(name, errp);
287*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2887c478bd9Sstevel@tonic-gate 	default:
289*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = EINVAL;
290*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
2917c478bd9Sstevel@tonic-gate 	}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	cache_unlock();
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	return (desc);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate dm_descriptor_t *
2997c478bd9Sstevel@tonic-gate dm_get_descriptors(dm_desc_type_t type, int filter[], int *errp)
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate 	descriptor_t **descs = NULL;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	cache_wlock();
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	switch (type) {
3077c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
308*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = drive_get_descriptors(filter, errp);
309*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3107c478bd9Sstevel@tonic-gate 	case DM_BUS:
311*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = bus_get_descriptors(filter, errp);
312*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3137c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
314*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = controller_get_descriptors(filter, errp);
315*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3167c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
317*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = media_get_descriptors(filter, errp);
318*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3197c478bd9Sstevel@tonic-gate 	case DM_SLICE:
320*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = slice_get_descriptors(filter, errp);
321*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3227c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
323*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = partition_get_descriptors(filter, errp);
324*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3257c478bd9Sstevel@tonic-gate 	case DM_PATH:
326*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = path_get_descriptors(filter, errp);
327*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3287c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
329*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		descs = alias_get_descriptors(filter, errp);
330*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3317c478bd9Sstevel@tonic-gate 	default:
332*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = EINVAL;
333*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	cache_unlock();
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	return (ptr_array_to_desc_array(descs, errp));
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate char *
3427c478bd9Sstevel@tonic-gate dm_get_name(dm_descriptor_t desc, int *errp)
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate 	descriptor_t	*dp;
3457c478bd9Sstevel@tonic-gate 	char		*nm = NULL;
3467c478bd9Sstevel@tonic-gate 	char		*name = NULL;
3477c478bd9Sstevel@tonic-gate 
34869fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	cache_rlock();
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
353*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		cache_unlock();
354*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = EBADF;
355*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
3597c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
360*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		cache_unlock();
361*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = ENODEV;
362*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	switch (dp->type) {
3667c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
367*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		nm = (drive_get_name(dp));
368*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3697c478bd9Sstevel@tonic-gate 	case DM_BUS:
370*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		nm = (bus_get_name(dp));
371*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3727c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
373*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		nm = (controller_get_name(dp));
374*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3757c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
376*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		nm = (media_get_name(dp));
377*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3787c478bd9Sstevel@tonic-gate 	case DM_SLICE:
379*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		nm = (slice_get_name(dp));
380*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3817c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
382*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		nm = (partition_get_name(dp));
383*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3847c478bd9Sstevel@tonic-gate 	case DM_PATH:
385*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		nm = (path_get_name(dp));
386*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3877c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
388*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		nm = (alias_get_name(dp));
389*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		break;
3907c478bd9Sstevel@tonic-gate 	}
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	cache_unlock();
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	*errp = 0;
3957c478bd9Sstevel@tonic-gate 	if (nm != NULL) {
396*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		name = strdup(nm);
397*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		if (name == NULL) {
398*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 			*errp = ENOMEM;
399*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 			return (NULL);
400*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		}
401*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (name);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 	return (NULL);
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate nvlist_t *
4077c478bd9Sstevel@tonic-gate dm_get_stats(dm_descriptor_t desc, int stat_type, int *errp)
4087c478bd9Sstevel@tonic-gate {
4097c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
4107c478bd9Sstevel@tonic-gate 	nvlist_t	*stats = NULL;
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 
41369fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	cache_rlock();
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
4183e1bd7a2Ssjelinek 		cache_unlock();
4193e1bd7a2Ssjelinek 		*errp = EBADF;
4203e1bd7a2Ssjelinek 		return (NULL);
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	/* verify that the descriptor is still valid */
4247c478bd9Sstevel@tonic-gate 	if (dp->p.generic == NULL) {
4253e1bd7a2Ssjelinek 		cache_unlock();
4263e1bd7a2Ssjelinek 		*errp = ENODEV;
4273e1bd7a2Ssjelinek 		return (NULL);
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	switch (dp->type) {
4317c478bd9Sstevel@tonic-gate 	case DM_DRIVE:
4323e1bd7a2Ssjelinek 		stats = drive_get_stats(dp, stat_type, errp);
4333e1bd7a2Ssjelinek 		break;
4347c478bd9Sstevel@tonic-gate 	case DM_BUS:
4353e1bd7a2Ssjelinek 		stats = bus_get_stats(dp, stat_type, errp);
4363e1bd7a2Ssjelinek 		break;
4377c478bd9Sstevel@tonic-gate 	case DM_CONTROLLER:
4383e1bd7a2Ssjelinek 		stats = controller_get_stats(dp, stat_type, errp);
4393e1bd7a2Ssjelinek 		break;
4407c478bd9Sstevel@tonic-gate 	case DM_MEDIA:
4413e1bd7a2Ssjelinek 		stats = media_get_stats(dp, stat_type, errp);
4423e1bd7a2Ssjelinek 		break;
4437c478bd9Sstevel@tonic-gate 	case DM_SLICE:
4443e1bd7a2Ssjelinek 		if (stat_type == DM_SLICE_STAT_USE) {
4453e1bd7a2Ssjelinek 			/*
4463e1bd7a2Ssjelinek 			 * If NOINUSE_CHECK is set, we do not perform
4473e1bd7a2Ssjelinek 			 * the in use checking if the user has set stat_type
4483e1bd7a2Ssjelinek 			 * DM_SLICE_STAT_USE
4493e1bd7a2Ssjelinek 			 */
45082d71480Ssjelinek 			if (NOINUSE_SET) {
4513e1bd7a2Ssjelinek 				stats = NULL;
4523e1bd7a2Ssjelinek 				break;
4533e1bd7a2Ssjelinek 			}
4543e1bd7a2Ssjelinek 		}
4553e1bd7a2Ssjelinek 		stats = slice_get_stats(dp, stat_type, errp);
4563e1bd7a2Ssjelinek 		break;
4577c478bd9Sstevel@tonic-gate 	case DM_PARTITION:
4583e1bd7a2Ssjelinek 		stats = partition_get_stats(dp, stat_type, errp);
4593e1bd7a2Ssjelinek 		break;
4607c478bd9Sstevel@tonic-gate 	case DM_PATH:
4613e1bd7a2Ssjelinek 		stats = path_get_stats(dp, stat_type, errp);
4623e1bd7a2Ssjelinek 		break;
4637c478bd9Sstevel@tonic-gate 	case DM_ALIAS:
4643e1bd7a2Ssjelinek 		stats = alias_get_stats(dp, stat_type, errp);
4653e1bd7a2Ssjelinek 		break;
4667c478bd9Sstevel@tonic-gate 	default:
4673e1bd7a2Ssjelinek 		*errp = EINVAL;
4683e1bd7a2Ssjelinek 		break;
4697c478bd9Sstevel@tonic-gate 	}
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	cache_unlock();
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	return (stats);
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate dm_desc_type_t
4777c478bd9Sstevel@tonic-gate dm_get_type(dm_descriptor_t desc)
4787c478bd9Sstevel@tonic-gate {
4797c478bd9Sstevel@tonic-gate 	descriptor_t  *dp;
4807c478bd9Sstevel@tonic-gate 
48169fb9702Smike_s 	dp = (descriptor_t *)(uintptr_t)desc;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	cache_rlock();
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	if (!cache_is_valid_desc(dp)) {
486*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		cache_unlock();
487*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (-1);
4887c478bd9Sstevel@tonic-gate 	}
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	cache_unlock();
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	return (dp->type);
4937c478bd9Sstevel@tonic-gate }
4943e1bd7a2Ssjelinek /*
4953e1bd7a2Ssjelinek  * Returns, via slices paramater, a dm_descriptor_t list of
4963e1bd7a2Ssjelinek  * slices for the named disk drive.
4973e1bd7a2Ssjelinek  */
4983e1bd7a2Ssjelinek void
4993e1bd7a2Ssjelinek dm_get_slices(char *drive, dm_descriptor_t **slices, int *errp)
5003e1bd7a2Ssjelinek {
5013e1bd7a2Ssjelinek 	dm_descriptor_t alias;
5023e1bd7a2Ssjelinek 	dm_descriptor_t	*media;
5033e1bd7a2Ssjelinek 	dm_descriptor_t *disk;
5047c478bd9Sstevel@tonic-gate 
5053e1bd7a2Ssjelinek 	*slices = NULL;
5063e1bd7a2Ssjelinek 	*errp = 0;
5073e1bd7a2Ssjelinek 
5083e1bd7a2Ssjelinek 	if (drive == NULL) {
5093e1bd7a2Ssjelinek 		return;
5103e1bd7a2Ssjelinek 	}
5113e1bd7a2Ssjelinek 
5123e1bd7a2Ssjelinek 	alias = dm_get_descriptor_by_name(DM_ALIAS, drive, errp);
5133e1bd7a2Ssjelinek 
5143e1bd7a2Ssjelinek 	/*
5153e1bd7a2Ssjelinek 	 * Errors must be handled by the caller. The dm_descriptor_t *
5163e1bd7a2Ssjelinek 	 * values will be NULL if an error occured in these calls.
5173e1bd7a2Ssjelinek 	 */
5183e1bd7a2Ssjelinek 
5193e1bd7a2Ssjelinek 	if (alias != NULL) {
5203e1bd7a2Ssjelinek 		disk = dm_get_associated_descriptors(alias, DM_DRIVE, errp);
5213e1bd7a2Ssjelinek 		dm_free_descriptor(alias);
5223e1bd7a2Ssjelinek 		if (disk != NULL) {
5233e1bd7a2Ssjelinek 			media = dm_get_associated_descriptors(*disk,
5243e1bd7a2Ssjelinek 			    DM_MEDIA, errp);
5253e1bd7a2Ssjelinek 			dm_free_descriptors(disk);
5263e1bd7a2Ssjelinek 			if (media != NULL) {
5273e1bd7a2Ssjelinek 				*slices = dm_get_associated_descriptors(*media,
5283e1bd7a2Ssjelinek 				    DM_SLICE, errp);
5293e1bd7a2Ssjelinek 				dm_free_descriptors(media);
5303e1bd7a2Ssjelinek 			}
5313e1bd7a2Ssjelinek 		}
5323e1bd7a2Ssjelinek 	}
5333e1bd7a2Ssjelinek }
5343e1bd7a2Ssjelinek /*
5353e1bd7a2Ssjelinek  * Convenience function to get slice stats
5363e1bd7a2Ssjelinek  */
5373e1bd7a2Ssjelinek void
5383e1bd7a2Ssjelinek dm_get_slice_stats(char *slice, nvlist_t **dev_stats, int *errp)
5393e1bd7a2Ssjelinek {
5403e1bd7a2Ssjelinek 	dm_descriptor_t	devp;
5413e1bd7a2Ssjelinek 
5423e1bd7a2Ssjelinek 	*dev_stats = NULL;
5433e1bd7a2Ssjelinek 	*errp = 0;
5443e1bd7a2Ssjelinek 
5453e1bd7a2Ssjelinek 	if (slice == NULL) {
5463e1bd7a2Ssjelinek 		return;
5473e1bd7a2Ssjelinek 	}
5483e1bd7a2Ssjelinek 
5493e1bd7a2Ssjelinek 	/*
5503e1bd7a2Ssjelinek 	 * Errors must be handled by the caller. The dm_descriptor_t *
5513e1bd7a2Ssjelinek 	 * values will be NULL if an error occured in these calls.
5523e1bd7a2Ssjelinek 	 */
5533e1bd7a2Ssjelinek 	devp = dm_get_descriptor_by_name(DM_SLICE, slice, errp);
5543e1bd7a2Ssjelinek 	if (devp != NULL) {
5553e1bd7a2Ssjelinek 		*dev_stats = dm_get_stats(devp, DM_SLICE_STAT_USE,
5563e1bd7a2Ssjelinek 		    errp);
5573e1bd7a2Ssjelinek 		dm_free_descriptor(devp);
5583e1bd7a2Ssjelinek 	}
5593e1bd7a2Ssjelinek }
5603e1bd7a2Ssjelinek 
56146a2abf2Seschrock /*
56246a2abf2Seschrock  * Checks for overlapping slices.   If the given device is a slice, and it
56346a2abf2Seschrock  * overlaps with any non-backup slice on the disk, return true with a detailed
56446a2abf2Seschrock  * description similar to dm_inuse().
56546a2abf2Seschrock  */
56646a2abf2Seschrock int
56746a2abf2Seschrock dm_isoverlapping(char *slicename, char **overlaps_with, int *errp)
56846a2abf2Seschrock {
56946a2abf2Seschrock 	dm_descriptor_t slice = NULL;
57046a2abf2Seschrock 	dm_descriptor_t *media = NULL;
57146a2abf2Seschrock 	dm_descriptor_t *slices = NULL;
57246a2abf2Seschrock 	int 		i = 0;
57346a2abf2Seschrock 	uint32_t	in_snum;
57446a2abf2Seschrock 	uint64_t 	start_block = 0;
57546a2abf2Seschrock 	uint64_t 	end_block = 0;
57646a2abf2Seschrock 	uint64_t 	media_size = 0;
57746a2abf2Seschrock 	uint64_t 	size = 0;
57846a2abf2Seschrock 	nvlist_t 	*media_attrs = NULL;
57946a2abf2Seschrock 	nvlist_t 	*slice_attrs = NULL;
58046a2abf2Seschrock 	int		ret = 0;
58146a2abf2Seschrock 
58246a2abf2Seschrock 	slice = dm_get_descriptor_by_name(DM_SLICE, slicename, errp);
58346a2abf2Seschrock 	if (slice == NULL)
58446a2abf2Seschrock 		goto out;
58546a2abf2Seschrock 
58646a2abf2Seschrock 	/*
58746a2abf2Seschrock 	 * Get the list of slices be fetching the associated media, and then all
58846a2abf2Seschrock 	 * associated slices.
58946a2abf2Seschrock 	 */
59046a2abf2Seschrock 	media = dm_get_associated_descriptors(slice, DM_MEDIA, errp);
59146a2abf2Seschrock 	if (media == NULL || *media == NULL || *errp != 0)
59246a2abf2Seschrock 		goto out;
59346a2abf2Seschrock 
59446a2abf2Seschrock 	slices = dm_get_associated_descriptors(*media, DM_SLICE, errp);
59546a2abf2Seschrock 	if (slices == NULL || *slices == NULL || *errp != 0)
59646a2abf2Seschrock 		goto out;
59746a2abf2Seschrock 
59846a2abf2Seschrock 	media_attrs = dm_get_attributes(*media, errp);
59946a2abf2Seschrock 	if (media_attrs == NULL || *errp)
60046a2abf2Seschrock 		goto out;
60146a2abf2Seschrock 
60246a2abf2Seschrock 	*errp = nvlist_lookup_uint64(media_attrs, DM_NACCESSIBLE, &media_size);
60346a2abf2Seschrock 	if (*errp != 0)
60446a2abf2Seschrock 		goto out;
60546a2abf2Seschrock 
60646a2abf2Seschrock 	slice_attrs = dm_get_attributes(slice, errp);
60746a2abf2Seschrock 	if (slice_attrs == NULL || *errp != 0)
60846a2abf2Seschrock 		goto out;
60946a2abf2Seschrock 
61046a2abf2Seschrock 	*errp = nvlist_lookup_uint64(slice_attrs, DM_START, &start_block);
61146a2abf2Seschrock 	if (*errp != 0)
61246a2abf2Seschrock 		goto out;
61346a2abf2Seschrock 
61446a2abf2Seschrock 	*errp = nvlist_lookup_uint64(slice_attrs, DM_SIZE, &size);
61546a2abf2Seschrock 	if (*errp != 0)
61646a2abf2Seschrock 		goto out;
61746a2abf2Seschrock 
61846a2abf2Seschrock 	*errp = nvlist_lookup_uint32(slice_attrs, DM_INDEX, &in_snum);
61946a2abf2Seschrock 	if (*errp != 0)
62046a2abf2Seschrock 		goto out;
62146a2abf2Seschrock 
62246a2abf2Seschrock 	end_block = (start_block + size) - 1;
62346a2abf2Seschrock 
62446a2abf2Seschrock 	for (i = 0; slices[i]; i ++) {
62546a2abf2Seschrock 		uint64_t other_start;
62646a2abf2Seschrock 		uint64_t other_end;
62746a2abf2Seschrock 		uint64_t other_size;
62846a2abf2Seschrock 		uint32_t snum;
62946a2abf2Seschrock 
63046a2abf2Seschrock 		nvlist_t *other_attrs = dm_get_attributes(slices[i], errp);
63146a2abf2Seschrock 
63246a2abf2Seschrock 		if (other_attrs == NULL)
63346a2abf2Seschrock 			continue;
63446a2abf2Seschrock 
63546a2abf2Seschrock 		if (*errp != 0)
63646a2abf2Seschrock 			goto out;
63746a2abf2Seschrock 
63846a2abf2Seschrock 		*errp = nvlist_lookup_uint64(other_attrs, DM_START,
63946a2abf2Seschrock 		    &other_start);
64046a2abf2Seschrock 		if (*errp) {
64146a2abf2Seschrock 			nvlist_free(other_attrs);
64246a2abf2Seschrock 			goto out;
64346a2abf2Seschrock 		}
64446a2abf2Seschrock 
64546a2abf2Seschrock 		*errp = nvlist_lookup_uint64(other_attrs, DM_SIZE,
64646a2abf2Seschrock 		    &other_size);
64746a2abf2Seschrock 
64846a2abf2Seschrock 		if (*errp) {
64946a2abf2Seschrock 			nvlist_free(other_attrs);
65046a2abf2Seschrock 			ret = -1;
65146a2abf2Seschrock 			goto out;
65246a2abf2Seschrock 		}
65346a2abf2Seschrock 
65446a2abf2Seschrock 		other_end = (other_size + other_start) - 1;
65546a2abf2Seschrock 
65646a2abf2Seschrock 		*errp = nvlist_lookup_uint32(other_attrs, DM_INDEX,
65746a2abf2Seschrock 		    &snum);
65846a2abf2Seschrock 
65946a2abf2Seschrock 		if (*errp) {
66046a2abf2Seschrock 			nvlist_free(other_attrs);
66146a2abf2Seschrock 			ret = -1;
66246a2abf2Seschrock 			goto out;
66346a2abf2Seschrock 		}
66446a2abf2Seschrock 
66546a2abf2Seschrock 		/*
66646a2abf2Seschrock 		 * Check to see if there are > 2 overlapping regions
66746a2abf2Seschrock 		 * on this media in the same region as this slice.
66846a2abf2Seschrock 		 * This is done by assuming the following:
66946a2abf2Seschrock 		 *   	Slice 2 is the backup slice if it is the size
67046a2abf2Seschrock 		 *	of the whole disk
67146a2abf2Seschrock 		 * If slice 2 is the overlap and slice 2 is the size of
67246a2abf2Seschrock 		 * the whole disk, continue. If another slice is found
67346a2abf2Seschrock 		 * that overlaps with our slice, return it.
67446a2abf2Seschrock 		 * There is the potential that there is more than one slice
67546a2abf2Seschrock 		 * that our slice overlaps with, however, we only return
67646a2abf2Seschrock 		 * the first overlapping slice we find.
67746a2abf2Seschrock 		 *
67846a2abf2Seschrock 		 */
67946a2abf2Seschrock 		if (start_block >= other_start && start_block <= other_end) {
68046a2abf2Seschrock 			if ((snum == 2 && (other_size == media_size)) ||
68146a2abf2Seschrock 			    snum == in_snum) {
68246a2abf2Seschrock 				continue;
68346a2abf2Seschrock 			} else {
68446a2abf2Seschrock 				char *str = dm_get_name(slices[i], errp);
68546a2abf2Seschrock 				if (*errp != 0) {
68646a2abf2Seschrock 					nvlist_free(other_attrs);
68746a2abf2Seschrock 					ret = -1;
68846a2abf2Seschrock 					goto out;
68946a2abf2Seschrock 				}
69046a2abf2Seschrock 				*overlaps_with = strdup(str);
69146a2abf2Seschrock 				dm_free_name(str);
69246a2abf2Seschrock 				nvlist_free(other_attrs);
69346a2abf2Seschrock 				ret = 1;
69446a2abf2Seschrock 				goto out;
69546a2abf2Seschrock 			}
69646a2abf2Seschrock 		} else if (other_start >= start_block &&
69746a2abf2Seschrock 		    other_start <= end_block) {
69846a2abf2Seschrock 			if ((snum == 2 && (other_size == media_size)) ||
69946a2abf2Seschrock 			    snum == in_snum) {
70046a2abf2Seschrock 				continue;
70146a2abf2Seschrock 			} else {
70246a2abf2Seschrock 				char *str = dm_get_name(slices[i], errp);
70346a2abf2Seschrock 				if (*errp != 0) {
70446a2abf2Seschrock 					nvlist_free(other_attrs);
70546a2abf2Seschrock 					ret = -1;
70646a2abf2Seschrock 					goto out;
70746a2abf2Seschrock 				}
70846a2abf2Seschrock 				*overlaps_with = strdup(str);
70946a2abf2Seschrock 				dm_free_name(str);
71046a2abf2Seschrock 				nvlist_free(other_attrs);
71146a2abf2Seschrock 				ret = 1;
71246a2abf2Seschrock 				goto out;
71346a2abf2Seschrock 			}
71446a2abf2Seschrock 		}
71546a2abf2Seschrock 		nvlist_free(other_attrs);
71646a2abf2Seschrock 	}
71746a2abf2Seschrock 
71846a2abf2Seschrock out:
71946a2abf2Seschrock 	if (media_attrs)
72046a2abf2Seschrock 		nvlist_free(media_attrs);
72146a2abf2Seschrock 	if (slice_attrs)
72246a2abf2Seschrock 		nvlist_free(slice_attrs);
72346a2abf2Seschrock 
72446a2abf2Seschrock 	if (slices)
72546a2abf2Seschrock 		dm_free_descriptors(slices);
72646a2abf2Seschrock 	if (media)
72746a2abf2Seschrock 		dm_free_descriptors(media);
72846a2abf2Seschrock 	if (slice)
72946a2abf2Seschrock 		dm_free_descriptor(slice);
73046a2abf2Seschrock 
73146a2abf2Seschrock 	return (ret);
73246a2abf2Seschrock }
73346a2abf2Seschrock 
734181c2f42Smmusante /*
735181c2f42Smmusante  * Get the full list of swap entries.  Returns -1 on error, or >= 0 to
736181c2f42Smmusante  * indicate the number of entries in the list.  Callers are responsible
737181c2f42Smmusante  * for calling dm_free_swapentries() to deallocate memory.  If this
738181c2f42Smmusante  * returns 0, the swaptbl_t still needs to be freed.
739181c2f42Smmusante  */
740181c2f42Smmusante int
741181c2f42Smmusante dm_get_swapentries(swaptbl_t **stp, int *errp)
742181c2f42Smmusante {
743181c2f42Smmusante 	int count, i;
744181c2f42Smmusante 	swaptbl_t *tbl;
745181c2f42Smmusante 	char *ptr;
746181c2f42Smmusante 
747181c2f42Smmusante 	*stp = NULL;
748181c2f42Smmusante 
749181c2f42Smmusante 	/* get number of swap entries */
750181c2f42Smmusante 	if ((count = swapctl(SC_GETNSWP, NULL)) < 0) {
751181c2f42Smmusante 		*errp = errno;
752181c2f42Smmusante 		return (-1);
753181c2f42Smmusante 	}
754181c2f42Smmusante 
755181c2f42Smmusante 	if (count == 0) {
756181c2f42Smmusante 		return (0);
757181c2f42Smmusante 	}
758181c2f42Smmusante 
759181c2f42Smmusante 	/* allocate space */
760181c2f42Smmusante 	tbl = calloc(1, sizeof (int) + count * sizeof (swapent_t));
761181c2f42Smmusante 	if (tbl == NULL) {
762181c2f42Smmusante 		*errp = ENOMEM;
763181c2f42Smmusante 		return (-1);
764181c2f42Smmusante 	}
765181c2f42Smmusante 
766181c2f42Smmusante 	ptr = calloc(1, count * MAXPATHLEN);
767181c2f42Smmusante 	if (ptr == NULL) {
768181c2f42Smmusante 		*errp = ENOMEM;
769181c2f42Smmusante 		free(tbl);
770181c2f42Smmusante 		return (-1);
771181c2f42Smmusante 	}
772181c2f42Smmusante 
773181c2f42Smmusante 	/* set up pointers to the pathnames */
774181c2f42Smmusante 	tbl->swt_n = count;
775181c2f42Smmusante 	for (i = 0; i < count; i++) {
776181c2f42Smmusante 		tbl->swt_ent[i].ste_path = ptr;
777181c2f42Smmusante 		ptr += MAXPATHLEN;
778181c2f42Smmusante 	}
779181c2f42Smmusante 
780181c2f42Smmusante 	/* get list of swap paths */
781181c2f42Smmusante 	count = swapctl(SC_LIST, tbl);
782181c2f42Smmusante 	if (count < 0) {
783181c2f42Smmusante 		*errp = errno;
784181c2f42Smmusante 		free(ptr);
785181c2f42Smmusante 		free(tbl);
786181c2f42Smmusante 		return (-1);
787181c2f42Smmusante 	}
788181c2f42Smmusante 
789181c2f42Smmusante 	*stp = tbl;
790181c2f42Smmusante 	return (count);
791181c2f42Smmusante }
792181c2f42Smmusante 
793181c2f42Smmusante /* ARGSUSED */
794181c2f42Smmusante void
795181c2f42Smmusante dm_free_swapentries(swaptbl_t *stp)
796181c2f42Smmusante {
797181c2f42Smmusante 	ASSERT(stp != NULL);
798181c2f42Smmusante 
799181c2f42Smmusante 	free(stp->swt_ent[0].ste_path);
800181c2f42Smmusante 	free(stp);
801181c2f42Smmusante }
802181c2f42Smmusante 
803181c2f42Smmusante /*
804181c2f42Smmusante  * Check a slice to see if it's being used by swap.
805181c2f42Smmusante  */
806181c2f42Smmusante int
807181c2f42Smmusante dm_inuse_swap(const char *dev_name, int *errp)
808181c2f42Smmusante {
809181c2f42Smmusante 	int count;
810181c2f42Smmusante 	int found;
811181c2f42Smmusante 	swaptbl_t *tbl = NULL;
812181c2f42Smmusante 
813181c2f42Smmusante 	*errp = 0;
814181c2f42Smmusante 
815181c2f42Smmusante 	count = dm_get_swapentries(&tbl, errp);
816181c2f42Smmusante 	if (count < 0 || *errp) {
817181c2f42Smmusante 		if (tbl)
818181c2f42Smmusante 			dm_free_swapentries(tbl);
819181c2f42Smmusante 		return (-1);
820181c2f42Smmusante 	}
821181c2f42Smmusante 
822181c2f42Smmusante 	/* if there are no swap entries, we're done */
823181c2f42Smmusante 	if (!count) {
824181c2f42Smmusante 		return (0);
825181c2f42Smmusante 	}
826181c2f42Smmusante 
827181c2f42Smmusante 	ASSERT(tbl != NULL);
828181c2f42Smmusante 
829181c2f42Smmusante 	found = 0;
830181c2f42Smmusante 	while (count--) {
831181c2f42Smmusante 		if (strcmp(dev_name, tbl->swt_ent[count].ste_path) == 0) {
832181c2f42Smmusante 			found = 1;
833181c2f42Smmusante 			break;
834181c2f42Smmusante 		}
835181c2f42Smmusante 	}
836181c2f42Smmusante 
837181c2f42Smmusante 	dm_free_swapentries(tbl);
838181c2f42Smmusante 	return (found);
839181c2f42Smmusante }
840181c2f42Smmusante 
8413e1bd7a2Ssjelinek /*
8423e1bd7a2Ssjelinek  * Returns 'in use' details, if found, about a specific dev_name,
8433e1bd7a2Ssjelinek  * based on the caller(who). It is important to note that it is possible
8443e1bd7a2Ssjelinek  * for there to be more than one 'in use' statistic regarding a dev_name.
8453e1bd7a2Ssjelinek  * The **msg parameter returns a list of 'in use' details. This message
8463e1bd7a2Ssjelinek  * is formatted via gettext().
8473e1bd7a2Ssjelinek  */
8483e1bd7a2Ssjelinek int
8493e1bd7a2Ssjelinek dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
8503e1bd7a2Ssjelinek {
8513e1bd7a2Ssjelinek 	nvlist_t *dev_stats = NULL;
8523e1bd7a2Ssjelinek 	char *by, *data;
8533e1bd7a2Ssjelinek 	nvpair_t *nvwhat = NULL;
8543e1bd7a2Ssjelinek 	nvpair_t *nvdesc = NULL;
8553e1bd7a2Ssjelinek 	int	found = 0;
856181c2f42Smmusante 	int	err;
8573e1bd7a2Ssjelinek 	char	*dname = NULL;
8583e1bd7a2Ssjelinek 
8593e1bd7a2Ssjelinek 	*errp = 0;
8603e1bd7a2Ssjelinek 	*msg = NULL;
8613e1bd7a2Ssjelinek 
86282d71480Ssjelinek 	/*
86382d71480Ssjelinek 	 * If the user doesn't want to do in use checking, return.
86482d71480Ssjelinek 	 */
86582d71480Ssjelinek 
86682d71480Ssjelinek 	if (NOINUSE_SET)
86782d71480Ssjelinek 		return (0);
86882d71480Ssjelinek 
8693e1bd7a2Ssjelinek 	dname = getfullblkname(dev_name);
8703e1bd7a2Ssjelinek 	/*
8713e1bd7a2Ssjelinek 	 * If we cannot find the block name, we cannot check the device
8723e1bd7a2Ssjelinek 	 * for in use statistics. So, return found, which is == 0.
8733e1bd7a2Ssjelinek 	 */
8743e1bd7a2Ssjelinek 	if (dname == NULL || *dname == '\0') {
8753e1bd7a2Ssjelinek 		return (found);
8763e1bd7a2Ssjelinek 	}
8773e1bd7a2Ssjelinek 
878181c2f42Smmusante 	/*
879181c2f42Smmusante 	 * Slice stats for swap devices are only returned if mounted
880181c2f42Smmusante 	 * (e.g. /tmp).  Other devices or files being used for swap
881181c2f42Smmusante 	 * are ignored, so we add a special check here to use swapctl(2)
882181c2f42Smmusante 	 * to perform in-use checking.
883181c2f42Smmusante 	 */
884181c2f42Smmusante 	if (ANY_ZPOOL_USE(who) && (err = dm_inuse_swap(dname, errp))) {
885181c2f42Smmusante 
886181c2f42Smmusante 		/* on error, dm_inuse_swap sets errp */
887181c2f42Smmusante 		if (err < 0) {
888181c2f42Smmusante 			free(dname);
889181c2f42Smmusante 			return (err);
890181c2f42Smmusante 		}
891181c2f42Smmusante 
892181c2f42Smmusante 		/* simulate a mounted swap device */
893181c2f42Smmusante 		(void) build_usage_string(dname, DM_USE_MOUNT, "swap", msg,
894181c2f42Smmusante 		    &found, errp);
895181c2f42Smmusante 
896181c2f42Smmusante 		/* if this fails, dm_get_usage_string changed */
897181c2f42Smmusante 		ASSERT(found == 1);
898181c2f42Smmusante 
899181c2f42Smmusante 		free(dname);
900181c2f42Smmusante 		return (found);
901181c2f42Smmusante 	}
902181c2f42Smmusante 
9033e1bd7a2Ssjelinek 	dm_get_slice_stats(dname, &dev_stats, errp);
9043e1bd7a2Ssjelinek 	if (dev_stats == NULL) {
9053e1bd7a2Ssjelinek 		/*
9063e1bd7a2Ssjelinek 		 * If there is an error, but it isn't a no device found error
9073e1bd7a2Ssjelinek 		 * return the error as recorded. Otherwise, with a full
9083e1bd7a2Ssjelinek 		 * block name, we might not be able to get the slice
9093e1bd7a2Ssjelinek 		 * associated, and will get an ENODEV error. For example,
9103e1bd7a2Ssjelinek 		 * an SVM metadevice will return a value from getfullblkname()
9113e1bd7a2Ssjelinek 		 * but libdiskmgt won't be able to find this device for
9123e1bd7a2Ssjelinek 		 * statistics gathering. This is expected and we should not
9133e1bd7a2Ssjelinek 		 * report errnoneous errors.
9143e1bd7a2Ssjelinek 		 */
9153e1bd7a2Ssjelinek 		if (*errp) {
9163e1bd7a2Ssjelinek 			if (*errp == ENODEV) {
9173e1bd7a2Ssjelinek 				*errp = 0;
9183e1bd7a2Ssjelinek 			}
9193e1bd7a2Ssjelinek 		}
9203e1bd7a2Ssjelinek 		free(dname);
9213e1bd7a2Ssjelinek 		return (found);
9223e1bd7a2Ssjelinek 	}
9233e1bd7a2Ssjelinek 
9243e1bd7a2Ssjelinek 	for (;;) {
9253e1bd7a2Ssjelinek 
9263e1bd7a2Ssjelinek 		nvwhat = nvlist_next_nvpair(dev_stats, nvdesc);
9273e1bd7a2Ssjelinek 		nvdesc = nvlist_next_nvpair(dev_stats, nvwhat);
9283e1bd7a2Ssjelinek 
9293e1bd7a2Ssjelinek 		/*
9303e1bd7a2Ssjelinek 		 * End of the list found.
9313e1bd7a2Ssjelinek 		 */
9323e1bd7a2Ssjelinek 		if (nvwhat == NULL || nvdesc == NULL) {
9333e1bd7a2Ssjelinek 			break;
9343e1bd7a2Ssjelinek 		}
9353e1bd7a2Ssjelinek 		/*
9363e1bd7a2Ssjelinek 		 * Otherwise, we check to see if this client(who) cares
9373e1bd7a2Ssjelinek 		 * about this in use scenario
9383e1bd7a2Ssjelinek 		 */
9393e1bd7a2Ssjelinek 
9403e1bd7a2Ssjelinek 		ASSERT(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0);
9413e1bd7a2Ssjelinek 		ASSERT(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0);
9423e1bd7a2Ssjelinek 		/*
9433e1bd7a2Ssjelinek 		 * If we error getting the string value continue on
9443e1bd7a2Ssjelinek 		 * to the next pair(if there is one)
9453e1bd7a2Ssjelinek 		 */
9463e1bd7a2Ssjelinek 		if (nvpair_value_string(nvwhat, &by)) {
9473e1bd7a2Ssjelinek 			continue;
9483e1bd7a2Ssjelinek 		}
9493e1bd7a2Ssjelinek 		if (nvpair_value_string(nvdesc, &data)) {
9503e1bd7a2Ssjelinek 			continue;
9513e1bd7a2Ssjelinek 		}
9523e1bd7a2Ssjelinek 
9533e1bd7a2Ssjelinek 		switch (who) {
9543e1bd7a2Ssjelinek 			case DM_WHO_MKFS:
9553e1bd7a2Ssjelinek 				/*
9563e1bd7a2Ssjelinek 				 * mkfs is not in use for these cases.
9573e1bd7a2Ssjelinek 				 * All others are in use.
9583e1bd7a2Ssjelinek 				 */
9593e1bd7a2Ssjelinek 				if (strcmp(by, DM_USE_LU) == 0 ||
96046a2abf2Seschrock 				    strcmp(by, DM_USE_FS) == 0 ||
96146a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
9623e1bd7a2Ssjelinek 					break;
9633e1bd7a2Ssjelinek 				}
9643e1bd7a2Ssjelinek 				if (build_usage_string(dname,
9653e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
9663e1bd7a2Ssjelinek 					if (*errp) {
9673e1bd7a2Ssjelinek 						goto out;
9683e1bd7a2Ssjelinek 					}
9693e1bd7a2Ssjelinek 				}
9703e1bd7a2Ssjelinek 				break;
9713e1bd7a2Ssjelinek 			case DM_WHO_SWAP:
9723e1bd7a2Ssjelinek 				/*
9733e1bd7a2Ssjelinek 				 * Not in use for this.
9743e1bd7a2Ssjelinek 				 */
9753e1bd7a2Ssjelinek 				if (strcmp(by, DM_USE_DUMP) == 0 ||
97646a2abf2Seschrock 				    strcmp(by, DM_USE_FS) == 0 ||
97746a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
9783e1bd7a2Ssjelinek 					break;
9793e1bd7a2Ssjelinek 				}
980*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 				if (strcmp(by, DM_USE_LU) == 0 &&
981*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 				    strcmp(data, "-") == 0) {
982*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 					break;
983*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 				}
984*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 				if (strcmp(by, DM_USE_VFSTAB) == 0 &&
985*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 				    strcmp(data, "") == 0) {
986*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 					break;
987*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 				}
9883e1bd7a2Ssjelinek 				if (build_usage_string(dname,
9893e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
9903e1bd7a2Ssjelinek 					if (*errp) {
9913e1bd7a2Ssjelinek 						goto out;
9923e1bd7a2Ssjelinek 					}
9933e1bd7a2Ssjelinek 				}
9943e1bd7a2Ssjelinek 				break;
9953e1bd7a2Ssjelinek 			case DM_WHO_DUMP:
9963e1bd7a2Ssjelinek 				/*
9973e1bd7a2Ssjelinek 				 * Not in use for this.
9983e1bd7a2Ssjelinek 				 */
9993e1bd7a2Ssjelinek 				if ((strcmp(by, DM_USE_MOUNT) == 0 &&
10003e1bd7a2Ssjelinek 				    strcmp(data, "swap") == 0) ||
10013e1bd7a2Ssjelinek 				    strcmp(by, DM_USE_DUMP) == 0 ||
100246a2abf2Seschrock 				    strcmp(by, DM_USE_FS) == 0 ||
100346a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
10043e1bd7a2Ssjelinek 					break;
10053e1bd7a2Ssjelinek 				}
10063e1bd7a2Ssjelinek 				if (build_usage_string(dname,
10073e1bd7a2Ssjelinek 				    by, data, msg, &found, errp)) {
10083e1bd7a2Ssjelinek 					if (*errp) {
10093e1bd7a2Ssjelinek 						goto out;
10103e1bd7a2Ssjelinek 					}
10113e1bd7a2Ssjelinek 				}
10123e1bd7a2Ssjelinek 				break;
10133e1bd7a2Ssjelinek 
10143e1bd7a2Ssjelinek 			case DM_WHO_FORMAT:
101546a2abf2Seschrock 				if (strcmp(by, DM_USE_FS) == 0 ||
101646a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0)
10173e1bd7a2Ssjelinek 					break;
10183e1bd7a2Ssjelinek 				if (build_usage_string(dname,
10193e1bd7a2Ssjelinek 				    by, data, msg, &found, errp) != 0) {
10203e1bd7a2Ssjelinek 					if (*errp) {
10213e1bd7a2Ssjelinek 						goto out;
10223e1bd7a2Ssjelinek 					}
10233e1bd7a2Ssjelinek 				}
10243e1bd7a2Ssjelinek 				break;
102546a2abf2Seschrock 
102646a2abf2Seschrock 			case DM_WHO_ZPOOL_FORCE:
102746a2abf2Seschrock 				if (strcmp(by, DM_USE_FS) == 0 ||
102846a2abf2Seschrock 				    strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0)
102946a2abf2Seschrock 					break;
103046a2abf2Seschrock 				/* FALLTHROUGH */
103146a2abf2Seschrock 			case DM_WHO_ZPOOL:
103246a2abf2Seschrock 				if (build_usage_string(dname,
103346a2abf2Seschrock 				    by, data, msg, &found, errp) != 0) {
103446a2abf2Seschrock 					if (*errp)
103546a2abf2Seschrock 						goto out;
103646a2abf2Seschrock 				}
103746a2abf2Seschrock 				break;
103846a2abf2Seschrock 
103946657f8dSmmusante 			case DM_WHO_ZPOOL_SPARE:
104046657f8dSmmusante 				if (strcmp(by, DM_USE_SPARE_ZPOOL) != 0) {
104146657f8dSmmusante 					if (build_usage_string(dname, by,
104246657f8dSmmusante 					    data, msg, &found, errp) != 0) {
104346657f8dSmmusante 						if (*errp)
104446657f8dSmmusante 							goto out;
104546657f8dSmmusante 					}
104646657f8dSmmusante 				}
104746657f8dSmmusante 				break;
104846657f8dSmmusante 
10493e1bd7a2Ssjelinek 			default:
10503e1bd7a2Ssjelinek 				/*
10513e1bd7a2Ssjelinek 				 * nothing found in use for this client
10523e1bd7a2Ssjelinek 				 * of libdiskmgt. Default is 'not in use'.
10533e1bd7a2Ssjelinek 				 */
10543e1bd7a2Ssjelinek 				break;
10553e1bd7a2Ssjelinek 		}
10563e1bd7a2Ssjelinek 	}
10573e1bd7a2Ssjelinek out:
10583e1bd7a2Ssjelinek 	if (dname != NULL)
10593e1bd7a2Ssjelinek 		free(dname);
10603e1bd7a2Ssjelinek 	if (dev_stats != NULL)
10613e1bd7a2Ssjelinek 		nvlist_free(dev_stats);
10623e1bd7a2Ssjelinek 
10633e1bd7a2Ssjelinek 	return (found);
10643e1bd7a2Ssjelinek }
10653e1bd7a2Ssjelinek 
10663e1bd7a2Ssjelinek void
10673e1bd7a2Ssjelinek dm_get_usage_string(char *what, char *how, char **usage_string)
10683e1bd7a2Ssjelinek {
10693e1bd7a2Ssjelinek 
10703e1bd7a2Ssjelinek 
10713e1bd7a2Ssjelinek 	if (usage_string == NULL || what == NULL) {
10723e1bd7a2Ssjelinek 		return;
10733e1bd7a2Ssjelinek 	}
10743e1bd7a2Ssjelinek 	*usage_string = NULL;
10753e1bd7a2Ssjelinek 
10763e1bd7a2Ssjelinek 	if (strcmp(what, DM_USE_MOUNT) == 0) {
10773e1bd7a2Ssjelinek 		if (strcmp(how, "swap") == 0) {
10783e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
10793e1bd7a2Ssjelinek 			    "%s is currently used by swap. Please see swap(1M)."
10803e1bd7a2Ssjelinek 			    "\n");
10813e1bd7a2Ssjelinek 		} else {
10823e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
10833e1bd7a2Ssjelinek 			    "%s is currently mounted on %s."
10843e1bd7a2Ssjelinek 			    " Please see umount(1M).\n");
10853e1bd7a2Ssjelinek 		}
10863e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_VFSTAB) == 0) {
10873e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
10883e1bd7a2Ssjelinek 		    "%s is normally mounted on %s according to /etc/vfstab. "
10893e1bd7a2Ssjelinek 		    "Please remove this entry to use this device.\n");
10903e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_FS) == 0) {
10913e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
109246a2abf2Seschrock 		    "%s contains a %s filesystem.\n");
10933e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_SVM) == 0) {
10943e1bd7a2Ssjelinek 		if (strcmp(how, "mdb") == 0) {
10953e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
10963e1bd7a2Ssjelinek 			    "%s contains an SVM %s. Please see "
10973e1bd7a2Ssjelinek 			    "metadb(1M).\n");
10983e1bd7a2Ssjelinek 		} else {
10993e1bd7a2Ssjelinek 			*usage_string = dgettext(TEXT_DOMAIN,
11003e1bd7a2Ssjelinek 			    "%s is part of SVM volume %s. "
11013e1bd7a2Ssjelinek 			    "Please see metaclear(1M).\n");
11023e1bd7a2Ssjelinek 		}
11033e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_VXVM) == 0) {
11043e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
11053e1bd7a2Ssjelinek 		    "%s is part of VxVM volume %s.\n");
11063e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_LU) == 0) {
11073e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
11083e1bd7a2Ssjelinek 		    "%s is in use for live upgrade %s. Please see ludelete(1M)."
11093e1bd7a2Ssjelinek 		    "\n");
11103e1bd7a2Ssjelinek 	} else if (strcmp(what, DM_USE_DUMP) == 0) {
11113e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
11123e1bd7a2Ssjelinek 		    "%s is in use by %s. Please see dumpadm(1M)."
11133e1bd7a2Ssjelinek 		    "\n");
111446a2abf2Seschrock 	} else if (strcmp(what, DM_USE_EXPORTED_ZPOOL) == 0) {
111546a2abf2Seschrock 		*usage_string = dgettext(TEXT_DOMAIN,
111646a2abf2Seschrock 		    "%s is part of exported or potentially active ZFS pool %s. "
111746a2abf2Seschrock 		    "Please see zpool(1M).\n");
111846a2abf2Seschrock 	} else if (strcmp(what, DM_USE_ACTIVE_ZPOOL) == 0) {
11193e1bd7a2Ssjelinek 		*usage_string = dgettext(TEXT_DOMAIN,
112046a2abf2Seschrock 		    "%s is part of active ZFS pool %s. Please see zpool(1M)."
11213e1bd7a2Ssjelinek 		    "\n");
112299653d4eSeschrock 	} else if (strcmp(what, DM_USE_SPARE_ZPOOL) == 0) {
112399653d4eSeschrock 		*usage_string = dgettext(TEXT_DOMAIN,
112499653d4eSeschrock 		    "%s is reserved as a hot spare for ZFS pool %s.  Please "
112599653d4eSeschrock 		    "see zpool(1M).\n");
1126fa94a07fSbrendan 	} else if (strcmp(what, DM_USE_L2CACHE_ZPOOL) == 0) {
1127fa94a07fSbrendan 		*usage_string = dgettext(TEXT_DOMAIN,
1128fa94a07fSbrendan 		    "%s is in use as a cache device for ZFS pool %s.  "
1129fa94a07fSbrendan 		    "Please see zpool(1M).\n");
11303e1bd7a2Ssjelinek 	}
11313e1bd7a2Ssjelinek }
11327c478bd9Sstevel@tonic-gate void
11337c478bd9Sstevel@tonic-gate libdiskmgt_add_str(nvlist_t *attrs, char *name, char *val, int *errp)
11347c478bd9Sstevel@tonic-gate {
11357c478bd9Sstevel@tonic-gate 	if (*errp == 0) {
11367c478bd9Sstevel@tonic-gate 		*errp = nvlist_add_string(attrs, name, val);
11377c478bd9Sstevel@tonic-gate 	}
11387c478bd9Sstevel@tonic-gate }
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate descriptor_t **
11417c478bd9Sstevel@tonic-gate libdiskmgt_empty_desc_array(int *errp)
11427c478bd9Sstevel@tonic-gate {
11437c478bd9Sstevel@tonic-gate 	descriptor_t	**empty;
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 	empty = (descriptor_t **)calloc(1, sizeof (descriptor_t *));
11467c478bd9Sstevel@tonic-gate 	if (empty == NULL) {
1147*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = ENOMEM;
1148*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
11497c478bd9Sstevel@tonic-gate 	}
11507c478bd9Sstevel@tonic-gate 	empty[0] = NULL;
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 	*errp = 0;
11537c478bd9Sstevel@tonic-gate 	return (empty);
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate void
11577c478bd9Sstevel@tonic-gate libdiskmgt_init_debug()
11587c478bd9Sstevel@tonic-gate {
11597c478bd9Sstevel@tonic-gate 	char	*valp;
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 	if ((valp = getenv(DM_DEBUG)) != NULL) {
1162*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		dm_debug = atoi(valp);
11637c478bd9Sstevel@tonic-gate 	}
11647c478bd9Sstevel@tonic-gate }
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate int
11677c478bd9Sstevel@tonic-gate libdiskmgt_str_eq(char *nm1, char *nm2)
11687c478bd9Sstevel@tonic-gate {
11697c478bd9Sstevel@tonic-gate 	if (nm1 == NULL) {
1170*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		if (dm_debug) {
1171*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 			(void) fprintf(stderr, "WARNING: str_eq nm1 NULL\n");
1172*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		}
11737c478bd9Sstevel@tonic-gate 
1174*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		if (nm2 == NULL) {
1175*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 			return (1);
1176*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		} else {
1177*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 			return (0);
1178*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		}
11797c478bd9Sstevel@tonic-gate 	}
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	/* nm1 != NULL */
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate 	if (nm2 == NULL) {
1184*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		if (dm_debug) {
1185*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 			(void) fprintf(stderr, "WARNING: str_eq nm2 NULL\n");
1186*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		}
1187*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (0);
11887c478bd9Sstevel@tonic-gate 	}
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate 	if (strcmp(nm1, nm2) == 0) {
1191*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (1);
11927c478bd9Sstevel@tonic-gate 	}
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 	return (0);
11957c478bd9Sstevel@tonic-gate }
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11987c478bd9Sstevel@tonic-gate static descriptor_t **
11997c478bd9Sstevel@tonic-gate desc_array_to_ptr_array(dm_descriptor_t *descs, int *errp)
12007c478bd9Sstevel@tonic-gate {
12017c478bd9Sstevel@tonic-gate #ifdef _LP64
12027c478bd9Sstevel@tonic-gate 	return ((descriptor_t **)descs);
12037c478bd9Sstevel@tonic-gate #else
12047c478bd9Sstevel@tonic-gate 	/* convert the 64 bit descriptors to 32 bit ptrs */
12057c478bd9Sstevel@tonic-gate 	int	cnt;
12067c478bd9Sstevel@tonic-gate 	int	i;
12077c478bd9Sstevel@tonic-gate 	descriptor_t **da;
12087c478bd9Sstevel@tonic-gate 
1209*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 	for (cnt = 0; descs[cnt]; cnt++)
1210*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		;
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 	da = (descriptor_t **)calloc(cnt + 1, sizeof (descriptor_t *));
12137c478bd9Sstevel@tonic-gate 	if (da == NULL) {
1214*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = ENOMEM;
1215*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
12167c478bd9Sstevel@tonic-gate 	}
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	for (i = 0; descs[i]; i++) {
1219*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		da[i] = (descriptor_t *)(uintptr_t)descs[i];
12207c478bd9Sstevel@tonic-gate 	}
12217c478bd9Sstevel@tonic-gate 	*errp = 0;
12227c478bd9Sstevel@tonic-gate 	free(descs);
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 	return (da);
12257c478bd9Sstevel@tonic-gate #endif
12267c478bd9Sstevel@tonic-gate }
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12297c478bd9Sstevel@tonic-gate static dm_descriptor_t *
12307c478bd9Sstevel@tonic-gate ptr_array_to_desc_array(descriptor_t **ptrs, int *errp)
12317c478bd9Sstevel@tonic-gate {
12327c478bd9Sstevel@tonic-gate #ifdef _LP64
12337c478bd9Sstevel@tonic-gate 	return ((dm_descriptor_t *)ptrs);
12347c478bd9Sstevel@tonic-gate #else
12357c478bd9Sstevel@tonic-gate 	/* convert the 32 bit ptrs to the 64 bit descriptors */
12367c478bd9Sstevel@tonic-gate 	int	cnt;
12377c478bd9Sstevel@tonic-gate 	int	i;
12387c478bd9Sstevel@tonic-gate 	dm_descriptor_t *da;
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 	if (*errp != 0 || ptrs == NULL) {
1241*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
12427c478bd9Sstevel@tonic-gate 	}
12437c478bd9Sstevel@tonic-gate 
1244*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 	for (cnt = 0; ptrs[cnt]; cnt++)
1245*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		;
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 	da = (dm_descriptor_t *)calloc(cnt + 1, sizeof (dm_descriptor_t));
12487c478bd9Sstevel@tonic-gate 	if (da == NULL) {
1249*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		*errp = ENOMEM;
1250*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		return (NULL);
12517c478bd9Sstevel@tonic-gate 	}
12527c478bd9Sstevel@tonic-gate 
12537c478bd9Sstevel@tonic-gate 	for (i = 0; ptrs[i]; i++) {
1254*efd79defSsriman bhavanam - Sun Microsystems - Bangalore India 		da[i] = (uintptr_t)ptrs[i];
12557c478bd9Sstevel@tonic-gate 	}
12567c478bd9Sstevel@tonic-gate 	*errp = 0;
12577c478bd9Sstevel@tonic-gate 	free(ptrs);
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 	return (da);
12607c478bd9Sstevel@tonic-gate #endif
12617c478bd9Sstevel@tonic-gate }
12623e1bd7a2Ssjelinek /*
12633e1bd7a2Ssjelinek  * Build the usage string for the in use data. Return the build string in
12643e1bd7a2Ssjelinek  * the msg parameter. This function takes care of reallocing all the memory
12653e1bd7a2Ssjelinek  * for this usage string. Usage string is returned already formatted for
12663e1bd7a2Ssjelinek  * localization.
12673e1bd7a2Ssjelinek  */
12683e1bd7a2Ssjelinek static int
12693e1bd7a2Ssjelinek build_usage_string(char *dname, char *by, char *data, char **msg,
12703e1bd7a2Ssjelinek     int *found, int *errp)
12713e1bd7a2Ssjelinek {
12723e1bd7a2Ssjelinek 	int	len0;
12733e1bd7a2Ssjelinek 	int	len1;
12743e1bd7a2Ssjelinek 	char	*use;
12753e1bd7a2Ssjelinek 	char	*p;
12763e1bd7a2Ssjelinek 
12773e1bd7a2Ssjelinek 	*errp = 0;
12783e1bd7a2Ssjelinek 
12793e1bd7a2Ssjelinek 	dm_get_usage_string(by, data, &use);
12803e1bd7a2Ssjelinek 	if (!use) {
12813e1bd7a2Ssjelinek 		return (-1);
12823e1bd7a2Ssjelinek 	}
12833e1bd7a2Ssjelinek 
12843e1bd7a2Ssjelinek 	if (*msg)
12853e1bd7a2Ssjelinek 		len0 = strlen(*msg);
12863e1bd7a2Ssjelinek 	else
12873e1bd7a2Ssjelinek 		len0 = 0;
12883e1bd7a2Ssjelinek 	/* LINTED */
12893e1bd7a2Ssjelinek 	len1 = snprintf(NULL, 0, use, dname, data);
12903e1bd7a2Ssjelinek 
12913e1bd7a2Ssjelinek 	/*
12923e1bd7a2Ssjelinek 	 * If multiple in use details they
12933e1bd7a2Ssjelinek 	 * are listed 1 per line for ease of
12943e1bd7a2Ssjelinek 	 * reading. dm_find_usage_string
12953e1bd7a2Ssjelinek 	 * formats these appropriately.
12963e1bd7a2Ssjelinek 	 */
12973e1bd7a2Ssjelinek 	if ((p = realloc(*msg, len0 + len1 + 1)) == NULL) {
12983e1bd7a2Ssjelinek 		*errp = errno;
12993e1bd7a2Ssjelinek 		free(*msg);
13003e1bd7a2Ssjelinek 		return (-1);
13013e1bd7a2Ssjelinek 	}
13023e1bd7a2Ssjelinek 	*msg = p;
13033e1bd7a2Ssjelinek 
13043e1bd7a2Ssjelinek 	/* LINTED */
13053e1bd7a2Ssjelinek 	(void) snprintf(*msg + len0, len1 + 1, use, dname, data);
13063e1bd7a2Ssjelinek 	(*found)++;
13073e1bd7a2Ssjelinek 	return (0);
13083e1bd7a2Ssjelinek }
1309