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