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 static enum spdk_log_level g_spdk_log_level = SPDK_LOG_NOTICE; 41 static enum spdk_log_level g_spdk_log_print_level = SPDK_LOG_NOTICE; 42 43 SPDK_LOG_REGISTER_TRACE_FLAG("log", SPDK_TRACE_LOG) 44 45 #define MAX_TMPBUF 1024 46 47 static const char *const spdk_level_names[] = { 48 [SPDK_LOG_ERROR] = "ERROR", 49 [SPDK_LOG_WARN] = "WARNING", 50 [SPDK_LOG_NOTICE] = "NOTICE", 51 [SPDK_LOG_INFO] = "INFO", 52 [SPDK_LOG_DEBUG] = "DEBUG", 53 }; 54 55 void 56 spdk_log_open(void) 57 { 58 openlog("spdk", LOG_PID, LOG_LOCAL7); 59 } 60 61 void 62 spdk_log_close(void) 63 { 64 closelog(); 65 } 66 67 void 68 spdk_log_set_level(enum spdk_log_level level) 69 { 70 g_spdk_log_level = level; 71 } 72 73 enum spdk_log_level 74 spdk_log_get_level(void) { 75 return g_spdk_log_level; 76 } 77 78 void 79 spdk_log_set_print_level(enum spdk_log_level level) 80 { 81 g_spdk_log_print_level = level; 82 } 83 84 enum spdk_log_level 85 spdk_log_get_print_level(void) { 86 return g_spdk_log_print_level; 87 } 88 89 void 90 spdk_log(enum spdk_log_level level, const char *file, const int line, const char *func, 91 const char *format, ...) 92 { 93 int severity = LOG_INFO; 94 char buf[MAX_TMPBUF]; 95 va_list ap; 96 97 switch (level) { 98 case SPDK_LOG_ERROR: 99 severity = LOG_ERR; 100 break; 101 case SPDK_LOG_WARN: 102 severity = LOG_WARNING; 103 break; 104 case SPDK_LOG_NOTICE: 105 severity = LOG_NOTICE; 106 break; 107 case SPDK_LOG_INFO: 108 case SPDK_LOG_DEBUG: 109 severity = LOG_INFO; 110 break; 111 } 112 113 va_start(ap, format); 114 115 vsnprintf(buf, sizeof(buf), format, ap); 116 117 if (level <= g_spdk_log_print_level) { 118 fprintf(stderr, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf); 119 } 120 121 if (level <= g_spdk_log_level) { 122 syslog(severity, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf); 123 } 124 125 va_end(ap); 126 } 127 128 static void 129 fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len) 130 { 131 char tmpbuf[MAX_TMPBUF]; 132 char buf16[16 + 1]; 133 size_t total; 134 unsigned int idx; 135 136 fprintf(fp, "%s\n", label); 137 138 memset(buf16, 0, sizeof buf16); 139 total = 0; 140 for (idx = 0; idx < len; idx++) { 141 if (idx != 0 && idx % 16 == 0) { 142 snprintf(tmpbuf + total, sizeof tmpbuf - total, 143 " %s", buf16); 144 fprintf(fp, "%s\n", tmpbuf); 145 total = 0; 146 } 147 if (idx % 16 == 0) { 148 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 149 "%08x ", idx); 150 } 151 if (idx % 8 == 0) { 152 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 153 "%s", " "); 154 } 155 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 156 "%2.2x ", buf[idx] & 0xff); 157 buf16[idx % 16] = isprint(buf[idx]) ? buf[idx] : '.'; 158 } 159 for (; idx % 16 != 0; idx++) { 160 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, " "); 161 buf16[idx % 16] = ' '; 162 } 163 snprintf(tmpbuf + total, sizeof tmpbuf - total, " %s", buf16); 164 fprintf(fp, "%s\n", tmpbuf); 165 fflush(fp); 166 } 167 168 void 169 spdk_trace_dump(FILE *fp, const char *label, const void *buf, size_t len) 170 { 171 fdump(fp, label, buf, len); 172 } 173 174 static struct spdk_trace_flag * 175 get_trace_flag(const char *name) 176 { 177 struct spdk_trace_flag *flag; 178 179 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 180 if (strcasecmp(name, flag->name) == 0) { 181 return flag; 182 } 183 } 184 185 return NULL; 186 } 187 188 void 189 spdk_log_register_trace_flag(const char *name, struct spdk_trace_flag *flag) 190 { 191 struct spdk_trace_flag *iter; 192 193 if (name == NULL || flag == NULL) { 194 SPDK_ERRLOG("missing spdk_trace_flag parameters\n"); 195 abort(); 196 } 197 198 if (get_trace_flag(name)) { 199 SPDK_ERRLOG("duplicate spdk_trace_flag '%s'\n", name); 200 abort(); 201 } 202 203 TAILQ_FOREACH(iter, &g_trace_flags, tailq) { 204 if (strcasecmp(iter->name, flag->name) > 0) { 205 TAILQ_INSERT_BEFORE(iter, flag, tailq); 206 return; 207 } 208 } 209 210 TAILQ_INSERT_TAIL(&g_trace_flags, flag, tailq); 211 } 212 213 bool 214 spdk_log_get_trace_flag(const char *name) 215 { 216 struct spdk_trace_flag *flag = get_trace_flag(name); 217 218 if (flag && flag->enabled) { 219 return true; 220 } 221 222 return false; 223 } 224 225 static int 226 set_trace_flag(const char *name, bool value) 227 { 228 struct spdk_trace_flag *flag; 229 230 if (strcasecmp(name, "all") == 0) { 231 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 232 flag->enabled = value; 233 } 234 return 0; 235 } 236 237 flag = get_trace_flag(name); 238 if (flag == NULL) { 239 return -1; 240 } 241 242 flag->enabled = value; 243 244 return 0; 245 } 246 247 int 248 spdk_log_set_trace_flag(const char *name) 249 { 250 return set_trace_flag(name, true); 251 } 252 253 int 254 spdk_log_clear_trace_flag(const char *name) 255 { 256 return set_trace_flag(name, false); 257 } 258 259 struct spdk_trace_flag * 260 spdk_log_get_first_trace_flag(void) 261 { 262 return TAILQ_FIRST(&g_trace_flags); 263 } 264 265 struct spdk_trace_flag * 266 spdk_log_get_next_trace_flag(struct spdk_trace_flag *flag) 267 { 268 return TAILQ_NEXT(flag, tailq); 269 } 270 271 void 272 spdk_tracelog_usage(FILE *f, const char *trace_arg) 273 { 274 #ifdef DEBUG 275 struct spdk_trace_flag *flag; 276 277 fprintf(f, " %s flag enable trace flag (all", trace_arg); 278 279 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 280 fprintf(f, ", %s", flag->name); 281 } 282 283 fprintf(f, ")\n"); 284 #else 285 fprintf(f, " %s flag enable trace flag (not supported - must rebuild with CONFIG_DEBUG=y)\n", 286 trace_arg); 287 #endif 288 } 289