1767Ssjelinek /*
2767Ssjelinek  * CDDL HEADER START
3767Ssjelinek  *
4767Ssjelinek  * The contents of this file are subject to the terms of the
51594Slling  * Common Development and Distribution License (the "License").
61594Slling  * You may not use this file except in compliance with the License.
7767Ssjelinek  *
8767Ssjelinek  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9767Ssjelinek  * or http://www.opensolaris.org/os/licensing.
10767Ssjelinek  * See the License for the specific language governing permissions
11767Ssjelinek  * and limitations under the License.
12767Ssjelinek  *
13767Ssjelinek  * When distributing Covered Code, include this CDDL HEADER in each
14767Ssjelinek  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15767Ssjelinek  * If applicable, add the following below this CDDL HEADER, with the
16767Ssjelinek  * fields enclosed by brackets "[]" replaced with your own identifying
17767Ssjelinek  * information: Portions Copyright [yyyy] [name of copyright owner]
18767Ssjelinek  *
19767Ssjelinek  * CDDL HEADER END
20767Ssjelinek  */
21767Ssjelinek /*
221352Seschrock  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23767Ssjelinek  * Use is subject to license terms.
24767Ssjelinek  */
25767Ssjelinek 
26767Ssjelinek #pragma ident	"%Z%%M%	%I%	%E% SMI"
27767Ssjelinek 
28767Ssjelinek /*
29767Ssjelinek  * Attempt to dynamically link in the ZFS libzfs.so.1 so that we can
30767Ssjelinek  * see if there are any ZFS zpools on any of the slices.
31767Ssjelinek  */
32767Ssjelinek 
33767Ssjelinek #include <stdlib.h>
34767Ssjelinek #include <stdio.h>
35767Ssjelinek #include <strings.h>
361594Slling #include <unistd.h>
37767Ssjelinek #include <sys/param.h>
38767Ssjelinek #include <sys/errno.h>
39767Ssjelinek #include <sys/types.h>
40767Ssjelinek #include <sys/stat.h>
41767Ssjelinek #include <fcntl.h>
42767Ssjelinek #include <thread.h>
43767Ssjelinek #include <synch.h>
44767Ssjelinek #include <dlfcn.h>
45767Ssjelinek #include <link.h>
46767Ssjelinek #include <ctype.h>
471352Seschrock #include <sys/fs/zfs.h>
48767Ssjelinek 
49*2082Seschrock #include <libzfs.h>
50767Ssjelinek #include "libdiskmgt.h"
51767Ssjelinek #include "disks_private.h"
52767Ssjelinek 
53767Ssjelinek /*
54767Ssjelinek  * Pointers to libzfs.so functions that we dynamically resolve.
55767Ssjelinek  */
56*2082Seschrock static int (*zfsdl_zpool_in_use)(libzfs_handle_t *hdl, int fd,
57*2082Seschrock     pool_state_t *state, char **name, boolean_t *);
58*2082Seschrock static libzfs_handle_t *(*zfsdl_libzfs_init)(boolean_t);
59767Ssjelinek 
60767Ssjelinek static mutex_t			init_lock = DEFAULTMUTEX;
61767Ssjelinek static rwlock_t			zpool_lock = DEFAULTRWLOCK;
62*2082Seschrock static boolean_t		initialized;
63*2082Seschrock static libzfs_handle_t		*zfs_hdl;
64767Ssjelinek 
65767Ssjelinek static void	*init_zpool();
66767Ssjelinek 
671352Seschrock static int
681352Seschrock inuse_zpool_common(char *slice, nvlist_t *attrs, int *errp, char *type)
69767Ssjelinek {
70767Ssjelinek 	int		found = 0;
711352Seschrock 	char		*name;
72767Ssjelinek 	int		fd;
731352Seschrock 	pool_state_t	state;
74*2082Seschrock 	boolean_t	used;
75767Ssjelinek 
76767Ssjelinek 	*errp = 0;
77767Ssjelinek 	if (slice == NULL) {
78767Ssjelinek 	    return (found);
79767Ssjelinek 	}
80767Ssjelinek 
81767Ssjelinek 	(void) mutex_lock(&init_lock);
82767Ssjelinek 
83767Ssjelinek 	/*
84767Ssjelinek 	 * Dynamically load libzfs
85767Ssjelinek 	 */
86767Ssjelinek 	if (!initialized) {
87767Ssjelinek 		if (!init_zpool()) {
88767Ssjelinek 			(void) mutex_unlock(&init_lock);
89767Ssjelinek 			return (found);
90767Ssjelinek 		}
91*2082Seschrock 		initialized = B_TRUE;
92767Ssjelinek 	}
93767Ssjelinek 	(void) mutex_unlock(&init_lock);
94767Ssjelinek 	(void) rw_rdlock(&zpool_lock);
95767Ssjelinek 	if ((fd = open(slice, O_RDONLY)) > 0) {
96*2082Seschrock 		name = NULL;
97*2082Seschrock 		if (zfsdl_zpool_in_use(zfs_hdl, fd, &state,
98*2082Seschrock 		    &name, &used) == 0 && used) {
991352Seschrock 			if (strcmp(type, DM_USE_ACTIVE_ZPOOL) == 0) {
100*2082Seschrock 				if (state == POOL_STATE_ACTIVE) {
1011352Seschrock 					found = 1;
102*2082Seschrock 				} else if (state == POOL_STATE_SPARE) {
103*2082Seschrock 					found = 1;
104*2082Seschrock 					type = DM_USE_SPARE_ZPOOL;
105*2082Seschrock 				}
1061352Seschrock 			} else {
1071352Seschrock 				found = 1;
1081352Seschrock 			}
1091352Seschrock 
1101352Seschrock 			if (found) {
1111352Seschrock 				libdiskmgt_add_str(attrs, DM_USED_BY,
1121352Seschrock 				    type, errp);
1131352Seschrock 				libdiskmgt_add_str(attrs, DM_USED_NAME,
114*2082Seschrock 				    name, errp);
1151352Seschrock 			}
116767Ssjelinek 		}
117*2082Seschrock 		if (name)
118*2082Seschrock 			free(name);
1191594Slling 		(void) close(fd);
120767Ssjelinek 	}
121767Ssjelinek 	(void) rw_unlock(&zpool_lock);
122767Ssjelinek 
123767Ssjelinek 	return (found);
124767Ssjelinek }
125767Ssjelinek 
1261352Seschrock int
1271352Seschrock inuse_active_zpool(char *slice, nvlist_t *attrs, int *errp)
1281352Seschrock {
1291352Seschrock 	return (inuse_zpool_common(slice, attrs, errp, DM_USE_ACTIVE_ZPOOL));
1301352Seschrock }
1311352Seschrock 
1321352Seschrock int
1331352Seschrock inuse_exported_zpool(char *slice, nvlist_t *attrs, int *errp)
1341352Seschrock {
1351352Seschrock 	return (inuse_zpool_common(slice, attrs, errp, DM_USE_EXPORTED_ZPOOL));
1361352Seschrock }
1371352Seschrock 
138767Ssjelinek /*
139767Ssjelinek  * Try to dynamically link the zfs functions we need.
140767Ssjelinek  */
141767Ssjelinek static void*
142767Ssjelinek init_zpool()
143767Ssjelinek {
144767Ssjelinek 	void	*lh = NULL;
145767Ssjelinek 
146767Ssjelinek 	if ((lh = dlopen("libzfs.so", RTLD_NOW)) == NULL) {
147767Ssjelinek 		return (lh);
148767Ssjelinek 	}
149*2082Seschrock 
150767Ssjelinek 	/*
151767Ssjelinek 	 * Instantiate the functions needed to get zpool configuration
152767Ssjelinek 	 * data
153767Ssjelinek 	 */
154*2082Seschrock 	if ((zfsdl_libzfs_init = (libzfs_handle_t *(*)(boolean_t))
155*2082Seschrock 	    dlsym(lh, "libzfs_init")) == NULL ||
156*2082Seschrock 	    (zfsdl_zpool_in_use = (int (*)(libzfs_handle_t *, int,
157*2082Seschrock 	    pool_state_t *, char **, boolean_t *))
1581352Seschrock 	    dlsym(lh, "zpool_in_use")) == NULL) {
159767Ssjelinek 		(void) dlclose(lh);
160767Ssjelinek 		return (NULL);
161767Ssjelinek 	}
162767Ssjelinek 
163*2082Seschrock 	if ((zfs_hdl = (*zfsdl_libzfs_init)(B_FALSE)) == NULL) {
164*2082Seschrock 		(void) dlclose(lh);
165*2082Seschrock 		return (NULL);
166*2082Seschrock 	}
167*2082Seschrock 
168767Ssjelinek 	return (lh);
169767Ssjelinek }
170