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/stdinc.h" 35 36 #include "spdk_internal/log.h" 37 38 static TAILQ_HEAD(, spdk_trace_flag) g_trace_flags = TAILQ_HEAD_INITIALIZER(g_trace_flags); 39 40 unsigned int spdk_g_notice_stderr_flag = 1; 41 int spdk_g_log_facility = LOG_DAEMON; 42 unsigned int spdk_g_log_priority = LOG_NOTICE; 43 44 SPDK_LOG_REGISTER_TRACE_FLAG("debug", SPDK_TRACE_DEBUG) 45 46 #define MAX_TMPBUF 1024 47 48 struct syslog_code { 49 const char *c_name; 50 int c_val; 51 }; 52 53 static const struct syslog_code facilitynames[] = { 54 { "auth", LOG_AUTH, }, 55 { "authpriv", LOG_AUTHPRIV, }, 56 { "cron", LOG_CRON, }, 57 { "daemon", LOG_DAEMON, }, 58 { "ftp", LOG_FTP, }, 59 { "kern", LOG_KERN, }, 60 { "lpr", LOG_LPR, }, 61 { "mail", LOG_MAIL, }, 62 { "news", LOG_NEWS, }, 63 { "syslog", LOG_SYSLOG, }, 64 { "user", LOG_USER, }, 65 { "uucp", LOG_UUCP, }, 66 { "local0", LOG_LOCAL0, }, 67 { "local1", LOG_LOCAL1, }, 68 { "local2", LOG_LOCAL2, }, 69 { "local3", LOG_LOCAL3, }, 70 { "local4", LOG_LOCAL4, }, 71 { "local5", LOG_LOCAL5, }, 72 { "local6", LOG_LOCAL6, }, 73 { "local7", LOG_LOCAL7, }, 74 #ifdef __FreeBSD__ 75 { "console", LOG_CONSOLE, }, 76 { "ntp", LOG_NTP, }, 77 { "security", LOG_SECURITY, }, 78 #endif 79 { NULL, -1, } 80 }; 81 82 static const struct syslog_code prioritynames[] = { 83 { "alert", LOG_ALERT, }, 84 { "crit", LOG_CRIT, }, 85 { "debug", LOG_DEBUG, }, 86 { "emerg", LOG_EMERG, }, 87 { "err", LOG_ERR, }, 88 { "info", LOG_INFO, }, 89 { "notice", LOG_NOTICE, }, 90 { "warning", LOG_WARNING, }, 91 { NULL, -1, } 92 }; 93 94 int 95 spdk_set_log_facility(const char *facility) 96 { 97 int i; 98 99 for (i = 0; facilitynames[i].c_name != NULL; i++) { 100 if (strcasecmp(facilitynames[i].c_name, facility) == 0) { 101 spdk_g_log_facility = facilitynames[i].c_val; 102 return 0; 103 } 104 } 105 106 spdk_g_log_facility = LOG_DAEMON; 107 return -1; 108 } 109 110 const char * 111 spdk_get_log_facility(void) 112 { 113 const char *def_name = NULL; 114 int i; 115 116 for (i = 0; facilitynames[i].c_name != NULL; i++) { 117 if (facilitynames[i].c_val == spdk_g_log_facility) { 118 return facilitynames[i].c_name; 119 } else if (facilitynames[i].c_val == LOG_DAEMON) { 120 def_name = facilitynames[i].c_name; 121 } 122 } 123 124 return def_name; 125 } 126 127 int 128 spdk_set_log_priority(const char *priority) 129 { 130 int i; 131 132 for (i = 0; prioritynames[i].c_name != NULL; i++) { 133 if (strcasecmp(prioritynames[i].c_name, priority) == 0) { 134 spdk_g_log_priority = prioritynames[i].c_val; 135 return 0; 136 } 137 } 138 139 spdk_g_log_priority = LOG_NOTICE; 140 return -1; 141 } 142 143 void 144 spdk_noticelog(const char *file, const int line, const char *func, 145 const char *format, ...) 146 { 147 char buf[MAX_TMPBUF]; 148 va_list ap; 149 150 va_start(ap, format); 151 vsnprintf(buf, sizeof buf, format, ap); 152 if (file != NULL) { 153 if (func != NULL) { 154 if (spdk_g_notice_stderr_flag) { 155 fprintf(stderr, "%s:%4d:%s: %s", file, line, func, buf); 156 } 157 syslog(LOG_NOTICE, "%s:%4d:%s: %s", file, line, func, buf); 158 } else { 159 if (spdk_g_notice_stderr_flag) { 160 fprintf(stderr, "%s:%4d: %s", file, line, buf); 161 } 162 syslog(LOG_NOTICE, "%s:%4d: %s", file, line, buf); 163 } 164 } else { 165 if (spdk_g_notice_stderr_flag) { 166 fprintf(stderr, "%s", buf); 167 } 168 syslog(LOG_NOTICE, "%s", buf); 169 } 170 va_end(ap); 171 } 172 173 void 174 spdk_warnlog(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 (file != NULL) { 183 if (func != NULL) { 184 fprintf(stderr, "%s:%4d:%s: %s", file, line, func, buf); 185 syslog(LOG_WARNING, "%s:%4d:%s: %s", 186 file, line, func, buf); 187 } else { 188 fprintf(stderr, "%s:%4d: %s", file, line, buf); 189 syslog(LOG_WARNING, "%s:%4d: %s", file, line, buf); 190 } 191 } else { 192 fprintf(stderr, "%s", buf); 193 syslog(LOG_WARNING, "%s", buf); 194 } 195 196 va_end(ap); 197 } 198 199 void 200 spdk_tracelog(const char *flag, const char *file, const int line, const char *func, 201 const char *format, ...) 202 { 203 char buf[MAX_TMPBUF]; 204 va_list ap; 205 206 va_start(ap, format); 207 vsnprintf(buf, sizeof buf, format, ap); 208 if (func != NULL) { 209 fprintf(stderr, "[%s] %s:%4d:%s: %s", flag, file, line, func, buf); 210 //syslog(LOG_INFO, "[%s] %s:%4d:%s: %s", flag, file, line, func, buf); 211 } else { 212 fprintf(stderr, "[%s] %s:%4d: %s", flag, file, line, buf); 213 //syslog(LOG_INFO, "[%s] %s:%4d: %s", flag, file, line, buf); 214 } 215 va_end(ap); 216 } 217 218 void 219 spdk_errlog(const char *file, const int line, const char *func, 220 const char *format, ...) 221 { 222 char buf[MAX_TMPBUF]; 223 va_list ap; 224 225 va_start(ap, format); 226 vsnprintf(buf, sizeof buf, format, ap); 227 if (func != NULL) { 228 fprintf(stderr, "%s:%4d:%s: ***ERROR*** %s", file, line, func, buf); 229 syslog(LOG_ERR, "%s:%4d:%s: ***ERROR*** %s", file, line, func, buf); 230 } else { 231 fprintf(stderr, "%s:%4d: ***ERROR*** %s", file, line, buf); 232 syslog(LOG_ERR, "%s:%4d: ***ERROR*** %s", file, line, buf); 233 } 234 va_end(ap); 235 } 236 237 static void 238 fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len) 239 { 240 char tmpbuf[MAX_TMPBUF]; 241 char buf16[16 + 1]; 242 size_t total; 243 unsigned int idx; 244 245 fprintf(fp, "%s\n", label); 246 247 memset(buf16, 0, sizeof buf16); 248 total = 0; 249 for (idx = 0; idx < len; idx++) { 250 if (idx != 0 && idx % 16 == 0) { 251 snprintf(tmpbuf + total, sizeof tmpbuf - total, 252 " %s", buf16); 253 fprintf(fp, "%s\n", tmpbuf); 254 total = 0; 255 } 256 if (idx % 16 == 0) { 257 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 258 "%08x ", idx); 259 } 260 if (idx % 8 == 0) { 261 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 262 "%s", " "); 263 } 264 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 265 "%2.2x ", buf[idx] & 0xff); 266 buf16[idx % 16] = isprint(buf[idx]) ? buf[idx] : '.'; 267 } 268 for (; idx % 16 != 0; idx++) { 269 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, " "); 270 buf16[idx % 16] = ' '; 271 } 272 snprintf(tmpbuf + total, sizeof tmpbuf - total, " %s", buf16); 273 fprintf(fp, "%s\n", tmpbuf); 274 fflush(fp); 275 } 276 277 void 278 spdk_trace_dump(const char *label, const uint8_t *buf, size_t len) 279 { 280 fdump(stderr, label, buf, len); 281 } 282 283 static struct spdk_trace_flag * 284 get_trace_flag(const char *name) 285 { 286 struct spdk_trace_flag *flag; 287 288 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 289 if (strcasecmp(name, flag->name) == 0) { 290 return flag; 291 } 292 } 293 294 return NULL; 295 } 296 297 void 298 spdk_log_register_trace_flag(const char *name, struct spdk_trace_flag *flag) 299 { 300 struct spdk_trace_flag *iter; 301 302 if (name == NULL || flag == NULL) { 303 fprintf(stderr, "missing spdk_trace_flag parameters\n"); 304 abort(); 305 } 306 307 if (get_trace_flag(name)) { 308 fprintf(stderr, "duplicate spdk_trace_flag '%s'\n", name); 309 abort(); 310 } 311 312 TAILQ_FOREACH(iter, &g_trace_flags, tailq) { 313 if (strcasecmp(iter->name, flag->name) > 0) { 314 TAILQ_INSERT_BEFORE(iter, flag, tailq); 315 return; 316 } 317 } 318 319 TAILQ_INSERT_TAIL(&g_trace_flags, flag, tailq); 320 } 321 322 bool 323 spdk_log_get_trace_flag(const char *name) 324 { 325 struct spdk_trace_flag *flag = get_trace_flag(name); 326 327 if (flag && flag->enabled) { 328 return true; 329 } 330 331 return false; 332 } 333 334 static int 335 set_trace_flag(const char *name, bool value) 336 { 337 struct spdk_trace_flag *flag; 338 339 if (strcasecmp(name, "all") == 0) { 340 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 341 flag->enabled = value; 342 } 343 return 0; 344 } 345 346 flag = get_trace_flag(name); 347 if (flag == NULL) { 348 return -1; 349 } 350 351 flag->enabled = value; 352 353 return 0; 354 } 355 356 int 357 spdk_log_set_trace_flag(const char *name) 358 { 359 return set_trace_flag(name, true); 360 } 361 362 int 363 spdk_log_clear_trace_flag(const char *name) 364 { 365 return set_trace_flag(name, false); 366 } 367 368 struct spdk_trace_flag * 369 spdk_log_get_first_trace_flag(void) 370 { 371 return TAILQ_FIRST(&g_trace_flags); 372 } 373 374 struct spdk_trace_flag * 375 spdk_log_get_next_trace_flag(struct spdk_trace_flag *flag) 376 { 377 return TAILQ_NEXT(flag, tailq); 378 } 379 380 void 381 spdk_open_log(void) 382 { 383 if (spdk_g_log_facility != 0) { 384 openlog("spdk", LOG_PID, spdk_g_log_facility); 385 } else { 386 openlog("spdk", LOG_PID, LOG_DAEMON); 387 } 388 } 389 390 void 391 spdk_close_log(void) 392 { 393 closelog(); 394 } 395 396 void 397 spdk_tracelog_usage(FILE *f, const char *trace_arg) 398 { 399 #ifdef DEBUG 400 struct spdk_trace_flag *flag; 401 402 fprintf(f, " %s flag enable trace flag (all", trace_arg); 403 404 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 405 fprintf(f, ", %s", flag->name); 406 } 407 408 fprintf(f, ")\n"); 409 #else 410 fprintf(f, " %s flag enable trace flag (not supported - must rebuild with CONFIG_DEBUG=y)\n", 411 trace_arg); 412 #endif 413 } 414