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 #pragma ident "%Z%%M% %I% %E% SMI"
273e1bd7a2Ssjelinek
283e1bd7a2Ssjelinek /*
293e1bd7a2Ssjelinek * Attempt to dynamically link in the ZFS libzfs.so.1 so that we can
303e1bd7a2Ssjelinek * see if there are any ZFS zpools on any of the slices.
313e1bd7a2Ssjelinek */
323e1bd7a2Ssjelinek
333e1bd7a2Ssjelinek #include <stdlib.h>
343e1bd7a2Ssjelinek #include <stdio.h>
353e1bd7a2Ssjelinek #include <strings.h>
36752712d2Slling #include <unistd.h>
373e1bd7a2Ssjelinek #include <sys/param.h>
383e1bd7a2Ssjelinek #include <sys/errno.h>
393e1bd7a2Ssjelinek #include <sys/types.h>
403e1bd7a2Ssjelinek #include <sys/stat.h>
413e1bd7a2Ssjelinek #include <fcntl.h>
423e1bd7a2Ssjelinek #include <thread.h>
433e1bd7a2Ssjelinek #include <synch.h>
443e1bd7a2Ssjelinek #include <dlfcn.h>
453e1bd7a2Ssjelinek #include <link.h>
463e1bd7a2Ssjelinek #include <ctype.h>
4746a2abf2Seschrock #include <sys/fs/zfs.h>
483e1bd7a2Ssjelinek
4999653d4eSeschrock #include <libzfs.h>
503e1bd7a2Ssjelinek #include "libdiskmgt.h"
513e1bd7a2Ssjelinek #include "disks_private.h"
523e1bd7a2Ssjelinek
533e1bd7a2Ssjelinek /*
543e1bd7a2Ssjelinek * Pointers to libzfs.so functions that we dynamically resolve.
553e1bd7a2Ssjelinek */
5699653d4eSeschrock static int (*zfsdl_zpool_in_use)(libzfs_handle_t *hdl, int fd,
5799653d4eSeschrock pool_state_t *state, char **name, boolean_t *);
5899653d4eSeschrock static libzfs_handle_t *(*zfsdl_libzfs_init)(boolean_t);
593e1bd7a2Ssjelinek
603e1bd7a2Ssjelinek static mutex_t init_lock = DEFAULTMUTEX;
613e1bd7a2Ssjelinek static rwlock_t zpool_lock = DEFAULTRWLOCK;
6299653d4eSeschrock static boolean_t initialized;
6399653d4eSeschrock static libzfs_handle_t *zfs_hdl;
643e1bd7a2Ssjelinek
653e1bd7a2Ssjelinek static void *init_zpool();
663e1bd7a2Ssjelinek
6746a2abf2Seschrock static int
inuse_zpool_common(char * slice,nvlist_t * attrs,int * errp,char * type)6846a2abf2Seschrock inuse_zpool_common(char *slice, nvlist_t *attrs, int *errp, char *type)
693e1bd7a2Ssjelinek {
703e1bd7a2Ssjelinek int found = 0;
7146a2abf2Seschrock char *name;
723e1bd7a2Ssjelinek int fd;
7346a2abf2Seschrock pool_state_t state;
7499653d4eSeschrock boolean_t used;
753e1bd7a2Ssjelinek
763e1bd7a2Ssjelinek *errp = 0;
773e1bd7a2Ssjelinek if (slice == NULL) {
783e1bd7a2Ssjelinek return (found);
793e1bd7a2Ssjelinek }
803e1bd7a2Ssjelinek
813e1bd7a2Ssjelinek (void) mutex_lock(&init_lock);
823e1bd7a2Ssjelinek
833e1bd7a2Ssjelinek /*
843e1bd7a2Ssjelinek * Dynamically load libzfs
853e1bd7a2Ssjelinek */
863e1bd7a2Ssjelinek if (!initialized) {
873e1bd7a2Ssjelinek if (!init_zpool()) {
883e1bd7a2Ssjelinek (void) mutex_unlock(&init_lock);
893e1bd7a2Ssjelinek return (found);
903e1bd7a2Ssjelinek }
9199653d4eSeschrock initialized = B_TRUE;
923e1bd7a2Ssjelinek }
933e1bd7a2Ssjelinek (void) mutex_unlock(&init_lock);
943e1bd7a2Ssjelinek (void) rw_rdlock(&zpool_lock);
953e1bd7a2Ssjelinek if ((fd = open(slice, O_RDONLY)) > 0) {
9699653d4eSeschrock name = NULL;
9799653d4eSeschrock if (zfsdl_zpool_in_use(zfs_hdl, fd, &state,
9899653d4eSeschrock &name, &used) == 0 && used) {
9946a2abf2Seschrock if (strcmp(type, DM_USE_ACTIVE_ZPOOL) == 0) {
10099653d4eSeschrock if (state == POOL_STATE_ACTIVE) {
10146a2abf2Seschrock found = 1;
10299653d4eSeschrock } else if (state == POOL_STATE_SPARE) {
10399653d4eSeschrock found = 1;
10499653d4eSeschrock type = DM_USE_SPARE_ZPOOL;
105*fa94a07fSbrendan } else if (state == POOL_STATE_L2CACHE) {
106*fa94a07fSbrendan found = 1;
107*fa94a07fSbrendan type = DM_USE_L2CACHE_ZPOOL;
10899653d4eSeschrock }
10946a2abf2Seschrock } else {
11046a2abf2Seschrock found = 1;
11146a2abf2Seschrock }
11246a2abf2Seschrock
11346a2abf2Seschrock if (found) {
1143e1bd7a2Ssjelinek libdiskmgt_add_str(attrs, DM_USED_BY,
11546a2abf2Seschrock type, errp);
1163e1bd7a2Ssjelinek libdiskmgt_add_str(attrs, DM_USED_NAME,
1173e1bd7a2Ssjelinek name, errp);
11846a2abf2Seschrock }
1193e1bd7a2Ssjelinek }
12099653d4eSeschrock if (name)
12199653d4eSeschrock free(name);
122752712d2Slling (void) close(fd);
1233e1bd7a2Ssjelinek }
1243e1bd7a2Ssjelinek (void) rw_unlock(&zpool_lock);
1253e1bd7a2Ssjelinek
1263e1bd7a2Ssjelinek return (found);
1273e1bd7a2Ssjelinek }
1283e1bd7a2Ssjelinek
12946a2abf2Seschrock int
inuse_active_zpool(char * slice,nvlist_t * attrs,int * errp)13046a2abf2Seschrock inuse_active_zpool(char *slice, nvlist_t *attrs, int *errp)
13146a2abf2Seschrock {
13246a2abf2Seschrock return (inuse_zpool_common(slice, attrs, errp, DM_USE_ACTIVE_ZPOOL));
13346a2abf2Seschrock }
13446a2abf2Seschrock
13546a2abf2Seschrock int
inuse_exported_zpool(char * slice,nvlist_t * attrs,int * errp)13646a2abf2Seschrock inuse_exported_zpool(char *slice, nvlist_t *attrs, int *errp)
13746a2abf2Seschrock {
13846a2abf2Seschrock return (inuse_zpool_common(slice, attrs, errp, DM_USE_EXPORTED_ZPOOL));
13946a2abf2Seschrock }
14046a2abf2Seschrock
1413e1bd7a2Ssjelinek /*
1423e1bd7a2Ssjelinek * Try to dynamically link the zfs functions we need.
1433e1bd7a2Ssjelinek */
1443e1bd7a2Ssjelinek static void*
init_zpool()1453e1bd7a2Ssjelinek init_zpool()
1463e1bd7a2Ssjelinek {
1473e1bd7a2Ssjelinek void *lh = NULL;
1483e1bd7a2Ssjelinek
1493e1bd7a2Ssjelinek if ((lh = dlopen("libzfs.so", RTLD_NOW)) == NULL) {
1503e1bd7a2Ssjelinek return (lh);
1513e1bd7a2Ssjelinek }
15299653d4eSeschrock
1533e1bd7a2Ssjelinek /*
1543e1bd7a2Ssjelinek * Instantiate the functions needed to get zpool configuration
1553e1bd7a2Ssjelinek * data
1563e1bd7a2Ssjelinek */
15799653d4eSeschrock if ((zfsdl_libzfs_init = (libzfs_handle_t *(*)(boolean_t))
15899653d4eSeschrock dlsym(lh, "libzfs_init")) == NULL ||
15999653d4eSeschrock (zfsdl_zpool_in_use = (int (*)(libzfs_handle_t *, int,
16099653d4eSeschrock pool_state_t *, char **, boolean_t *))
16146a2abf2Seschrock dlsym(lh, "zpool_in_use")) == NULL) {
1623e1bd7a2Ssjelinek (void) dlclose(lh);
1633e1bd7a2Ssjelinek return (NULL);
1643e1bd7a2Ssjelinek }
1653e1bd7a2Ssjelinek
16699653d4eSeschrock if ((zfs_hdl = (*zfsdl_libzfs_init)(B_FALSE)) == NULL) {
16799653d4eSeschrock (void) dlclose(lh);
16899653d4eSeschrock return (NULL);
16999653d4eSeschrock }
17099653d4eSeschrock
1713e1bd7a2Ssjelinek return (lh);
1723e1bd7a2Ssjelinek }
173