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