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