1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/log.h" 35 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <strings.h> 41 #include <syslog.h> 42 #include <ctype.h> 43 #include <errno.h> 44 45 struct spdk_trace_flag { 46 const char *name; 47 bool *enabled; 48 }; 49 50 static size_t g_num_trace_flags = 0; 51 static struct spdk_trace_flag *g_trace_flags = NULL; 52 53 unsigned int spdk_g_notice_stderr_flag = 1; 54 unsigned int spdk_g_log_facility = LOG_DAEMON; 55 unsigned int spdk_g_log_priority = LOG_NOTICE; 56 57 SPDK_LOG_REGISTER_TRACE_FLAG("debug", SPDK_TRACE_DEBUG) 58 59 #define MAX_TMPBUF 1024 60 61 int 62 spdk_set_log_facility(const char *facility) 63 { 64 if (strcasecmp(facility, "daemon") == 0) { 65 spdk_g_log_facility = LOG_DAEMON; 66 } else if (strcasecmp(facility, "auth") == 0) { 67 spdk_g_log_facility = LOG_AUTH; 68 } else if (strcasecmp(facility, "authpriv") == 0) { 69 spdk_g_log_facility = LOG_AUTHPRIV; 70 } else if (strcasecmp(facility, "local1") == 0) { 71 spdk_g_log_facility = LOG_LOCAL1; 72 } else if (strcasecmp(facility, "local2") == 0) { 73 spdk_g_log_facility = LOG_LOCAL2; 74 } else if (strcasecmp(facility, "local3") == 0) { 75 spdk_g_log_facility = LOG_LOCAL3; 76 } else if (strcasecmp(facility, "local4") == 0) { 77 spdk_g_log_facility = LOG_LOCAL4; 78 } else if (strcasecmp(facility, "local5") == 0) { 79 spdk_g_log_facility = LOG_LOCAL5; 80 } else if (strcasecmp(facility, "local6") == 0) { 81 spdk_g_log_facility = LOG_LOCAL6; 82 } else if (strcasecmp(facility, "local7") == 0) { 83 spdk_g_log_facility = LOG_LOCAL7; 84 } else { 85 spdk_g_log_facility = LOG_DAEMON; 86 return -1; 87 } 88 return 0; 89 } 90 91 int 92 spdk_set_log_priority(const char *priority) 93 { 94 if (strcasecmp(priority, "emerg") == 0) { 95 spdk_g_log_priority = LOG_EMERG; 96 } else if (strcasecmp(priority, "alert") == 0) { 97 spdk_g_log_priority = LOG_ALERT; 98 } else if (strcasecmp(priority, "crit") == 0) { 99 spdk_g_log_priority = LOG_CRIT; 100 } else if (strcasecmp(priority, "err") == 0) { 101 spdk_g_log_priority = LOG_ERR; 102 } else if (strcasecmp(priority, "warning") == 0) { 103 spdk_g_log_priority = LOG_WARNING; 104 } else if (strcasecmp(priority, "notice") == 0) { 105 spdk_g_log_priority = LOG_NOTICE; 106 } else if (strcasecmp(priority, "info") == 0) { 107 spdk_g_log_priority = LOG_INFO; 108 } else if (strcasecmp(priority, "debug") == 0) { 109 spdk_g_log_priority = LOG_DEBUG; 110 } else { 111 spdk_g_log_priority = LOG_NOTICE; 112 return -1; 113 } 114 return 0; 115 } 116 117 void 118 spdk_noticelog(const char *file, const int line, const char *func, 119 const char *format, ...) 120 { 121 char buf[MAX_TMPBUF]; 122 va_list ap; 123 124 va_start(ap, format); 125 vsnprintf(buf, sizeof buf, format, ap); 126 if (file != NULL) { 127 if (func != NULL) { 128 if (spdk_g_notice_stderr_flag) { 129 fprintf(stderr, "%s:%4d:%s: %s", file, line, func, buf); 130 } 131 syslog(LOG_NOTICE, "%s:%4d:%s: %s", file, line, func, buf); 132 } else { 133 if (spdk_g_notice_stderr_flag) { 134 fprintf(stderr, "%s:%4d: %s", file, line, buf); 135 } 136 syslog(LOG_NOTICE, "%s:%4d: %s", file, line, buf); 137 } 138 } else { 139 if (spdk_g_notice_stderr_flag) { 140 fprintf(stderr, "%s", buf); 141 } 142 syslog(LOG_NOTICE, "%s", buf); 143 } 144 va_end(ap); 145 } 146 147 void 148 spdk_warnlog(const char *file, const int line, const char *func, 149 const char *format, ...) 150 { 151 char buf[MAX_TMPBUF]; 152 va_list ap; 153 154 va_start(ap, format); 155 vsnprintf(buf, sizeof buf, format, ap); 156 if (file != NULL) { 157 if (func != NULL) { 158 fprintf(stderr, "%s:%4d:%s: %s", file, line, func, buf); 159 syslog(LOG_WARNING, "%s:%4d:%s: %s", 160 file, line, func, buf); 161 } else { 162 fprintf(stderr, "%s:%4d: %s", file, line, buf); 163 syslog(LOG_WARNING, "%s:%4d: %s", file, line, buf); 164 } 165 } else { 166 fprintf(stderr, "%s", buf); 167 syslog(LOG_WARNING, "%s", buf); 168 } 169 170 va_end(ap); 171 } 172 173 void 174 spdk_tracelog(const char *file, const int line, const char *func, 175 const char *format, ...) 176 { 177 char buf[MAX_TMPBUF]; 178 va_list ap; 179 180 va_start(ap, format); 181 vsnprintf(buf, sizeof buf, format, ap); 182 if (func != NULL) { 183 fprintf(stderr, "%s:%4d:%s: %s", file, line, func, buf); 184 //syslog(LOG_INFO, "%s:%4d:%s: %s", file, line, func, buf); 185 } else { 186 fprintf(stderr, "%s:%4d: %s", file, line, buf); 187 //syslog(LOG_INFO, "%s:%4d: %s", file, line, buf); 188 } 189 va_end(ap); 190 } 191 192 void 193 spdk_errlog(const char *file, const int line, const char *func, 194 const char *format, ...) 195 { 196 char buf[MAX_TMPBUF]; 197 va_list ap; 198 199 va_start(ap, format); 200 vsnprintf(buf, sizeof buf, format, ap); 201 if (func != NULL) { 202 fprintf(stderr, "%s:%4d:%s: ***ERROR*** %s", file, line, func, buf); 203 syslog(LOG_ERR, "%s:%4d:%s: ***ERROR*** %s", file, line, func, buf); 204 } else { 205 fprintf(stderr, "%s:%4d: ***ERROR*** %s", file, line, buf); 206 syslog(LOG_ERR, "%s:%4d: ***ERROR*** %s", file, line, buf); 207 } 208 va_end(ap); 209 } 210 211 static void 212 fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len) 213 { 214 char tmpbuf[MAX_TMPBUF]; 215 char buf16[16 + 1]; 216 size_t total; 217 unsigned int idx; 218 219 fprintf(fp, "%s\n", label); 220 221 memset(buf16, 0, sizeof buf16); 222 total = 0; 223 for (idx = 0; idx < len; idx++) { 224 if (idx != 0 && idx % 16 == 0) { 225 snprintf(tmpbuf + total, sizeof tmpbuf - total, 226 " %s", buf16); 227 fprintf(fp, "%s\n", tmpbuf); 228 total = 0; 229 } 230 if (idx % 16 == 0) { 231 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 232 "%08x ", idx); 233 } 234 if (idx % 8 == 0) { 235 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 236 "%s", " "); 237 } 238 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 239 "%2.2x ", buf[idx] & 0xff); 240 buf16[idx % 16] = isprint(buf[idx]) ? buf[idx] : '.'; 241 } 242 for (; idx % 16 != 0; idx++) { 243 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, " "); 244 buf16[idx % 16] = ' '; 245 } 246 snprintf(tmpbuf + total, sizeof tmpbuf - total, " %s", buf16); 247 fprintf(fp, "%s\n", tmpbuf); 248 fflush(fp); 249 } 250 251 void 252 spdk_trace_dump(const char *label, const uint8_t *buf, size_t len) 253 { 254 fdump(stderr, label, buf, len); 255 } 256 257 static int compare_trace_flags(const void *key, const void *p) 258 { 259 const struct spdk_trace_flag *flag = p; 260 261 return strcasecmp(key, flag->name); 262 } 263 264 static struct spdk_trace_flag * 265 get_trace_flag(const char *name) 266 { 267 return bsearch(name, g_trace_flags, g_num_trace_flags, sizeof(struct spdk_trace_flag), 268 compare_trace_flags); 269 } 270 271 void 272 spdk_log_register_trace_flag(const char *name, bool *enabled) 273 { 274 struct spdk_trace_flag *flag, *new_flags; 275 276 if (name == NULL || enabled == NULL) { 277 fprintf(stderr, "missing spdk_trace_flag parameters\n"); 278 abort(); 279 } 280 281 if (get_trace_flag(name)) { 282 fprintf(stderr, "duplicate spdk_trace_flag '%s'\n", name); 283 abort(); 284 } 285 286 new_flags = realloc(g_trace_flags, (g_num_trace_flags + 1) * sizeof(struct spdk_trace_flag)); 287 if (new_flags == NULL) { 288 fprintf(stderr, "spdk_trace_flag allocation error\n"); 289 abort(); 290 } 291 292 g_trace_flags = new_flags; 293 294 /* Find slot so that new flag is inserted in sorted order */ 295 for (flag = g_trace_flags; flag != g_trace_flags + g_num_trace_flags; flag++) { 296 if (strcasecmp(name, flag->name) < 0) { 297 size_t to_move = g_num_trace_flags - (flag - g_trace_flags); 298 299 memmove(flag + 1, flag, to_move * sizeof(struct spdk_trace_flag)); 300 break; 301 } 302 } 303 304 flag->name = name; 305 flag->enabled = enabled; 306 g_num_trace_flags++; 307 } 308 309 bool 310 spdk_log_get_trace_flag(const char *name) 311 { 312 struct spdk_trace_flag *flag = get_trace_flag(name); 313 314 if (flag && *flag->enabled) { 315 return true; 316 } 317 318 return false; 319 } 320 321 static int 322 set_trace_flag(const char *name, bool value) 323 { 324 struct spdk_trace_flag *flag; 325 size_t i; 326 327 if (strcasecmp(name, "all") == 0) { 328 for (i = 0; i < g_num_trace_flags; i++) { 329 *g_trace_flags[i].enabled = value; 330 } 331 return 0; 332 } 333 334 flag = get_trace_flag(name); 335 if (flag == NULL) { 336 return -1; 337 } 338 339 *flag->enabled = value; 340 341 return 0; 342 } 343 344 int 345 spdk_log_set_trace_flag(const char *name) 346 { 347 return set_trace_flag(name, true); 348 } 349 350 int 351 spdk_log_clear_trace_flag(const char *name) 352 { 353 return set_trace_flag(name, false); 354 } 355 356 357 size_t spdk_log_get_num_trace_flags(void) 358 { 359 return g_num_trace_flags; 360 } 361 362 const char *spdk_log_get_trace_flag_name(size_t idx) 363 { 364 if (idx >= g_num_trace_flags) { 365 return NULL; 366 } 367 368 return g_trace_flags[idx].name; 369 } 370 371 void 372 spdk_open_log(void) 373 { 374 if (spdk_g_log_facility != 0) { 375 openlog("spdk", LOG_PID, spdk_g_log_facility); 376 } else { 377 openlog("spdk", LOG_PID, LOG_DAEMON); 378 } 379 } 380 381 void 382 spdk_close_log(void) 383 { 384 closelog(); 385 } 386 387 void 388 spdk_tracelog_usage(FILE *f, const char *trace_arg) 389 { 390 #ifdef DEBUG 391 size_t i; 392 393 fprintf(f, " %s flag enable trace flag (all", trace_arg); 394 395 for (i = 0; i < g_num_trace_flags; i++) { 396 fprintf(f, ", %s", g_trace_flags[i].name); 397 } 398 399 fprintf(f, ")\n"); 400 #else 401 fprintf(f, " %s flag enable trace flag (not supported - must rebuild with CONFIG_DEBUG=y)\n", 402 trace_arg); 403 #endif 404 } 405