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 2006 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_guid(zhp) == 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 (0); 107 108 for (c = 0; c < children; c++) 109 if ((ret = find_vdev_iter(child[c], search)) != 0) 110 return (ret); 111 112 return (NULL); 113 } 114 115 static nvlist_t * 116 find_vdev(zpool_handle_t *zhp, uint64_t guid) 117 { 118 nvlist_t *config; 119 nvlist_t *nvroot; 120 121 config = zpool_get_config(zhp, NULL); 122 123 (void) nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot); 124 125 return (find_vdev_iter(nvroot, guid)); 126 } 127 128 int 129 fmd_fmri_present(nvlist_t *nvl) 130 { 131 uint64_t pool_guid, vdev_guid; 132 cbdata_t cb; 133 int ret; 134 135 (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 136 137 cb.cb_guid = pool_guid; 138 cb.cb_pool = NULL; 139 140 if (zpool_iter(g_zfs, find_pool, &cb) != 1) 141 return (0); 142 143 if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { 144 zpool_close(cb.cb_pool); 145 return (1); 146 } 147 148 ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL); 149 150 zpool_close(cb.cb_pool); 151 152 return (ret); 153 } 154 155 int 156 fmd_fmri_unusable(nvlist_t *nvl) 157 { 158 uint64_t pool_guid, vdev_guid; 159 cbdata_t cb; 160 nvlist_t *vd; 161 int ret; 162 163 (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 164 165 cb.cb_guid = pool_guid; 166 cb.cb_pool = NULL; 167 168 if (zpool_iter(g_zfs, find_pool, &cb) != 1) 169 return (1); 170 171 if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { 172 ret = (zpool_get_state(cb.cb_pool) == POOL_STATE_UNAVAIL); 173 zpool_close(cb.cb_pool); 174 return (ret); 175 } 176 177 vd = find_vdev(cb.cb_pool, vdev_guid); 178 if (vd == NULL) { 179 ret = 1; 180 } else { 181 vdev_stat_t *vs; 182 uint_t c; 183 184 (void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_STATS, 185 (uint64_t **)&vs, &c); 186 187 ret = (vs->vs_state < VDEV_STATE_DEGRADED); 188 } 189 190 zpool_close(cb.cb_pool); 191 192 return (ret); 193 } 194 195 int 196 fmd_fmri_init(void) 197 { 198 g_zfs = libzfs_init(); 199 200 if (g_zfs == NULL) 201 return (-1); 202 else 203 return (0); 204 } 205 206 void 207 fmd_fmri_fini(void) 208 { 209 if (g_zfs) 210 libzfs_fini(g_zfs); 211 } 212