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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <fm/fmd_fmri.h> 29 #include <strings.h> 30 #include <libzfs.h> 31 32 typedef struct cbdata { 33 uint64_t cb_guid; 34 zpool_handle_t *cb_pool; 35 } cbdata_t; 36 37 libzfs_handle_t *g_zfs; 38 39 static int 40 find_pool(zpool_handle_t *zhp, void *data) 41 { 42 cbdata_t *cbp = data; 43 44 if (zpool_get_prop_int(zhp, ZPOOL_PROP_GUID, NULL) == cbp->cb_guid) { 45 cbp->cb_pool = zhp; 46 return (1); 47 } 48 49 zpool_close(zhp); 50 51 return (0); 52 } 53 54 ssize_t 55 fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) 56 { 57 uint64_t pool_guid, vdev_guid; 58 cbdata_t cb; 59 ssize_t len; 60 const char *name; 61 char guidbuf[64]; 62 63 (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 64 65 /* 66 * Attempt to convert the pool guid to a name. 67 */ 68 cb.cb_guid = pool_guid; 69 cb.cb_pool = NULL; 70 71 if (zpool_iter(g_zfs, find_pool, &cb) == 1) { 72 name = zpool_get_name(cb.cb_pool); 73 } else { 74 (void) snprintf(guidbuf, sizeof (guidbuf), "%llx", pool_guid); 75 name = guidbuf; 76 } 77 78 if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) == 0) 79 len = snprintf(buf, buflen, "%s://pool=%s/vdev=%llx", 80 FM_FMRI_SCHEME_ZFS, name, vdev_guid); 81 else 82 len = snprintf(buf, buflen, "%s://pool=%s", 83 FM_FMRI_SCHEME_ZFS, name); 84 85 if (cb.cb_pool) 86 zpool_close(cb.cb_pool); 87 88 return (len); 89 } 90 91 static nvlist_t * 92 find_vdev_iter(nvlist_t *nv, uint64_t search) 93 { 94 uint_t c, children; 95 nvlist_t **child; 96 uint64_t guid; 97 nvlist_t *ret; 98 99 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid); 100 101 if (search == guid) 102 return (nv); 103 104 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 105 &child, &children) != 0) 106 return (NULL); 107 108 for (c = 0; c < children; c++) 109 if ((ret = find_vdev_iter(child[c], search)) != 0) 110 return (ret); 111 112 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 113 &child, &children) != 0) 114 return (NULL); 115 116 for (c = 0; c < children; c++) 117 if ((ret = find_vdev_iter(child[c], search)) != 0) 118 return (ret); 119 120 return (NULL); 121 } 122 123 static nvlist_t * 124 find_vdev(zpool_handle_t *zhp, uint64_t guid) 125 { 126 nvlist_t *config, *nvroot; 127 128 config = zpool_get_config(zhp, NULL); 129 130 (void) nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot); 131 132 return (find_vdev_iter(nvroot, guid)); 133 } 134 135 int 136 fmd_fmri_present(nvlist_t *nvl) 137 { 138 uint64_t pool_guid, vdev_guid; 139 cbdata_t cb; 140 int ret; 141 142 (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 143 144 cb.cb_guid = pool_guid; 145 cb.cb_pool = NULL; 146 147 if (zpool_iter(g_zfs, find_pool, &cb) != 1) 148 return (0); 149 150 if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { 151 zpool_close(cb.cb_pool); 152 return (1); 153 } 154 155 ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL); 156 157 zpool_close(cb.cb_pool); 158 159 return (ret); 160 } 161 162 int 163 fmd_fmri_unusable(nvlist_t *nvl) 164 { 165 uint64_t pool_guid, vdev_guid; 166 cbdata_t cb; 167 nvlist_t *vd; 168 int ret; 169 170 (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 171 172 cb.cb_guid = pool_guid; 173 cb.cb_pool = NULL; 174 175 if (zpool_iter(g_zfs, find_pool, &cb) != 1) 176 return (1); 177 178 if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { 179 ret = (zpool_get_state(cb.cb_pool) == POOL_STATE_UNAVAIL); 180 zpool_close(cb.cb_pool); 181 return (ret); 182 } 183 184 vd = find_vdev(cb.cb_pool, vdev_guid); 185 if (vd == NULL) { 186 ret = 1; 187 } else { 188 vdev_stat_t *vs; 189 uint_t c; 190 191 (void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_STATS, 192 (uint64_t **)&vs, &c); 193 194 ret = (vs->vs_state < VDEV_STATE_DEGRADED); 195 } 196 197 zpool_close(cb.cb_pool); 198 199 return (ret); 200 } 201 202 int 203 fmd_fmri_init(void) 204 { 205 g_zfs = libzfs_init(); 206 207 if (g_zfs == NULL) 208 return (-1); 209 else 210 return (0); 211 } 212 213 void 214 fmd_fmri_fini(void) 215 { 216 if (g_zfs) 217 libzfs_fini(g_zfs); 218 } 219