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