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 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 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 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 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 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 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 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 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 162 dfree(void *p, size_t sz) 163 { 164 fmd_hdl_free(g_fm_hdl, p, sz); 165 } 166 167 void 168 dstrfree(char *s) 169 { 170 fmd_hdl_strfree(g_fm_hdl, s); 171 } 172 173 void * 174 dmalloc(size_t sz) 175 { 176 return (fmd_hdl_alloc(g_fm_hdl, sz, FMD_SLEEP)); 177 } 178 179 void * 180 dzmalloc(size_t sz) 181 { 182 return (fmd_hdl_zalloc(g_fm_hdl, sz, FMD_SLEEP)); 183 } 184 185 186 char * 187 dstrdup(const char *s) 188 { 189 return (fmd_hdl_strdup(g_fm_hdl, s, FMD_SLEEP)); 190 } 191 192 void 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 * 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 * 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 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 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