Home | History | Annotate | Download | only in zfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <fm/fmd_fmri.h>
     27 #include <strings.h>
     28 #include <libzfs.h>
     29 
     30 typedef struct cbdata {
     31 	uint64_t	cb_guid;
     32 	zpool_handle_t	*cb_pool;
     33 } cbdata_t;
     34 
     35 libzfs_handle_t *g_zfs;
     36 
     37 static int
     38 find_pool(zpool_handle_t *zhp, void *data)
     39 {
     40 	cbdata_t *cbp = data;
     41 
     42 	if (zpool_get_prop_int(zhp, ZPOOL_PROP_GUID, NULL) == cbp->cb_guid) {
     43 		cbp->cb_pool = zhp;
     44 		return (1);
     45 	}
     46 
     47 	zpool_close(zhp);
     48 
     49 	return (0);
     50 }
     51 
     52 ssize_t
     53 fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
     54 {
     55 	uint64_t pool_guid, vdev_guid;
     56 	cbdata_t cb;
     57 	ssize_t len;
     58 	const char *name;
     59 	char guidbuf[64];
     60 
     61 	(void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
     62 
     63 	/*
     64 	 * Attempt to convert the pool guid to a name.
     65 	 */
     66 	cb.cb_guid = pool_guid;
     67 	cb.cb_pool = NULL;
     68 
     69 	if (zpool_iter(g_zfs, find_pool, &cb) == 1) {
     70 		name = zpool_get_name(cb.cb_pool);
     71 	} else {
     72 		(void) snprintf(guidbuf, sizeof (guidbuf), "%llx", pool_guid);
     73 		name = guidbuf;
     74 	}
     75 
     76 	if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) == 0)
     77 		len = snprintf(buf, buflen, "%s://pool=%s/vdev=%llx",
     78 		    FM_FMRI_SCHEME_ZFS, name, vdev_guid);
     79 	else
     80 		len = snprintf(buf, buflen, "%s://pool=%s",
     81 		    FM_FMRI_SCHEME_ZFS, name);
     82 
     83 	if (cb.cb_pool)
     84 		zpool_close(cb.cb_pool);
     85 
     86 	return (len);
     87 }
     88 
     89 static nvlist_t *
     90 find_vdev_iter(nvlist_t *nv, uint64_t search)
     91 {
     92 	uint_t c, children;
     93 	nvlist_t **child;
     94 	uint64_t guid;
     95 	nvlist_t *ret;
     96 
     97 	(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid);
     98 
     99 	if (search == guid)
    100 		return (nv);
    101 
    102 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
    103 	    &child, &children) != 0)
    104 		return (NULL);
    105 
    106 	for (c = 0; c < children; c++)
    107 		if ((ret = find_vdev_iter(child[c], search)) != 0)
    108 			return (ret);
    109 
    110 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
    111 	    &child, &children) != 0)
    112 		return (NULL);
    113 
    114 	for (c = 0; c < children; c++)
    115 		if ((ret = find_vdev_iter(child[c], search)) != 0)
    116 			return (ret);
    117 
    118 	return (NULL);
    119 }
    120 
    121 static nvlist_t *
    122 find_vdev(zpool_handle_t *zhp, uint64_t guid)
    123 {
    124 	nvlist_t *config, *nvroot;
    125 
    126 	config = zpool_get_config(zhp, NULL);
    127 
    128 	(void) nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot);
    129 
    130 	return (find_vdev_iter(nvroot, guid));
    131 }
    132 
    133 int
    134 fmd_fmri_present(nvlist_t *nvl)
    135 {
    136 	uint64_t pool_guid, vdev_guid;
    137 	cbdata_t cb;
    138 	int ret;
    139 
    140 	(void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
    141 
    142 	cb.cb_guid = pool_guid;
    143 	cb.cb_pool = NULL;
    144 
    145 	if (zpool_iter(g_zfs, find_pool, &cb) != 1)
    146 		return (0);
    147 
    148 	if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) {
    149 		zpool_close(cb.cb_pool);
    150 		return (1);
    151 	}
    152 
    153 	ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL);
    154 
    155 	zpool_close(cb.cb_pool);
    156 
    157 	return (ret);
    158 }
    159 
    160 int
    161 fmd_fmri_replaced(nvlist_t *nvl)
    162 {
    163 	uint64_t pool_guid, vdev_guid;
    164 	cbdata_t cb;
    165 	int ret;
    166 
    167 	(void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
    168 
    169 	cb.cb_guid = pool_guid;
    170 	cb.cb_pool = NULL;
    171 
    172 	if (zpool_iter(g_zfs, find_pool, &cb) != 1)
    173 		return (FMD_OBJ_STATE_NOT_PRESENT);
    174 
    175 	if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) {
    176 		zpool_close(cb.cb_pool);
    177 		return (FMD_OBJ_STATE_STILL_PRESENT);
    178 	}
    179 
    180 	ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL) ?
    181 	    FMD_OBJ_STATE_STILL_PRESENT : FMD_OBJ_STATE_NOT_PRESENT;
    182 
    183 	zpool_close(cb.cb_pool);
    184 
    185 	return (ret);
    186 }
    187 
    188 int
    189 fmd_fmri_unusable(nvlist_t *nvl)
    190 {
    191 	uint64_t pool_guid, vdev_guid;
    192 	cbdata_t cb;
    193 	nvlist_t *vd;
    194 	int ret;
    195 
    196 	(void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
    197 
    198 	cb.cb_guid = pool_guid;
    199 	cb.cb_pool = NULL;
    200 
    201 	if (zpool_iter(g_zfs, find_pool, &cb) != 1)
    202 		return (1);
    203 
    204 	if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) {
    205 		ret = (zpool_get_state(cb.cb_pool) == POOL_STATE_UNAVAIL);
    206 		zpool_close(cb.cb_pool);
    207 		return (ret);
    208 	}
    209 
    210 	vd = find_vdev(cb.cb_pool, vdev_guid);
    211 	if (vd == NULL) {
    212 		ret = 1;
    213 	} else {
    214 		vdev_stat_t *vs;
    215 		uint_t c;
    216 
    217 		(void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_STATS,
    218 		    (uint64_t **)&vs, &c);
    219 
    220 		ret = (vs->vs_state < VDEV_STATE_DEGRADED);
    221 	}
    222 
    223 	zpool_close(cb.cb_pool);
    224 
    225 	return (ret);
    226 }
    227 
    228 int
    229 fmd_fmri_init(void)
    230 {
    231 	g_zfs = libzfs_init();
    232 
    233 	if (g_zfs == NULL)
    234 		return (-1);
    235 	else
    236 		return (0);
    237 }
    238 
    239 void
    240 fmd_fmri_fini(void)
    241 {
    242 	if (g_zfs)
    243 		libzfs_fini(g_zfs);
    244 }
    245