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 fflush(fp); 91 92 /* Release topology */ 93 fmd_hdl_topo_rele(hdl, thp); 94 95 /* Reload topology from XML file */ 96 if (fab_xpathCtx) 97 xmlXPathFreeContext(fab_xpathCtx); 98 if (fab_doc) 99 xmlFreeDoc(fab_doc); 100 fab_doc = xmlParseFile(XMLTOPOFILE); 101 fab_xpathCtx = xmlXPathNewContext(fab_doc); 102 fab_set_fake_rp(hdl); 103 fab_valid_topo = 1; 104 105 cleanup: 106 if (fp != NULL) 107 (void) fclose(fp); 108 else if (fd != -1) 109 (void) close(fd); 110 (void) unlink(XMLTOPOFILE); 111 } 112 113 /*ARGSUSED*/ 114 static void 115 fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) 116 { 117 nvlist_t *new_nvl; 118 119 (void) pthread_mutex_lock(&fab_lock); 120 if (!fab_valid_topo) 121 fab_update_topo(hdl); 122 (void) pthread_mutex_unlock(&fab_lock); 123 124 if (nvlist_dup(nvl, &new_nvl, NV_UNIQUE_NAME) != 0) { 125 fmd_hdl_error(hdl, "failed to duplicate event"); 126 return; 127 } 128 129 if (fmd_nvl_class_match(hdl, new_nvl, "ereport.io.pci.fabric")) { 130 fab_xlate_fabric_erpts(hdl, new_nvl, class); 131 } else { 132 fab_pr(hdl, ep, new_nvl); 133 if (fmd_nvl_class_match(hdl, new_nvl, 134 "ereport.io.pciex.rc.epkt")) { 135 fab_xlate_epkt_erpts(hdl, new_nvl, class); 136 } else { 137 fab_xlate_fire_erpts(hdl, new_nvl, class); 138 } 139 } 140 141 nvlist_free(new_nvl); 142 } 143 144 /* ARGSUSED */ 145 static void 146 fab_topo(fmd_hdl_t *hdl, topo_hdl_t *topo) 147 { 148 (void) pthread_mutex_lock(&fab_lock); 149 fab_valid_topo = 0; 150 (void) pthread_mutex_unlock(&fab_lock); 151 } 152 153 static const fmd_hdl_ops_t fmd_ops = { 154 fab_recv, /* fmdo_recv */ 155 NULL, /* fmdo_timeout */ 156 NULL, /* fmdo_close */ 157 NULL, /* fmdo_stats */ 158 NULL, /* fmdo_gc */ 159 NULL, /* fmdo_send */ 160 fab_topo, /* fmdo_topo */ 161 }; 162 163 static const fmd_hdl_info_t fmd_info = { 164 "Fabric Ereport Translater", "1.0", &fmd_ops, NULL 165 }; 166 167 void 168 _fmd_init(fmd_hdl_t *hdl) 169 { 170 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) 171 return; 172 173 /* Init libxml */ 174 xmlInitParser(); 175 176 fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL); 177 fmd_hdl_debug(hdl, "Fabric Translater Started\n"); 178 179 fab_setup_master_table(); 180 } 181 182 void 183 _fmd_fini(fmd_hdl_t *hdl) 184 { 185 /* Fini xpath */ 186 if (fab_xpathCtx) 187 xmlXPathFreeContext(fab_xpathCtx); 188 /* Free xml document */ 189 if (fab_doc) 190 xmlFreeDoc(fab_doc); 191 /* Fini libxml */ 192 xmlCleanupParser(); 193 194 fmd_xprt_close(hdl, fab_fmd_xprt); 195 } 196