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 /* 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 #include <fm/libtopo.h> 26 #include <sys/fm/util.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <sys/errno.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <pthread.h> 33 34 #include <libxml/xpathInternals.h> 35 36 #include "fabric-xlate.h" 37 38 #define XMLTOPOFILE "/var/run/fab-xlate-topo.xml" 39 40 fmd_xprt_t *fab_fmd_xprt; /* FMD transport layer handle */ 41 char fab_buf[FM_MAX_CLASS]; 42 43 /* Static FM Topo XML Format and XML XPath Context */ 44 static xmlDocPtr fab_doc = NULL; 45 xmlXPathContextPtr fab_xpathCtx = NULL; 46 static int fab_valid_topo = 0; 47 static pthread_mutex_t fab_lock = PTHREAD_MUTEX_INITIALIZER; 48 49 static void 50 fab_update_topo(fmd_hdl_t *hdl) 51 { 52 topo_hdl_t *thp = NULL; 53 FILE *fp = NULL; 54 int err = 0; 55 int fd = -1; 56 57 /* Open the temporary file with proper ownership */ 58 while (fd == -1) { 59 if ((unlink(XMLTOPOFILE) == -1) && (errno != ENOENT)) { 60 fmd_hdl_debug(hdl, "Failed to remove XML topo file\n"); 61 return; 62 } 63 fd = open(XMLTOPOFILE, O_RDWR | O_CREAT | O_EXCL, 0600); 64 if ((fd == -1) && (errno != EEXIST)) { 65 fmd_hdl_debug(hdl, "Failed to create XML topo file\n"); 66 return; 67 } 68 } 69 70 /* Associate a stream with the temporary file */ 71 if ((fp = fdopen(fd, "w")) == NULL) { 72 fmd_hdl_debug(hdl, "Failed to open XML topo file\n"); 73 goto cleanup; 74 } 75 76 /* Hold topology */ 77 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL) { 78 fmd_hdl_debug(hdl, "Failed to hold topo\n"); 79 goto cleanup; 80 } 81 82 /* Print topology to XML file */ 83 if (topo_xml_print(thp, fp, FM_FMRI_SCHEME_HC, &err) < 0) { 84 fmd_hdl_debug(hdl, "Failed to get XML topo\n"); 85 fmd_hdl_topo_rele(hdl, thp); 86 goto cleanup; 87 } 88 89 /* Release topology */ 90 fmd_hdl_topo_rele(hdl, thp); 91 92 /* Reload topology from XML file */ 93 if (fab_xpathCtx) 94 xmlXPathFreeContext(fab_xpathCtx); 95 if (fab_doc) 96 xmlFreeDoc(fab_doc); 97 fab_doc = xmlParseFile(XMLTOPOFILE); 98 fab_xpathCtx = xmlXPathNewContext(fab_doc); 99 fab_set_fake_rp(hdl); 100 fab_valid_topo = 1; 101 102 cleanup: 103 if (fp != NULL) 104 (void) fclose(fp); 105 else if (fd != -1) 106 (void) close(fd); 107 (void) unlink(XMLTOPOFILE); 108 } 109 110 /*ARGSUSED*/ 111 static void 112 fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) 113 { 114 nvlist_t *new_nvl; 115 116 (void) pthread_mutex_lock(&fab_lock); 117 if (!fab_valid_topo) 118 fab_update_topo(hdl); 119 (void) pthread_mutex_unlock(&fab_lock); 120 121 if (nvlist_dup(nvl, &new_nvl, NV_UNIQUE_NAME) != 0) { 122 fmd_hdl_error(hdl, "failed to duplicate event"); 123 return; 124 } 125 126 if (fmd_nvl_class_match(hdl, new_nvl, "ereport.io.pci.fabric")) { 127 fab_xlate_fabric_erpts(hdl, new_nvl, class); 128 } else { 129 fab_pr(hdl, ep, new_nvl); 130 if (fmd_nvl_class_match(hdl, new_nvl, 131 "ereport.io.pciex.rc.epkt")) { 132 fab_xlate_epkt_erpts(hdl, new_nvl, class); 133 } else { 134 fab_xlate_fire_erpts(hdl, new_nvl, class); 135 } 136 } 137 138 nvlist_free(new_nvl); 139 } 140 141 /* ARGSUSED */ 142 static void 143 fab_topo(fmd_hdl_t *hdl, topo_hdl_t *topo) 144 { 145 (void) pthread_mutex_lock(&fab_lock); 146 fab_valid_topo = 0; 147 (void) pthread_mutex_unlock(&fab_lock); 148 } 149 150 static const fmd_hdl_ops_t fmd_ops = { 151 fab_recv, /* fmdo_recv */ 152 NULL, /* fmdo_timeout */ 153 NULL, /* fmdo_close */ 154 NULL, /* fmdo_stats */ 155 NULL, /* fmdo_gc */ 156 NULL, /* fmdo_send */ 157 fab_topo, /* fmdo_topo */ 158 }; 159 160 static const fmd_hdl_info_t fmd_info = { 161 "Fabric Ereport Translater", "1.0", &fmd_ops, NULL 162 }; 163 164 void 165 _fmd_init(fmd_hdl_t *hdl) 166 { 167 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) 168 return; 169 170 /* Init libxml */ 171 xmlInitParser(); 172 173 fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL); 174 fmd_hdl_debug(hdl, "Fabric Translater Started\n"); 175 176 fab_setup_master_table(); 177 } 178 179 void 180 _fmd_fini(fmd_hdl_t *hdl) 181 { 182 /* Fini xpath */ 183 if (fab_xpathCtx) 184 xmlXPathFreeContext(fab_xpathCtx); 185 /* Free xml document */ 186 if (fab_doc) 187 xmlFreeDoc(fab_doc); 188 /* Fini libxml */ 189 xmlCleanupParser(); 190 191 fmd_xprt_close(hdl, fab_fmd_xprt); 192 } 193