1724365f7Ssethg /*
2724365f7Ssethg  * CDDL HEADER START
3724365f7Ssethg  *
4724365f7Ssethg  * The contents of this file are subject to the terms of the
5724365f7Ssethg  * Common Development and Distribution License (the "License").
6724365f7Ssethg  * You may not use this file except in compliance with the License.
7724365f7Ssethg  *
8724365f7Ssethg  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9724365f7Ssethg  * or http://www.opensolaris.org/os/licensing.
10724365f7Ssethg  * See the License for the specific language governing permissions
11724365f7Ssethg  * and limitations under the License.
12724365f7Ssethg  *
13724365f7Ssethg  * When distributing Covered Code, include this CDDL HEADER in each
14724365f7Ssethg  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15724365f7Ssethg  * If applicable, add the following below this CDDL HEADER, with the
16724365f7Ssethg  * fields enclosed by brackets "[]" replaced with your own identifying
17724365f7Ssethg  * information: Portions Copyright [yyyy] [name of copyright owner]
18724365f7Ssethg  *
19724365f7Ssethg  * CDDL HEADER END
20724365f7Ssethg  */
21724365f7Ssethg 
22724365f7Ssethg /*
2324db4641Seschrock  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24724365f7Ssethg  * Use is subject to license terms.
25724365f7Ssethg  */
26724365f7Ssethg 
27724365f7Ssethg #include <sys/types.h>
28724365f7Ssethg #include <inttypes.h>
29724365f7Ssethg #include <stdio.h>
30724365f7Ssethg #include <stdarg.h>
31724365f7Ssethg #include <ctype.h>
32724365f7Ssethg #include <errno.h>
33724365f7Ssethg #include <string.h>
34724365f7Ssethg #include <stdlib.h>
35724365f7Ssethg #include <pthread.h>
36724365f7Ssethg #include <smbios.h>
37724365f7Ssethg 
38724365f7Ssethg #include <fm/fmd_api.h>
39724365f7Ssethg 
40724365f7Ssethg #include "util.h"
41*184cd04cScth #include "disk_monitor.h"
42724365f7Ssethg 
43724365f7Ssethg extern log_class_t g_verbose;
44724365f7Ssethg 
45724365f7Ssethg static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
46724365f7Ssethg 
47724365f7Ssethg static void
verror(const char * fmt,va_list ap)48724365f7Ssethg verror(const char *fmt, va_list ap)
49724365f7Ssethg {
50724365f7Ssethg 	int error = errno;
51724365f7Ssethg 
527a0b67e3Ssethg 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
53724365f7Ssethg 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
54724365f7Ssethg 
55724365f7Ssethg 	if (fmt[strlen(fmt) - 1] != '\n')
56724365f7Ssethg 		fmd_hdl_debug(g_fm_hdl, ": %s\n", strerror(error));
57724365f7Ssethg 
587a0b67e3Ssethg 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
59724365f7Ssethg }
60724365f7Ssethg 
61724365f7Ssethg static void
vwarn_e(const char * fmt,va_list ap)62724365f7Ssethg vwarn_e(const char *fmt, va_list ap)
63724365f7Ssethg {
64724365f7Ssethg 	int error = errno;
65724365f7Ssethg 
667a0b67e3Ssethg 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
67724365f7Ssethg 	fmd_hdl_debug(g_fm_hdl, "WARNING: ");
68724365f7Ssethg 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
69724365f7Ssethg 
70724365f7Ssethg 	if (fmt[strlen(fmt) - 1] != '\n')
71724365f7Ssethg 		fmd_hdl_debug(g_fm_hdl, ": %s\n", strerror(error));
72724365f7Ssethg 
737a0b67e3Ssethg 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
74724365f7Ssethg }
75724365f7Ssethg 
76724365f7Ssethg static void
vwarn(const char * fmt,va_list ap)77724365f7Ssethg vwarn(const char *fmt, va_list ap)
78724365f7Ssethg {
797a0b67e3Ssethg 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
80724365f7Ssethg 	fmd_hdl_debug(g_fm_hdl, "WARNING: ");
81724365f7Ssethg 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
827a0b67e3Ssethg 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
83724365f7Ssethg }
84724365f7Ssethg 
85724365f7Ssethg void
vcont(log_class_t cl,const char * fmt,va_list ap)86724365f7Ssethg vcont(log_class_t cl, const char *fmt, va_list ap)
87724365f7Ssethg {
88724365f7Ssethg 	int error = errno;
89724365f7Ssethg 
90724365f7Ssethg 	if ((g_verbose & cl) != cl)
91724365f7Ssethg 		return;
92724365f7Ssethg 
937a0b67e3Ssethg 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
94724365f7Ssethg 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
95724365f7Ssethg 
96724365f7Ssethg 	if (fmt[strlen(fmt) - 1] != '\n')
97724365f7Ssethg 		fmd_hdl_debug(g_fm_hdl, ": %s\n", strerror(error));
98724365f7Ssethg 
997a0b67e3Ssethg 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
100724365f7Ssethg }
101724365f7Ssethg 
102724365f7Ssethg void
log_msg(log_class_t cl,const char * fmt,...)103724365f7Ssethg log_msg(log_class_t cl, const char *fmt, ...)
104724365f7Ssethg {
105724365f7Ssethg 	va_list ap;
106724365f7Ssethg 
107724365f7Ssethg 	if ((g_verbose & cl) != cl)
108724365f7Ssethg 		return;
109724365f7Ssethg 
1107a0b67e3Ssethg 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
111724365f7Ssethg 	va_start(ap, fmt);
112724365f7Ssethg 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
113724365f7Ssethg 	va_end(ap);
1147a0b67e3Ssethg 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
115724365f7Ssethg }
116724365f7Ssethg 
117724365f7Ssethg /*PRINTFLIKE1*/
118724365f7Ssethg void
log_err(const char * fmt,...)119724365f7Ssethg log_err(const char *fmt, ...)
120724365f7Ssethg {
121724365f7Ssethg 	va_list ap;
122724365f7Ssethg 
123724365f7Ssethg 	if ((g_verbose & MM_ERR) != MM_ERR)
124724365f7Ssethg 		return;
125724365f7Ssethg 
126724365f7Ssethg 	va_start(ap, fmt);
127724365f7Ssethg 	verror(fmt, ap);
128724365f7Ssethg 	va_end(ap);
129724365f7Ssethg }
130724365f7Ssethg 
131724365f7Ssethg /*PRINTFLIKE1*/
132724365f7Ssethg void
log_warn(const char * fmt,...)133724365f7Ssethg log_warn(const char *fmt, ...)
134724365f7Ssethg {
135724365f7Ssethg 	va_list ap;
136724365f7Ssethg 
137724365f7Ssethg 	if ((g_verbose & MM_WARN) != MM_WARN)
138724365f7Ssethg 		return;
139724365f7Ssethg 
140724365f7Ssethg 	va_start(ap, fmt);
141724365f7Ssethg 	vwarn(fmt, ap);
142724365f7Ssethg 	va_end(ap);
143724365f7Ssethg }
144724365f7Ssethg 
145724365f7Ssethg /*PRINTFLIKE1*/
146724365f7Ssethg void
log_warn_e(const char * fmt,...)147724365f7Ssethg log_warn_e(const char *fmt, ...)
148724365f7Ssethg {
149724365f7Ssethg 	va_list ap;
150724365f7Ssethg 
151724365f7Ssethg 	if ((g_verbose & MM_WARN) != MM_WARN)
152724365f7Ssethg 		return;
153724365f7Ssethg 
154724365f7Ssethg 	va_start(ap, fmt);
155724365f7Ssethg 	vwarn_e(fmt, ap);
156724365f7Ssethg 	va_end(ap);
157724365f7Ssethg }
158724365f7Ssethg 
159724365f7Ssethg void
dfree(void * p,size_t sz)160724365f7Ssethg dfree(void *p, size_t sz)
161724365f7Ssethg {
162724365f7Ssethg 	fmd_hdl_free(g_fm_hdl, p, sz);
163724365f7Ssethg }
164724365f7Ssethg 
165724365f7Ssethg void
dstrfree(char * s)166724365f7Ssethg dstrfree(char *s)
167724365f7Ssethg {
168724365f7Ssethg 	fmd_hdl_strfree(g_fm_hdl, s);
169724365f7Ssethg }
170724365f7Ssethg 
171724365f7Ssethg void *
dmalloc(size_t sz)172724365f7Ssethg dmalloc(size_t sz)
173724365f7Ssethg {
174724365f7Ssethg 	return (fmd_hdl_alloc(g_fm_hdl, sz, FMD_SLEEP));
175724365f7Ssethg }
176724365f7Ssethg 
177724365f7Ssethg void *
dzmalloc(size_t sz)178724365f7Ssethg dzmalloc(size_t sz)
179724365f7Ssethg {
180724365f7Ssethg 	return (fmd_hdl_zalloc(g_fm_hdl, sz, FMD_SLEEP));
181724365f7Ssethg }
182724365f7Ssethg 
183724365f7Ssethg 
184724365f7Ssethg char *
dstrdup(const char * s)185724365f7Ssethg dstrdup(const char *s)
186724365f7Ssethg {
187724365f7Ssethg 	return (fmd_hdl_strdup(g_fm_hdl, s, FMD_SLEEP));
188724365f7Ssethg }
189724365f7Ssethg 
190724365f7Ssethg void
queue_add(qu_t * qp,void * data)191724365f7Ssethg queue_add(qu_t *qp, void *data)
192724365f7Ssethg {
193724365f7Ssethg 	struct q_node *qnp =
194724365f7Ssethg 	    (struct q_node *)qp->nalloc(sizeof (struct q_node));
195724365f7Ssethg 	struct q_node *nodep;
196724365f7Ssethg 
197724365f7Ssethg 	qnp->data = data;
198724365f7Ssethg 	qnp->next = NULL;
1997a0b67e3Ssethg 	dm_assert(pthread_mutex_lock(&qp->mutex) == 0);
200724365f7Ssethg 
201724365f7Ssethg 	if (qp->nodep == NULL)
202724365f7Ssethg 		qp->nodep = qnp;
203724365f7Ssethg 	else {
204724365f7Ssethg 		nodep = qp->nodep;
205724365f7Ssethg 
206724365f7Ssethg 		while (nodep->next != NULL)
207724365f7Ssethg 			nodep = nodep->next;
208724365f7Ssethg 
209724365f7Ssethg 		nodep->next = qnp;
210724365f7Ssethg 	}
211724365f7Ssethg 
212724365f7Ssethg 	/* If the queue was empty, we need to wake people up */
213724365f7Ssethg 	if (qp->boe && qp->nodep == qnp)
2147a0b67e3Ssethg 		dm_assert(pthread_cond_broadcast(&qp->cvar) == 0);
2157a0b67e3Ssethg 	dm_assert(pthread_mutex_unlock(&qp->mutex) == 0);
216724365f7Ssethg }
217724365f7Ssethg 
218724365f7Ssethg void *
queue_remove(qu_t * qp)219724365f7Ssethg queue_remove(qu_t *qp)
220724365f7Ssethg {
221724365f7Ssethg 	void *rv = NULL;
222724365f7Ssethg 	struct q_node *nextnode;
223724365f7Ssethg 
2247a0b67e3Ssethg 	dm_assert(pthread_mutex_lock(&qp->mutex) == 0);
225724365f7Ssethg 
226724365f7Ssethg 	/* Wait while the queue is empty */
227724365f7Ssethg 	while (qp->boe && qp->nodep == NULL) {
228724365f7Ssethg 		(void) pthread_cond_wait(&qp->cvar, &qp->mutex);
229724365f7Ssethg 	}
230724365f7Ssethg 
231724365f7Ssethg 	/*
232724365f7Ssethg 	 * If Block-On-Empty is false, the queue may be empty
233724365f7Ssethg 	 */
234724365f7Ssethg 	if (qp->nodep != NULL) {
235724365f7Ssethg 		rv = qp->nodep->data;
236724365f7Ssethg 		nextnode = qp->nodep->next;
237724365f7Ssethg 		qp->nfree(qp->nodep, sizeof (struct q_node));
238724365f7Ssethg 		qp->nodep = nextnode;
239724365f7Ssethg 	}
240724365f7Ssethg 
2417a0b67e3Ssethg 	dm_assert(pthread_mutex_unlock(&qp->mutex) == 0);
242724365f7Ssethg 	return (rv);
243724365f7Ssethg }
244724365f7Ssethg 
245724365f7Ssethg qu_t *
new_queue(boolean_t block_on_empty,void * (* nodealloc)(size_t),void (* nodefree)(void *,size_t),void (* data_deallocator)(void *))246724365f7Ssethg new_queue(boolean_t block_on_empty, void *(*nodealloc)(size_t),
247724365f7Ssethg     void (*nodefree)(void *, size_t), void (*data_deallocator)(void *))
248724365f7Ssethg {
249724365f7Ssethg 	qu_t *newqp = (qu_t *)dmalloc(sizeof (qu_t));
250724365f7Ssethg 
251724365f7Ssethg 	newqp->boe = block_on_empty;
252724365f7Ssethg 	newqp->nalloc = nodealloc;
253724365f7Ssethg 	newqp->nfree = nodefree;
254724365f7Ssethg 	newqp->data_dealloc = data_deallocator;
2557a0b67e3Ssethg 	dm_assert(pthread_mutex_init(&newqp->mutex, NULL) == 0);
2567a0b67e3Ssethg 	dm_assert(pthread_cond_init(&newqp->cvar, NULL) == 0);
257724365f7Ssethg 	newqp->nodep = NULL;
258724365f7Ssethg 
259724365f7Ssethg 	return (newqp);
260724365f7Ssethg }
261724365f7Ssethg 
262724365f7Ssethg void
queue_free(qu_t ** qpp)263724365f7Ssethg queue_free(qu_t **qpp)
264724365f7Ssethg {
265724365f7Ssethg 	qu_t *qp = *qpp;
266724365f7Ssethg 	void *item;
267724365f7Ssethg 
2687a0b67e3Ssethg 	dm_assert(pthread_mutex_destroy(&qp->mutex) == 0);
2697a0b67e3Ssethg 	dm_assert(pthread_cond_destroy(&qp->cvar) == 0);
270724365f7Ssethg 
271724365f7Ssethg 	qp->boe = B_FALSE;
272724365f7Ssethg 
273724365f7Ssethg 	while ((item = queue_remove(qp)) != NULL) {
274724365f7Ssethg 		qp->data_dealloc(item);
275724365f7Ssethg 	}
276724365f7Ssethg 
2777a0b67e3Ssethg 	dm_assert(qp->nodep == NULL);
278724365f7Ssethg 
279724365f7Ssethg 	dfree(qp, sizeof (qu_t));
280724365f7Ssethg 	*qpp = NULL;
281724365f7Ssethg }
2827a0b67e3Ssethg 
2837a0b67e3Ssethg int
_dm_assert(const char * assertion,const char * file,int line,const char * func)2847a0b67e3Ssethg _dm_assert(const char *assertion, const char *file, int line, const char *func)
2857a0b67e3Ssethg {
2867a0b67e3Ssethg 	/*
2877a0b67e3Ssethg 	 * No newline is appended to the assertion message so that
2887a0b67e3Ssethg 	 * errno can be translated for us by fmd_hdl_abort().
2897a0b67e3Ssethg 	 */
2907a0b67e3Ssethg 	if (func)
2917a0b67e3Ssethg 		fmd_hdl_abort(g_fm_hdl, "Assertion failed: "
2927a0b67e3Ssethg 		    "%s, file: %s, line: %d, function: %s", assertion, file,
2937a0b67e3Ssethg 		    line, func);
2947a0b67e3Ssethg 	else
2957a0b67e3Ssethg 		fmd_hdl_abort(g_fm_hdl, "Assertion failed: "
2967a0b67e3Ssethg 		    "%s, file: %s, line: %d", assertion, file, line);
2977a0b67e3Ssethg 	/*NOTREACHED*/
2987a0b67e3Ssethg 	return (0);
2997a0b67e3Ssethg }
300