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