xref: /illumos-gate/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c (revision 71487f875a8d459180cea558ee6dc176c579bfe8)
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
fab_update_topo(fmd_hdl_t * hdl)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
fab_recv(fmd_hdl_t * hdl,fmd_event_t * ep,nvlist_t * nvl,const char * class)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
fab_topo(fmd_hdl_t * hdl,topo_hdl_t * topo)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
_fmd_init(fmd_hdl_t * hdl)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
_fmd_fini(fmd_hdl_t * hdl)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