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 int spdk_g_log_facility = LOG_DAEMON; 41 static enum spdk_log_level g_spdk_log_level = SPDK_LOG_NOTICE; 42 static enum spdk_log_level g_spdk_log_print_level = SPDK_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 char *const spdk_level_names[] = { 83 [SPDK_LOG_ERROR] = "ERROR", 84 [SPDK_LOG_WARN] = "WARNING", 85 [SPDK_LOG_NOTICE] = "NOTICE", 86 [SPDK_LOG_INFO] = "INFO", 87 [SPDK_LOG_DEBUG] = "DEBUG", 88 }; 89 90 void 91 spdk_log_open(void) 92 { 93 if (spdk_g_log_facility != 0) { 94 openlog("spdk", LOG_PID, spdk_g_log_facility); 95 } else { 96 openlog("spdk", LOG_PID, LOG_DAEMON); 97 } 98 } 99 100 void 101 spdk_log_close(void) 102 { 103 closelog(); 104 } 105 106 void 107 spdk_log_set_level(enum spdk_log_level level) 108 { 109 g_spdk_log_level = level; 110 } 111 112 enum spdk_log_level 113 spdk_log_get_level(void) { 114 return g_spdk_log_level; 115 } 116 117 void 118 spdk_log_set_print_level(enum spdk_log_level level) 119 { 120 g_spdk_log_print_level = level; 121 } 122 123 enum spdk_log_level 124 spdk_log_get_print_level(void) { 125 return g_spdk_log_print_level; 126 } 127 128 int 129 spdk_set_log_facility(const char *facility) 130 { 131 int i; 132 133 for (i = 0; facilitynames[i].c_name != NULL; i++) { 134 if (strcasecmp(facilitynames[i].c_name, facility) == 0) { 135 spdk_g_log_facility = facilitynames[i].c_val; 136 return 0; 137 } 138 } 139 140 spdk_g_log_facility = LOG_DAEMON; 141 return -1; 142 } 143 144 const char * 145 spdk_get_log_facility(void) 146 { 147 const char *def_name = NULL; 148 int i; 149 150 for (i = 0; facilitynames[i].c_name != NULL; i++) { 151 if (facilitynames[i].c_val == spdk_g_log_facility) { 152 return facilitynames[i].c_name; 153 } else if (facilitynames[i].c_val == LOG_DAEMON) { 154 def_name = facilitynames[i].c_name; 155 } 156 } 157 158 return def_name; 159 } 160 161 void 162 spdk_log(enum spdk_log_level level, const char *file, const int line, const char *func, 163 const char *format, ...) 164 { 165 int severity = LOG_INFO; 166 char buf[MAX_TMPBUF]; 167 va_list ap; 168 169 switch (level) { 170 case SPDK_LOG_ERROR: 171 severity = LOG_ERR; 172 break; 173 case SPDK_LOG_WARN: 174 severity = LOG_WARNING; 175 break; 176 case SPDK_LOG_NOTICE: 177 severity = LOG_NOTICE; 178 break; 179 case SPDK_LOG_INFO: 180 case SPDK_LOG_DEBUG: 181 severity = LOG_INFO; 182 break; 183 } 184 185 va_start(ap, format); 186 187 vsnprintf(buf, sizeof(buf), format, ap); 188 189 if (level <= g_spdk_log_print_level) { 190 fprintf(stderr, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf); 191 } 192 193 if (level <= g_spdk_log_level) { 194 syslog(severity, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf); 195 } 196 197 va_end(ap); 198 } 199 200 static void 201 fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len) 202 { 203 char tmpbuf[MAX_TMPBUF]; 204 char buf16[16 + 1]; 205 size_t total; 206 unsigned int idx; 207 208 fprintf(fp, "%s\n", label); 209 210 memset(buf16, 0, sizeof buf16); 211 total = 0; 212 for (idx = 0; idx < len; idx++) { 213 if (idx != 0 && idx % 16 == 0) { 214 snprintf(tmpbuf + total, sizeof tmpbuf - total, 215 " %s", buf16); 216 fprintf(fp, "%s\n", tmpbuf); 217 total = 0; 218 } 219 if (idx % 16 == 0) { 220 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 221 "%08x ", idx); 222 } 223 if (idx % 8 == 0) { 224 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 225 "%s", " "); 226 } 227 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 228 "%2.2x ", buf[idx] & 0xff); 229 buf16[idx % 16] = isprint(buf[idx]) ? buf[idx] : '.'; 230 } 231 for (; idx % 16 != 0; idx++) { 232 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, " "); 233 buf16[idx % 16] = ' '; 234 } 235 snprintf(tmpbuf + total, sizeof tmpbuf - total, " %s", buf16); 236 fprintf(fp, "%s\n", tmpbuf); 237 fflush(fp); 238 } 239 240 void 241 spdk_trace_dump(const char *label, const uint8_t *buf, size_t len) 242 { 243 fdump(stderr, label, buf, len); 244 } 245 246 static struct spdk_trace_flag * 247 get_trace_flag(const char *name) 248 { 249 struct spdk_trace_flag *flag; 250 251 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 252 if (strcasecmp(name, flag->name) == 0) { 253 return flag; 254 } 255 } 256 257 return NULL; 258 } 259 260 void 261 spdk_log_register_trace_flag(const char *name, struct spdk_trace_flag *flag) 262 { 263 struct spdk_trace_flag *iter; 264 265 if (name == NULL || flag == NULL) { 266 SPDK_ERRLOG("missing spdk_trace_flag parameters\n"); 267 abort(); 268 } 269 270 if (get_trace_flag(name)) { 271 SPDK_ERRLOG("duplicate spdk_trace_flag '%s'\n", name); 272 abort(); 273 } 274 275 TAILQ_FOREACH(iter, &g_trace_flags, tailq) { 276 if (strcasecmp(iter->name, flag->name) > 0) { 277 TAILQ_INSERT_BEFORE(iter, flag, tailq); 278 return; 279 } 280 } 281 282 TAILQ_INSERT_TAIL(&g_trace_flags, flag, tailq); 283 } 284 285 bool 286 spdk_log_get_trace_flag(const char *name) 287 { 288 struct spdk_trace_flag *flag = get_trace_flag(name); 289 290 if (flag && flag->enabled) { 291 return true; 292 } 293 294 return false; 295 } 296 297 static int 298 set_trace_flag(const char *name, bool value) 299 { 300 struct spdk_trace_flag *flag; 301 302 if (strcasecmp(name, "all") == 0) { 303 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 304 flag->enabled = value; 305 } 306 return 0; 307 } 308 309 flag = get_trace_flag(name); 310 if (flag == NULL) { 311 return -1; 312 } 313 314 flag->enabled = value; 315 316 return 0; 317 } 318 319 int 320 spdk_log_set_trace_flag(const char *name) 321 { 322 return set_trace_flag(name, true); 323 } 324 325 int 326 spdk_log_clear_trace_flag(const char *name) 327 { 328 return set_trace_flag(name, false); 329 } 330 331 struct spdk_trace_flag * 332 spdk_log_get_first_trace_flag(void) 333 { 334 return TAILQ_FIRST(&g_trace_flags); 335 } 336 337 struct spdk_trace_flag * 338 spdk_log_get_next_trace_flag(struct spdk_trace_flag *flag) 339 { 340 return TAILQ_NEXT(flag, tailq); 341 } 342 343 void 344 spdk_tracelog_usage(FILE *f, const char *trace_arg) 345 { 346 #ifdef DEBUG 347 struct spdk_trace_flag *flag; 348 349 fprintf(f, " %s flag enable trace flag (all", trace_arg); 350 351 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 352 fprintf(f, ", %s", flag->name); 353 } 354 355 fprintf(f, ")\n"); 356 #else 357 fprintf(f, " %s flag enable trace flag (not supported - must rebuild with CONFIG_DEBUG=y)\n", 358 trace_arg); 359 #endif 360 } 361