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