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 *
get_log_flag(const char * name)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
spdk_log_register_flag(const char * name,struct spdk_log_flag * flag)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
spdk_log_get_flag(const char * name)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
log_set_flag(const char * name,bool value)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
spdk_log_set_flag(const char * name)90 spdk_log_set_flag(const char *name)
91 {
92 return log_set_flag(name, true);
93 }
94
95 int
spdk_log_clear_flag(const char * name)96 spdk_log_clear_flag(const char *name)
97 {
98 return log_set_flag(name, false);
99 }
100
101 struct spdk_log_flag *
spdk_log_get_first_flag(void)102 spdk_log_get_first_flag(void)
103 {
104 return TAILQ_FIRST(&g_log_flags);
105 }
106
107 struct spdk_log_flag *
spdk_log_get_next_flag(struct spdk_log_flag * flag)108 spdk_log_get_next_flag(struct spdk_log_flag *flag)
109 {
110 return TAILQ_NEXT(flag, tailq);
111 }
112
113 void
spdk_log_usage(FILE * f,const char * log_arg)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