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