13e1bd7a2Ssjelinek /*
23e1bd7a2Ssjelinek  * CDDL HEADER START
33e1bd7a2Ssjelinek  *
43e1bd7a2Ssjelinek  * The contents of this file are subject to the terms of the
5752712d2Slling  * Common Development and Distribution License (the "License").
6752712d2Slling  * You may not use this file except in compliance with the License.
73e1bd7a2Ssjelinek  *
83e1bd7a2Ssjelinek  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93e1bd7a2Ssjelinek  * or http://www.opensolaris.org/os/licensing.
103e1bd7a2Ssjelinek  * See the License for the specific language governing permissions
113e1bd7a2Ssjelinek  * and limitations under the License.
123e1bd7a2Ssjelinek  *
133e1bd7a2Ssjelinek  * When distributing Covered Code, include this CDDL HEADER in each
143e1bd7a2Ssjelinek  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153e1bd7a2Ssjelinek  * If applicable, add the following below this CDDL HEADER, with the
163e1bd7a2Ssjelinek  * fields enclosed by brackets "[]" replaced with your own identifying
173e1bd7a2Ssjelinek  * information: Portions Copyright [yyyy] [name of copyright owner]
183e1bd7a2Ssjelinek  *
193e1bd7a2Ssjelinek  * CDDL HEADER END
203e1bd7a2Ssjelinek  */
213e1bd7a2Ssjelinek /*
22*fa94a07fSbrendan  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
233e1bd7a2Ssjelinek  * Use is subject to license terms.
243e1bd7a2Ssjelinek  */
253e1bd7a2Ssjelinek 
263e1bd7a2Ssjelinek /*
273e1bd7a2Ssjelinek  * Attempt to dynamically link in the ZFS libzfs.so.1 so that we can
283e1bd7a2Ssjelinek  * see if there are any ZFS zpools on any of the slices.
293e1bd7a2Ssjelinek  */
303e1bd7a2Ssjelinek 
313e1bd7a2Ssjelinek #include <stdlib.h>
323e1bd7a2Ssjelinek #include <stdio.h>
333e1bd7a2Ssjelinek #include <strings.h>
34752712d2Slling #include <unistd.h>
353e1bd7a2Ssjelinek #include <sys/param.h>
363e1bd7a2Ssjelinek #include <sys/errno.h>
373e1bd7a2Ssjelinek #include <sys/types.h>
383e1bd7a2Ssjelinek #include <sys/stat.h>
393e1bd7a2Ssjelinek #include <fcntl.h>
403e1bd7a2Ssjelinek #include <thread.h>
413e1bd7a2Ssjelinek #include <synch.h>
423e1bd7a2Ssjelinek #include <dlfcn.h>
433e1bd7a2Ssjelinek #include <link.h>
443e1bd7a2Ssjelinek #include <ctype.h>
4546a2abf2Seschrock #include <sys/fs/zfs.h>
463e1bd7a2Ssjelinek 
4799653d4eSeschrock #include <libzfs.h>
483e1bd7a2Ssjelinek #include "libdiskmgt.h"
493e1bd7a2Ssjelinek #include "disks_private.h"
503e1bd7a2Ssjelinek 
513e1bd7a2Ssjelinek /*
523e1bd7a2Ssjelinek  * Pointers to libzfs.so functions that we dynamically resolve.
533e1bd7a2Ssjelinek  */
5499653d4eSeschrock static int (*zfsdl_zpool_in_use)(libzfs_handle_t *hdl, int fd,
5599653d4eSeschrock     pool_state_t *state, char **name, boolean_t *);
5699653d4eSeschrock static libzfs_handle_t *(*zfsdl_libzfs_init)(boolean_t);
573e1bd7a2Ssjelinek 
583e1bd7a2Ssjelinek static mutex_t			init_lock = DEFAULTMUTEX;
593e1bd7a2Ssjelinek static rwlock_t			zpool_lock = DEFAULTRWLOCK;
6099653d4eSeschrock static boolean_t		initialized;
6199653d4eSeschrock static libzfs_handle_t		*zfs_hdl;
623e1bd7a2Ssjelinek 
633e1bd7a2Ssjelinek static void	*init_zpool();
643e1bd7a2Ssjelinek 
6546a2abf2Seschrock static int
inuse_zpool_common(char * slice,nvlist_t * attrs,int * errp,char * type)6646a2abf2Seschrock inuse_zpool_common(char *slice, nvlist_t *attrs, int *errp, char *type)
673e1bd7a2Ssjelinek {
683e1bd7a2Ssjelinek 	int		found = 0;
6946a2abf2Seschrock 	char		*name;
703e1bd7a2Ssjelinek 	int		fd;
7146a2abf2Seschrock 	pool_state_t	state;
7299653d4eSeschrock 	boolean_t	used;
733e1bd7a2Ssjelinek 
743e1bd7a2Ssjelinek 	*errp = 0;
753e1bd7a2Ssjelinek 	if (slice == NULL) {
763e1bd7a2Ssjelinek 	    return (found);
773e1bd7a2Ssjelinek 	}
783e1bd7a2Ssjelinek 
793e1bd7a2Ssjelinek 	(void) mutex_lock(&init_lock);
803e1bd7a2Ssjelinek 
813e1bd7a2Ssjelinek 	/*
823e1bd7a2Ssjelinek 	 * Dynamically load libzfs
833e1bd7a2Ssjelinek 	 */
843e1bd7a2Ssjelinek 	if (!initialized) {
853e1bd7a2Ssjelinek 		if (!init_zpool()) {
863e1bd7a2Ssjelinek 			(void) mutex_unlock(&init_lock);
873e1bd7a2Ssjelinek 			return (found);
883e1bd7a2Ssjelinek 		}
8999653d4eSeschrock 		initialized = B_TRUE;
903e1bd7a2Ssjelinek 	}
913e1bd7a2Ssjelinek 	(void) mutex_unlock(&init_lock);
923e1bd7a2Ssjelinek 	(void) rw_rdlock(&zpool_lock);
933e1bd7a2Ssjelinek 	if ((fd = open(slice, O_RDONLY)) > 0) {
9499653d4eSeschrock 		name = NULL;
9599653d4eSeschrock 		if (zfsdl_zpool_in_use(zfs_hdl, fd, &state,
9699653d4eSeschrock 		    &name, &used) == 0 && used) {
9746a2abf2Seschrock 			if (strcmp(type, DM_USE_ACTIVE_ZPOOL) == 0) {
9899653d4eSeschrock 				if (state == POOL_STATE_ACTIVE) {
9946a2abf2Seschrock 					found = 1;
10099653d4eSeschrock 				} else if (state == POOL_STATE_SPARE) {
10199653d4eSeschrock 					found = 1;
10299653d4eSeschrock 					type = DM_USE_SPARE_ZPOOL;
103*fa94a07fSbrendan 				} else if (state == POOL_STATE_L2CACHE) {
104*fa94a07fSbrendan 					found = 1;
105*fa94a07fSbrendan 					type = DM_USE_L2CACHE_ZPOOL;
10699653d4eSeschrock 				}
10746a2abf2Seschrock 			} else {
10846a2abf2Seschrock 				found = 1;
10946a2abf2Seschrock 			}
11046a2abf2Seschrock 
11146a2abf2Seschrock 			if (found) {
11246a2abf2Seschrock 				libdiskmgt_add_str(attrs, DM_USED_BY,
11346a2abf2Seschrock 				    type, errp);
11446a2abf2Seschrock 				libdiskmgt_add_str(attrs, DM_USED_NAME,
11599653d4eSeschrock 				    name, errp);
11646a2abf2Seschrock 			}
1173e1bd7a2Ssjelinek 		}
11899653d4eSeschrock 		if (name)
11999653d4eSeschrock 			free(name);
120752712d2Slling 		(void) close(fd);
1213e1bd7a2Ssjelinek 	}
1223e1bd7a2Ssjelinek 	(void) rw_unlock(&zpool_lock);
1233e1bd7a2Ssjelinek 
1243e1bd7a2Ssjelinek 	return (found);
1253e1bd7a2Ssjelinek }
1263e1bd7a2Ssjelinek 
12746a2abf2Seschrock int
inuse_active_zpool(char * slice,nvlist_t * attrs,int * errp)12846a2abf2Seschrock inuse_active_zpool(char *slice, nvlist_t *attrs, int *errp)
12946a2abf2Seschrock {
13046a2abf2Seschrock 	return (inuse_zpool_common(slice, attrs, errp, DM_USE_ACTIVE_ZPOOL));
13146a2abf2Seschrock }
13246a2abf2Seschrock 
13346a2abf2Seschrock int
inuse_exported_zpool(char * slice,nvlist_t * attrs,int * errp)13446a2abf2Seschrock inuse_exported_zpool(char *slice, nvlist_t *attrs, int *errp)
13546a2abf2Seschrock {
13646a2abf2Seschrock 	return (inuse_zpool_common(slice, attrs, errp, DM_USE_EXPORTED_ZPOOL));
13746a2abf2Seschrock }
13846a2abf2Seschrock 
1393e1bd7a2Ssjelinek /*
1403e1bd7a2Ssjelinek  * Try to dynamically link the zfs functions we need.
1413e1bd7a2Ssjelinek  */
1423e1bd7a2Ssjelinek static void*
init_zpool()1433e1bd7a2Ssjelinek init_zpool()
1443e1bd7a2Ssjelinek {
1453e1bd7a2Ssjelinek 	void	*lh = NULL;
1463e1bd7a2Ssjelinek 
1473e1bd7a2Ssjelinek 	if ((lh = dlopen("libzfs.so", RTLD_NOW)) == NULL) {
1483e1bd7a2Ssjelinek 		return (lh);
1493e1bd7a2Ssjelinek 	}
15099653d4eSeschrock 
1513e1bd7a2Ssjelinek 	/*
1523e1bd7a2Ssjelinek 	 * Instantiate the functions needed to get zpool configuration
1533e1bd7a2Ssjelinek 	 * data
1543e1bd7a2Ssjelinek 	 */
15599653d4eSeschrock 	if ((zfsdl_libzfs_init = (libzfs_handle_t *(*)(boolean_t))
15699653d4eSeschrock 	    dlsym(lh, "libzfs_init")) == NULL ||
15799653d4eSeschrock 	    (zfsdl_zpool_in_use = (int (*)(libzfs_handle_t *, int,
15899653d4eSeschrock 	    pool_state_t *, char **, boolean_t *))
15946a2abf2Seschrock 	    dlsym(lh, "zpool_in_use")) == NULL) {
1603e1bd7a2Ssjelinek 		(void) dlclose(lh);
1613e1bd7a2Ssjelinek 		return (NULL);
1623e1bd7a2Ssjelinek 	}
1633e1bd7a2Ssjelinek 
16499653d4eSeschrock 	if ((zfs_hdl = (*zfsdl_libzfs_init)(B_FALSE)) == NULL) {
16599653d4eSeschrock 		(void) dlclose(lh);
16699653d4eSeschrock 		return (NULL);
16799653d4eSeschrock 	}
16899653d4eSeschrock 
1693e1bd7a2Ssjelinek 	return (lh);
1703e1bd7a2Ssjelinek }
171