1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 8 #include "spdk/log.h" 9 10 static TAILQ_HEAD(spdk_log_flag_head, 11 spdk_log_flag) g_log_flags = TAILQ_HEAD_INITIALIZER(g_log_flags); 12 13 static struct spdk_log_flag * 14 get_log_flag(const char *name) 15 { 16 struct spdk_log_flag *flag; 17 18 TAILQ_FOREACH(flag, &g_log_flags, tailq) { 19 if (strcasecmp(name, flag->name) == 0) { 20 return flag; 21 } 22 } 23 24 return NULL; 25 } 26 27 void 28 spdk_log_register_flag(const char *name, struct spdk_log_flag *flag) 29 { 30 struct spdk_log_flag *iter; 31 32 if (name == NULL || flag == NULL) { 33 SPDK_ERRLOG("missing spdk_log_flag parameters\n"); 34 assert(false); 35 return; 36 } 37 38 if (get_log_flag(name)) { 39 SPDK_ERRLOG("duplicate spdk_log_flag '%s'\n", name); 40 assert(false); 41 return; 42 } 43 44 TAILQ_FOREACH(iter, &g_log_flags, tailq) { 45 if (strcasecmp(iter->name, flag->name) > 0) { 46 TAILQ_INSERT_BEFORE(iter, flag, tailq); 47 return; 48 } 49 } 50 51 TAILQ_INSERT_TAIL(&g_log_flags, flag, tailq); 52 } 53 54 bool 55 spdk_log_get_flag(const char *name) 56 { 57 struct spdk_log_flag *flag = get_log_flag(name); 58 59 if (flag && flag->enabled) { 60 return true; 61 } 62 63 return false; 64 } 65 66 static int 67 log_set_flag(const char *name, bool value) 68 { 69 struct spdk_log_flag *flag; 70 int rc = -EINVAL; 71 72 if (strcasecmp(name, "all") == 0) { 73 TAILQ_FOREACH(flag, &g_log_flags, tailq) { 74 flag->enabled = value; 75 } 76 return 0; 77 } 78 79 TAILQ_FOREACH(flag, &g_log_flags, tailq) { 80 if (fnmatch(name, flag->name, FNM_CASEFOLD) == 0) { 81 flag->enabled = value; 82 rc = 0; 83 } 84 } 85 86 return rc; 87 } 88 89 int 90 spdk_log_set_flag(const char *name) 91 { 92 return log_set_flag(name, true); 93 } 94 95 int 96 spdk_log_clear_flag(const char *name) 97 { 98 return log_set_flag(name, false); 99 } 100 101 struct spdk_log_flag * 102 spdk_log_get_first_flag(void) 103 { 104 return TAILQ_FIRST(&g_log_flags); 105 } 106 107 struct spdk_log_flag * 108 spdk_log_get_next_flag(struct spdk_log_flag *flag) 109 { 110 return TAILQ_NEXT(flag, tailq); 111 } 112 113 void 114 spdk_log_usage(FILE *f, const char *log_arg) 115 { 116 #define LINE_PREFIX " " 117 #define ENTRY_SEPARATOR ", " 118 #define MAX_LINE_LENGTH 100 119 uint64_t prefix_len = strlen(LINE_PREFIX); 120 uint64_t separator_len = strlen(ENTRY_SEPARATOR); 121 const char *first_entry = "--logflag <flag> enable log flag (all, "; 122 uint64_t curr_line_len; 123 uint64_t curr_entry_len; 124 struct spdk_log_flag *flag; 125 char first_line[MAX_LINE_LENGTH] = {}; 126 127 snprintf(first_line, sizeof(first_line), " %s, %s", log_arg, first_entry); 128 fprintf(f, "%s", first_line); 129 curr_line_len = strlen(first_line); 130 131 TAILQ_FOREACH(flag, &g_log_flags, tailq) { 132 curr_entry_len = strlen(flag->name); 133 if ((curr_line_len + curr_entry_len + separator_len) > MAX_LINE_LENGTH) { 134 fprintf(f, "\n%s", LINE_PREFIX); 135 curr_line_len = prefix_len; 136 } 137 138 fprintf(f, "%s", flag->name); 139 curr_line_len += curr_entry_len; 140 141 if (TAILQ_LAST(&g_log_flags, spdk_log_flag_head) == flag) { 142 break; 143 } 144 145 fprintf(f, "%s", ENTRY_SEPARATOR); 146 curr_line_len += separator_len; 147 } 148 149 fprintf(f, ")\n"); 150 } 151