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 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <inttypes.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <pthread.h>
38 #include <smbios.h>
39 
40 #include <fm/fmd_api.h>
41 
42 #include "util.h"
43 #include "disk_monitor.h"
44 
45 extern log_class_t g_verbose;
46 
47 static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
48 
49 static void
verror(const char * fmt,va_list ap)50 verror(const char *fmt, va_list ap)
51 {
52 	int error = errno;
53 
54 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
55 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
56 
57 	if (fmt[strlen(fmt) - 1] != '\n')
58 		fmd_hdl_debug(g_fm_hdl, ": %s\n", strerror(error));
59 
60 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
61 }
62 
63 static void
vwarn_e(const char * fmt,va_list ap)64 vwarn_e(const char *fmt, va_list ap)
65 {
66 	int error = errno;
67 
68 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
69 	fmd_hdl_debug(g_fm_hdl, "WARNING: ");
70 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
71 
72 	if (fmt[strlen(fmt) - 1] != '\n')
73 		fmd_hdl_debug(g_fm_hdl, ": %s\n", strerror(error));
74 
75 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
76 }
77 
78 static void
vwarn(const char * fmt,va_list ap)79 vwarn(const char *fmt, va_list ap)
80 {
81 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
82 	fmd_hdl_debug(g_fm_hdl, "WARNING: ");
83 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
84 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
85 }
86 
87 void
vcont(log_class_t cl,const char * fmt,va_list ap)88 vcont(log_class_t cl, const char *fmt, va_list ap)
89 {
90 	int error = errno;
91 
92 	if ((g_verbose & cl) != cl)
93 		return;
94 
95 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
96 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
97 
98 	if (fmt[strlen(fmt) - 1] != '\n')
99 		fmd_hdl_debug(g_fm_hdl, ": %s\n", strerror(error));
100 
101 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
102 }
103 
104 void
log_msg(log_class_t cl,const char * fmt,...)105 log_msg(log_class_t cl, const char *fmt, ...)
106 {
107 	va_list ap;
108 
109 	if ((g_verbose & cl) != cl)
110 		return;
111 
112 	dm_assert(pthread_mutex_lock(&log_mutex) == 0);
113 	va_start(ap, fmt);
114 	fmd_hdl_vdebug(g_fm_hdl, fmt, ap);
115 	va_end(ap);
116 	dm_assert(pthread_mutex_unlock(&log_mutex) == 0);
117 }
118 
119 /*PRINTFLIKE1*/
120 void
log_err(const char * fmt,...)121 log_err(const char *fmt, ...)
122 {
123 	va_list ap;
124 
125 	if ((g_verbose & MM_ERR) != MM_ERR)
126 		return;
127 
128 	va_start(ap, fmt);
129 	verror(fmt, ap);
130 	va_end(ap);
131 }
132 
133 /*PRINTFLIKE1*/
134 void
log_warn(const char * fmt,...)135 log_warn(const char *fmt, ...)
136 {
137 	va_list ap;
138 
139 	if ((g_verbose & MM_WARN) != MM_WARN)
140 		return;
141 
142 	va_start(ap, fmt);
143 	vwarn(fmt, ap);
144 	va_end(ap);
145 }
146 
147 /*PRINTFLIKE1*/
148 void
log_warn_e(const char * fmt,...)149 log_warn_e(const char *fmt, ...)
150 {
151 	va_list ap;
152 
153 	if ((g_verbose & MM_WARN) != MM_WARN)
154 		return;
155 
156 	va_start(ap, fmt);
157 	vwarn_e(fmt, ap);
158 	va_end(ap);
159 }
160 
161 void
dfree(void * p,size_t sz)162 dfree(void *p, size_t sz)
163 {
164 	fmd_hdl_free(g_fm_hdl, p, sz);
165 }
166 
167 void
dstrfree(char * s)168 dstrfree(char *s)
169 {
170 	fmd_hdl_strfree(g_fm_hdl, s);
171 }
172 
173 void *
dmalloc(size_t sz)174 dmalloc(size_t sz)
175 {
176 	return (fmd_hdl_alloc(g_fm_hdl, sz, FMD_SLEEP));
177 }
178 
179 void *
dzmalloc(size_t sz)180 dzmalloc(size_t sz)
181 {
182 	return (fmd_hdl_zalloc(g_fm_hdl, sz, FMD_SLEEP));
183 }
184 
185 
186 char *
dstrdup(const char * s)187 dstrdup(const char *s)
188 {
189 	return (fmd_hdl_strdup(g_fm_hdl, s, FMD_SLEEP));
190 }
191 
192 void
queue_add(qu_t * qp,void * data)193 queue_add(qu_t *qp, void *data)
194 {
195 	struct q_node *qnp =
196 	    (struct q_node *)qp->nalloc(sizeof (struct q_node));
197 	struct q_node *nodep;
198 
199 	qnp->data = data;
200 	qnp->next = NULL;
201 	dm_assert(pthread_mutex_lock(&qp->mutex) == 0);
202 
203 	if (qp->nodep == NULL)
204 		qp->nodep = qnp;
205 	else {
206 		nodep = qp->nodep;
207 
208 		while (nodep->next != NULL)
209 			nodep = nodep->next;
210 
211 		nodep->next = qnp;
212 	}
213 
214 	/* If the queue was empty, we need to wake people up */
215 	if (qp->boe && qp->nodep == qnp)
216 		dm_assert(pthread_cond_broadcast(&qp->cvar) == 0);
217 	dm_assert(pthread_mutex_unlock(&qp->mutex) == 0);
218 }
219 
220 void *
queue_remove(qu_t * qp)221 queue_remove(qu_t *qp)
222 {
223 	void *rv = NULL;
224 	struct q_node *nextnode;
225 
226 	dm_assert(pthread_mutex_lock(&qp->mutex) == 0);
227 
228 	/* Wait while the queue is empty */
229 	while (qp->boe && qp->nodep == NULL) {
230 		(void) pthread_cond_wait(&qp->cvar, &qp->mutex);
231 	}
232 
233 	/*
234 	 * If Block-On-Empty is false, the queue may be empty
235 	 */
236 	if (qp->nodep != NULL) {
237 		rv = qp->nodep->data;
238 		nextnode = qp->nodep->next;
239 		qp->nfree(qp->nodep, sizeof (struct q_node));
240 		qp->nodep = nextnode;
241 	}
242 
243 	dm_assert(pthread_mutex_unlock(&qp->mutex) == 0);
244 	return (rv);
245 }
246 
247 qu_t *
new_queue(boolean_t block_on_empty,void * (* nodealloc)(size_t),void (* nodefree)(void *,size_t),void (* data_deallocator)(void *))248 new_queue(boolean_t block_on_empty, void *(*nodealloc)(size_t),
249     void (*nodefree)(void *, size_t), void (*data_deallocator)(void *))
250 {
251 	qu_t *newqp = (qu_t *)dmalloc(sizeof (qu_t));
252 
253 	newqp->boe = block_on_empty;
254 	newqp->nalloc = nodealloc;
255 	newqp->nfree = nodefree;
256 	newqp->data_dealloc = data_deallocator;
257 	dm_assert(pthread_mutex_init(&newqp->mutex, NULL) == 0);
258 	dm_assert(pthread_cond_init(&newqp->cvar, NULL) == 0);
259 	newqp->nodep = NULL;
260 
261 	return (newqp);
262 }
263 
264 void
queue_free(qu_t ** qpp)265 queue_free(qu_t **qpp)
266 {
267 	qu_t *qp = *qpp;
268 	void *item;
269 
270 	dm_assert(pthread_mutex_destroy(&qp->mutex) == 0);
271 	dm_assert(pthread_cond_destroy(&qp->cvar) == 0);
272 
273 	qp->boe = B_FALSE;
274 
275 	while ((item = queue_remove(qp)) != NULL) {
276 		qp->data_dealloc(item);
277 	}
278 
279 	dm_assert(qp->nodep == NULL);
280 
281 	dfree(qp, sizeof (qu_t));
282 	*qpp = NULL;
283 }
284 
285 int
_dm_assert(const char * assertion,const char * file,int line,const char * func)286 _dm_assert(const char *assertion, const char *file, int line, const char *func)
287 {
288 	/*
289 	 * No newline is appended to the assertion message so that
290 	 * errno can be translated for us by fmd_hdl_abort().
291 	 */
292 	if (func)
293 		fmd_hdl_abort(g_fm_hdl, "Assertion failed: "
294 		    "%s, file: %s, line: %d, function: %s", assertion, file,
295 		    line, func);
296 	else
297 		fmd_hdl_abort(g_fm_hdl, "Assertion failed: "
298 		    "%s, file: %s, line: %d", assertion, file, line);
299 	/*NOTREACHED*/
300 	return (0);
301 }
302