fabric-xlate.c revision 12552:cffa6779b402
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
40fmd_xprt_t *fab_fmd_xprt;	/* FMD transport layer handle */
41char fab_buf[FM_MAX_CLASS];
42
43/* Static FM Topo XML Format and XML XPath Context  */
44static xmlDocPtr	fab_doc = NULL;
45xmlXPathContextPtr	fab_xpathCtx = NULL;
46static int		fab_valid_topo = 0;
47static pthread_mutex_t	fab_lock = PTHREAD_MUTEX_INITIALIZER;
48
49static void
50fab_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
102cleanup:
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*/
111static void
112fab_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 */
142static void
143fab_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
150static 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
160static const fmd_hdl_info_t fmd_info = {
161	"Fabric Ereport Translater", "1.0", &fmd_ops, NULL
162};
163
164void
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
179void
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