1767Ssjelinek /*
2767Ssjelinek  * CDDL HEADER START
3767Ssjelinek  *
4767Ssjelinek  * The contents of this file are subject to the terms of the
5767Ssjelinek  * Common Development and Distribution License, Version 1.0 only
6767Ssjelinek  * (the "License").  You may not use this file except in compliance
7767Ssjelinek  * with the License.
8767Ssjelinek  *
9767Ssjelinek  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10767Ssjelinek  * or http://www.opensolaris.org/os/licensing.
11767Ssjelinek  * See the License for the specific language governing permissions
12767Ssjelinek  * and limitations under the License.
13767Ssjelinek  *
14767Ssjelinek  * When distributing Covered Code, include this CDDL HEADER in each
15767Ssjelinek  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16767Ssjelinek  * If applicable, add the following below this CDDL HEADER, with the
17767Ssjelinek  * fields enclosed by brackets "[]" replaced with your own identifying
18767Ssjelinek  * information: Portions Copyright [yyyy] [name of copyright owner]
19767Ssjelinek  *
20767Ssjelinek  * CDDL HEADER END
21767Ssjelinek  */
22767Ssjelinek /*
23*1352Seschrock  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24767Ssjelinek  * Use is subject to license terms.
25767Ssjelinek  */
26767Ssjelinek 
27767Ssjelinek #pragma ident	"%Z%%M%	%I%	%E% SMI"
28767Ssjelinek 
29767Ssjelinek /*
30767Ssjelinek  * Attempt to dynamically link in the ZFS libzfs.so.1 so that we can
31767Ssjelinek  * see if there are any ZFS zpools on any of the slices.
32767Ssjelinek  */
33767Ssjelinek 
34767Ssjelinek #include <stdlib.h>
35767Ssjelinek #include <stdio.h>
36767Ssjelinek #include <strings.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>
47*1352Seschrock #include <sys/fs/zfs.h>
48767Ssjelinek 
49767Ssjelinek #include "libdiskmgt.h"
50767Ssjelinek #include "disks_private.h"
51767Ssjelinek 
52767Ssjelinek /*
53767Ssjelinek  * Pointers to libzfs.so functions that we dynamically resolve.
54767Ssjelinek  */
55*1352Seschrock static	int	(*zfsdl_zpool_in_use)(int fd, pool_state_t *state, char **name);
56767Ssjelinek 
57767Ssjelinek static mutex_t			init_lock = DEFAULTMUTEX;
58767Ssjelinek static rwlock_t			zpool_lock = DEFAULTRWLOCK;
59767Ssjelinek static	int			initialized = 0;
60767Ssjelinek 
61767Ssjelinek static void	*init_zpool();
62767Ssjelinek 
63*1352Seschrock static int
64*1352Seschrock inuse_zpool_common(char *slice, nvlist_t *attrs, int *errp, char *type)
65767Ssjelinek {
66767Ssjelinek 	int		found = 0;
67*1352Seschrock 	char		*name;
68767Ssjelinek 	int		fd;
69*1352Seschrock 	pool_state_t	state;
70767Ssjelinek 
71767Ssjelinek 	*errp = 0;
72767Ssjelinek 	if (slice == NULL) {
73767Ssjelinek 	    return (found);
74767Ssjelinek 	}
75767Ssjelinek 
76767Ssjelinek 	(void) mutex_lock(&init_lock);
77767Ssjelinek 
78767Ssjelinek 	/*
79767Ssjelinek 	 * Dynamically load libzfs
80767Ssjelinek 	 */
81767Ssjelinek 	if (!initialized) {
82767Ssjelinek 		if (!init_zpool()) {
83767Ssjelinek 			(void) mutex_unlock(&init_lock);
84767Ssjelinek 			return (found);
85767Ssjelinek 		}
86767Ssjelinek 		initialized = 1;
87767Ssjelinek 	}
88767Ssjelinek 	(void) mutex_unlock(&init_lock);
89767Ssjelinek 	(void) rw_rdlock(&zpool_lock);
90767Ssjelinek 	if ((fd = open(slice, O_RDONLY)) > 0) {
91*1352Seschrock 		if (zfsdl_zpool_in_use(fd, &state, &name)) {
92*1352Seschrock 			if (strcmp(type, DM_USE_ACTIVE_ZPOOL) == 0) {
93*1352Seschrock 				if (state == POOL_STATE_ACTIVE)
94*1352Seschrock 					found = 1;
95*1352Seschrock 			} else {
96*1352Seschrock 				found = 1;
97*1352Seschrock 			}
98*1352Seschrock 
99*1352Seschrock 			if (found) {
100*1352Seschrock 				libdiskmgt_add_str(attrs, DM_USED_BY,
101*1352Seschrock 				    type, errp);
102*1352Seschrock 				libdiskmgt_add_str(attrs, DM_USED_NAME,
103*1352Seschrock 					name, errp);
104*1352Seschrock 			}
105767Ssjelinek 		}
106767Ssjelinek 	}
107767Ssjelinek 	(void) rw_unlock(&zpool_lock);
108767Ssjelinek 
109767Ssjelinek 	return (found);
110767Ssjelinek }
111767Ssjelinek 
112*1352Seschrock int
113*1352Seschrock inuse_active_zpool(char *slice, nvlist_t *attrs, int *errp)
114*1352Seschrock {
115*1352Seschrock 	return (inuse_zpool_common(slice, attrs, errp, DM_USE_ACTIVE_ZPOOL));
116*1352Seschrock }
117*1352Seschrock 
118*1352Seschrock int
119*1352Seschrock inuse_exported_zpool(char *slice, nvlist_t *attrs, int *errp)
120*1352Seschrock {
121*1352Seschrock 	return (inuse_zpool_common(slice, attrs, errp, DM_USE_EXPORTED_ZPOOL));
122*1352Seschrock }
123*1352Seschrock 
124767Ssjelinek /*
125767Ssjelinek  * Try to dynamically link the zfs functions we need.
126767Ssjelinek  */
127767Ssjelinek static void*
128767Ssjelinek init_zpool()
129767Ssjelinek {
130767Ssjelinek 	void	*lh = NULL;
131767Ssjelinek 
132767Ssjelinek 	if ((lh = dlopen("libzfs.so", RTLD_NOW)) == NULL) {
133767Ssjelinek 		return (lh);
134767Ssjelinek 	}
135767Ssjelinek 	/*
136767Ssjelinek 	 * Instantiate the functions needed to get zpool configuration
137767Ssjelinek 	 * data
138767Ssjelinek 	 */
139*1352Seschrock 	if ((zfsdl_zpool_in_use = (int (*)(int, pool_state_t *, char **))
140*1352Seschrock 	    dlsym(lh, "zpool_in_use")) == NULL) {
141767Ssjelinek 		(void) dlclose(lh);
142767Ssjelinek 		return (NULL);
143767Ssjelinek 	}
144767Ssjelinek 
145767Ssjelinek 	return (lh);
146767Ssjelinek }
147