1ea8dc4b6Seschrock /* 2ea8dc4b6Seschrock * CDDL HEADER START 3ea8dc4b6Seschrock * 4ea8dc4b6Seschrock * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7ea8dc4b6Seschrock * 8ea8dc4b6Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9ea8dc4b6Seschrock * or http://www.opensolaris.org/os/licensing. 10ea8dc4b6Seschrock * See the License for the specific language governing permissions 11ea8dc4b6Seschrock * and limitations under the License. 12ea8dc4b6Seschrock * 13ea8dc4b6Seschrock * When distributing Covered Code, include this CDDL HEADER in each 14ea8dc4b6Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15ea8dc4b6Seschrock * If applicable, add the following below this CDDL HEADER, with the 16ea8dc4b6Seschrock * fields enclosed by brackets "[]" replaced with your own identifying 17ea8dc4b6Seschrock * information: Portions Copyright [yyyy] [name of copyright owner] 18ea8dc4b6Seschrock * 19ea8dc4b6Seschrock * CDDL HEADER END 20ea8dc4b6Seschrock */ 21ea8dc4b6Seschrock /* 223f9d6ad7SLin Ling * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 23ea8dc4b6Seschrock */ 24*6df8993aSGarrett D'Amore /* 25*6df8993aSGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 26*6df8993aSGarrett D'Amore */ 27ea8dc4b6Seschrock 28ea8dc4b6Seschrock #include <fm/fmd_fmri.h> 29ea8dc4b6Seschrock #include <strings.h> 30ea8dc4b6Seschrock #include <libzfs.h> 31ea8dc4b6Seschrock 32ea8dc4b6Seschrock typedef struct cbdata { 33ea8dc4b6Seschrock uint64_t cb_guid; 34ea8dc4b6Seschrock zpool_handle_t *cb_pool; 35ea8dc4b6Seschrock } cbdata_t; 36ea8dc4b6Seschrock 3799653d4eSeschrock libzfs_handle_t *g_zfs; 3899653d4eSeschrock 39ea8dc4b6Seschrock static int 40ea8dc4b6Seschrock find_pool(zpool_handle_t *zhp, void *data) 41ea8dc4b6Seschrock { 42ea8dc4b6Seschrock cbdata_t *cbp = data; 43ea8dc4b6Seschrock 44990b4856Slling if (zpool_get_prop_int(zhp, ZPOOL_PROP_GUID, NULL) == cbp->cb_guid) { 45ea8dc4b6Seschrock cbp->cb_pool = zhp; 46ea8dc4b6Seschrock return (1); 47ea8dc4b6Seschrock } 48ea8dc4b6Seschrock 49ea8dc4b6Seschrock zpool_close(zhp); 50ea8dc4b6Seschrock 51ea8dc4b6Seschrock return (0); 52ea8dc4b6Seschrock } 53ea8dc4b6Seschrock 54ea8dc4b6Seschrock ssize_t 55ea8dc4b6Seschrock fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) 56ea8dc4b6Seschrock { 57ea8dc4b6Seschrock uint64_t pool_guid, vdev_guid; 58ea8dc4b6Seschrock cbdata_t cb; 59ea8dc4b6Seschrock ssize_t len; 60ea8dc4b6Seschrock const char *name; 61ea8dc4b6Seschrock char guidbuf[64]; 62ea8dc4b6Seschrock 63ea8dc4b6Seschrock (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 64ea8dc4b6Seschrock 65ea8dc4b6Seschrock /* 66ea8dc4b6Seschrock * Attempt to convert the pool guid to a name. 67ea8dc4b6Seschrock */ 68ea8dc4b6Seschrock cb.cb_guid = pool_guid; 69ea8dc4b6Seschrock cb.cb_pool = NULL; 70ea8dc4b6Seschrock 7199653d4eSeschrock if (zpool_iter(g_zfs, find_pool, &cb) == 1) { 72ea8dc4b6Seschrock name = zpool_get_name(cb.cb_pool); 73ea8dc4b6Seschrock } else { 74ea8dc4b6Seschrock (void) snprintf(guidbuf, sizeof (guidbuf), "%llx", pool_guid); 75ea8dc4b6Seschrock name = guidbuf; 76ea8dc4b6Seschrock } 77ea8dc4b6Seschrock 78ea8dc4b6Seschrock if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) == 0) 79ea8dc4b6Seschrock len = snprintf(buf, buflen, "%s://pool=%s/vdev=%llx", 80ea8dc4b6Seschrock FM_FMRI_SCHEME_ZFS, name, vdev_guid); 81ea8dc4b6Seschrock else 82ea8dc4b6Seschrock len = snprintf(buf, buflen, "%s://pool=%s", 83ea8dc4b6Seschrock FM_FMRI_SCHEME_ZFS, name); 84ea8dc4b6Seschrock 85ea8dc4b6Seschrock if (cb.cb_pool) 86ea8dc4b6Seschrock zpool_close(cb.cb_pool); 87ea8dc4b6Seschrock 88ea8dc4b6Seschrock return (len); 89ea8dc4b6Seschrock } 90ea8dc4b6Seschrock 91ea8dc4b6Seschrock static nvlist_t * 92ea8dc4b6Seschrock find_vdev_iter(nvlist_t *nv, uint64_t search) 93ea8dc4b6Seschrock { 94ea8dc4b6Seschrock uint_t c, children; 95ea8dc4b6Seschrock nvlist_t **child; 96ea8dc4b6Seschrock uint64_t guid; 97ea8dc4b6Seschrock nvlist_t *ret; 98ea8dc4b6Seschrock 99ea8dc4b6Seschrock (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid); 100ea8dc4b6Seschrock 101ea8dc4b6Seschrock if (search == guid) 102ea8dc4b6Seschrock return (nv); 103ea8dc4b6Seschrock 104ea8dc4b6Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 105*6df8993aSGarrett D'Amore &child, &children) == 0) { 106c5904d13Seschrock 107c5904d13Seschrock for (c = 0; c < children; c++) 108c5904d13Seschrock if ((ret = find_vdev_iter(child[c], search)) != 0) 109c5904d13Seschrock return (ret); 110*6df8993aSGarrett D'Amore } 111c5904d13Seschrock 112c5904d13Seschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 113*6df8993aSGarrett D'Amore &child, &children) == 0) { 114ea8dc4b6Seschrock 115ea8dc4b6Seschrock for (c = 0; c < children; c++) 116ea8dc4b6Seschrock if ((ret = find_vdev_iter(child[c], search)) != 0) 117ea8dc4b6Seschrock return (ret); 118*6df8993aSGarrett D'Amore } 119*6df8993aSGarrett D'Amore 120*6df8993aSGarrett D'Amore if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 121*6df8993aSGarrett D'Amore &child, &children) == 0) { 122*6df8993aSGarrett D'Amore 123*6df8993aSGarrett D'Amore for (c = 0; c < children; c++) 124*6df8993aSGarrett D'Amore if ((ret = find_vdev_iter(child[c], search)) != 0) 125*6df8993aSGarrett D'Amore return (ret); 126*6df8993aSGarrett D'Amore } 127ea8dc4b6Seschrock 128ea8dc4b6Seschrock return (NULL); 129ea8dc4b6Seschrock } 130ea8dc4b6Seschrock 131ea8dc4b6Seschrock static nvlist_t * 132ea8dc4b6Seschrock find_vdev(zpool_handle_t *zhp, uint64_t guid) 133ea8dc4b6Seschrock { 134c5904d13Seschrock nvlist_t *config, *nvroot; 135ea8dc4b6Seschrock 136ea8dc4b6Seschrock config = zpool_get_config(zhp, NULL); 137ea8dc4b6Seschrock 138ea8dc4b6Seschrock (void) nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot); 139ea8dc4b6Seschrock 140ea8dc4b6Seschrock return (find_vdev_iter(nvroot, guid)); 141ea8dc4b6Seschrock } 142ea8dc4b6Seschrock 143ea8dc4b6Seschrock int 144ea8dc4b6Seschrock fmd_fmri_present(nvlist_t *nvl) 145ea8dc4b6Seschrock { 146ea8dc4b6Seschrock uint64_t pool_guid, vdev_guid; 147ea8dc4b6Seschrock cbdata_t cb; 148ea8dc4b6Seschrock int ret; 149ea8dc4b6Seschrock 150ea8dc4b6Seschrock (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 151ea8dc4b6Seschrock 152ea8dc4b6Seschrock cb.cb_guid = pool_guid; 153ea8dc4b6Seschrock cb.cb_pool = NULL; 154ea8dc4b6Seschrock 15599653d4eSeschrock if (zpool_iter(g_zfs, find_pool, &cb) != 1) 156ea8dc4b6Seschrock return (0); 157ea8dc4b6Seschrock 158ea8dc4b6Seschrock if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { 159ea8dc4b6Seschrock zpool_close(cb.cb_pool); 160ea8dc4b6Seschrock return (1); 161ea8dc4b6Seschrock } 162ea8dc4b6Seschrock 163ea8dc4b6Seschrock ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL); 164ea8dc4b6Seschrock 165ea8dc4b6Seschrock zpool_close(cb.cb_pool); 166ea8dc4b6Seschrock 167ea8dc4b6Seschrock return (ret); 168ea8dc4b6Seschrock } 169ea8dc4b6Seschrock 170ea8dc4b6Seschrock int 17146b28a98SStephen Hanson fmd_fmri_replaced(nvlist_t *nvl) 17246b28a98SStephen Hanson { 17346b28a98SStephen Hanson uint64_t pool_guid, vdev_guid; 17446b28a98SStephen Hanson cbdata_t cb; 17546b28a98SStephen Hanson int ret; 17646b28a98SStephen Hanson 17746b28a98SStephen Hanson (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 17846b28a98SStephen Hanson 17946b28a98SStephen Hanson cb.cb_guid = pool_guid; 18046b28a98SStephen Hanson cb.cb_pool = NULL; 18146b28a98SStephen Hanson 18246b28a98SStephen Hanson if (zpool_iter(g_zfs, find_pool, &cb) != 1) 18346b28a98SStephen Hanson return (FMD_OBJ_STATE_NOT_PRESENT); 18446b28a98SStephen Hanson 18546b28a98SStephen Hanson if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { 18646b28a98SStephen Hanson zpool_close(cb.cb_pool); 18746b28a98SStephen Hanson return (FMD_OBJ_STATE_STILL_PRESENT); 18846b28a98SStephen Hanson } 18946b28a98SStephen Hanson 19046b28a98SStephen Hanson ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL) ? 19146b28a98SStephen Hanson FMD_OBJ_STATE_STILL_PRESENT : FMD_OBJ_STATE_NOT_PRESENT; 19246b28a98SStephen Hanson 19346b28a98SStephen Hanson zpool_close(cb.cb_pool); 19446b28a98SStephen Hanson 19546b28a98SStephen Hanson return (ret); 19646b28a98SStephen Hanson } 19746b28a98SStephen Hanson 19846b28a98SStephen Hanson int 199ea8dc4b6Seschrock fmd_fmri_unusable(nvlist_t *nvl) 200ea8dc4b6Seschrock { 201ea8dc4b6Seschrock uint64_t pool_guid, vdev_guid; 202ea8dc4b6Seschrock cbdata_t cb; 203ea8dc4b6Seschrock nvlist_t *vd; 204ea8dc4b6Seschrock int ret; 205ea8dc4b6Seschrock 206ea8dc4b6Seschrock (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); 207ea8dc4b6Seschrock 208ea8dc4b6Seschrock cb.cb_guid = pool_guid; 209ea8dc4b6Seschrock cb.cb_pool = NULL; 210ea8dc4b6Seschrock 21199653d4eSeschrock if (zpool_iter(g_zfs, find_pool, &cb) != 1) 212ea8dc4b6Seschrock return (1); 213ea8dc4b6Seschrock 214ea8dc4b6Seschrock if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { 215ea8dc4b6Seschrock ret = (zpool_get_state(cb.cb_pool) == POOL_STATE_UNAVAIL); 216ea8dc4b6Seschrock zpool_close(cb.cb_pool); 217ea8dc4b6Seschrock return (ret); 218ea8dc4b6Seschrock } 219ea8dc4b6Seschrock 220ea8dc4b6Seschrock vd = find_vdev(cb.cb_pool, vdev_guid); 221ea8dc4b6Seschrock if (vd == NULL) { 222ea8dc4b6Seschrock ret = 1; 223ea8dc4b6Seschrock } else { 224ea8dc4b6Seschrock vdev_stat_t *vs; 225ea8dc4b6Seschrock uint_t c; 226ea8dc4b6Seschrock 2273f9d6ad7SLin Ling (void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_VDEV_STATS, 228ea8dc4b6Seschrock (uint64_t **)&vs, &c); 229ea8dc4b6Seschrock 230ea8dc4b6Seschrock ret = (vs->vs_state < VDEV_STATE_DEGRADED); 231ea8dc4b6Seschrock } 232ea8dc4b6Seschrock 233ea8dc4b6Seschrock zpool_close(cb.cb_pool); 234ea8dc4b6Seschrock 235ea8dc4b6Seschrock return (ret); 236ea8dc4b6Seschrock } 23799653d4eSeschrock 23899653d4eSeschrock int 23999653d4eSeschrock fmd_fmri_init(void) 24099653d4eSeschrock { 24199653d4eSeschrock g_zfs = libzfs_init(); 24299653d4eSeschrock 24399653d4eSeschrock if (g_zfs == NULL) 24499653d4eSeschrock return (-1); 24599653d4eSeschrock else 24699653d4eSeschrock return (0); 24799653d4eSeschrock } 24899653d4eSeschrock 24999653d4eSeschrock void 25099653d4eSeschrock fmd_fmri_fini(void) 25199653d4eSeschrock { 25299653d4eSeschrock if (g_zfs) 25399653d4eSeschrock libzfs_fini(g_zfs); 25499653d4eSeschrock } 255