1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/types.h>
29 #include <sys/varargs.h>
30 #include <sys/cmn_err.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/ib/clients/rds/rdsib_debug.h>
34
35 /*
36 * This file contains the debug defines and routines.
37 * Debugging information is collected in a circular kernel buffer. Debug
38 * messages with level lower than rdsdbglvl are ignored. The size of the
39 * of the debug buffer can be changed by setting 'rds_debug_buf_size' in
40 * bytes in /etc/system.
41 *
42 * The debug buffer can be cleared by setting 'rds_clear_debug_buf_flag = 1'
43 * on a running system.
44 */
45
46 #define RDS_DEBUG_SIZE_EXTRA_ALLOC 8
47 #define RDS_MIN_DEBUG_BUF_SIZE 0x1000
48 #define RDS_FUNCNAME_LEN 40
49 #define RDS_PRINTBUF_LEN 4096
50 #ifdef DEBUG
51 #define RDS_DEBUG_BUF_SIZE 0x10000
52 #else
53 #define RDS_DEBUG_BUF_SIZE 0x2000
54 #endif /* DEBUG */
55
56 /* Max length of a debug statement */
57 #define RDS_PRINT_BUF_LEN 4096
58
59 int rds_suppress_dprintf; /* Suppress debug printing */
60 int rds_buffer_dprintf = 1; /* Use debug buffer (0 == console) */
61 int rds_debug_buf_size = RDS_DEBUG_BUF_SIZE; /* Sz of Debug buf */
62 int rds_allow_intr_msgs = 0; /* log "intr" messages */
63 char *rds_debug_buf = NULL; /* The Debug Buf */
64 char *rds_buf_sptr, *rds_buf_eptr; /* debug buffer temp pointer */
65 int rds_clear_debug_buf_flag = 0; /* Clear debug buffer */
66 extern uint_t rdsdbglvl;
67
68 /*
69 * Print Buffer protected by mutex for debug stuff. The mutex also
70 * ensures serializing debug messages.
71 */
72 static kmutex_t rds_debug_mutex;
73 static char rds_print_buf[RDS_PRINT_BUF_LEN];
74
75 /* Function Prototypes */
76 static void rds_clear_print_buf();
77
78 /* RDS logging init */
79 void
rds_logging_initialization()80 rds_logging_initialization()
81 {
82 boolean_t flag = B_FALSE;
83
84 mutex_init(&rds_debug_mutex, NULL, MUTEX_DRIVER, NULL);
85 mutex_enter(&rds_debug_mutex);
86
87 if (rds_debug_buf_size <= RDS_DEBUG_SIZE_EXTRA_ALLOC) {
88 rds_debug_buf_size = RDS_MIN_DEBUG_BUF_SIZE;
89 flag = B_TRUE;
90 }
91
92 /* if it is less that RDS_MIN_DEBUG_BUF_SIZE, adjust it */
93 rds_debug_buf_size = max(RDS_MIN_DEBUG_BUF_SIZE,
94 rds_debug_buf_size);
95
96 rds_debug_buf = (char *)kmem_alloc(rds_debug_buf_size, KM_SLEEP);
97 rds_clear_print_buf();
98 mutex_exit(&rds_debug_mutex);
99
100 if (flag == B_TRUE) {
101 RDS_DPRINTF2("RDS", "rds_debug_buf_size was too small, "
102 "adjusted to %x", rds_debug_buf_size);
103 }
104 }
105
106
107 /* RDS logging destroy */
108 void
rds_logging_destroy()109 rds_logging_destroy()
110 {
111 mutex_enter(&rds_debug_mutex);
112 if (rds_debug_buf) {
113 kmem_free(rds_debug_buf, rds_debug_buf_size);
114 rds_debug_buf = NULL;
115 }
116 mutex_exit(&rds_debug_mutex);
117 mutex_destroy(&rds_debug_mutex);
118 }
119
120
121 /*
122 * debug, log, and console message handling
123 */
124
125 /*
126 * clear the RDS debug buffer
127 */
128 static void
rds_clear_print_buf()129 rds_clear_print_buf()
130 {
131 ASSERT(MUTEX_HELD(&rds_debug_mutex));
132 if (rds_debug_buf) {
133 rds_buf_sptr = rds_debug_buf;
134 rds_buf_eptr = rds_debug_buf + rds_debug_buf_size -
135 RDS_DEBUG_SIZE_EXTRA_ALLOC;
136
137 bzero(rds_debug_buf, rds_debug_buf_size);
138 }
139 }
140
141
142 static void
rds_vlog(char * name,uint_t level,char * fmt,va_list ap)143 rds_vlog(char *name, uint_t level, char *fmt, va_list ap)
144 {
145 char *label = (name == NULL) ? "rds" : name;
146 char *msg_ptr;
147 size_t len;
148
149 mutex_enter(&rds_debug_mutex);
150
151 /* if not using logging scheme; quit */
152 if (rds_suppress_dprintf || (rds_debug_buf == NULL)) {
153 mutex_exit(&rds_debug_mutex);
154 return;
155 }
156
157 /* If user requests to clear debug buffer, go ahead */
158 if (rds_clear_debug_buf_flag != 0) {
159 rds_clear_print_buf();
160 rds_clear_debug_buf_flag = 0;
161 }
162
163 /*
164 * put "label" into the buffer
165 */
166 len = snprintf(rds_print_buf, RDS_FUNCNAME_LEN, "%s:\t", label);
167
168 msg_ptr = rds_print_buf + len;
169 len += vsnprintf(msg_ptr, RDS_PRINT_BUF_LEN - len - 2, fmt, ap);
170
171 len = min(len, RDS_PRINT_BUF_LEN - 2);
172 ASSERT(len == strlen(rds_print_buf));
173 rds_print_buf[len++] = '\n';
174 rds_print_buf[len] = '\0';
175
176 /*
177 * stuff the message in the debug buf
178 */
179 if (rds_buffer_dprintf) {
180
181 /*
182 * overwrite >>>> that might be over the end of the
183 * the buffer
184 */
185 *rds_buf_sptr = '\0';
186
187 if (rds_buf_sptr + len > rds_buf_eptr) {
188 size_t left = (uintptr_t)rds_buf_eptr -
189 (uintptr_t)rds_buf_sptr;
190
191 bcopy((caddr_t)rds_print_buf,
192 (caddr_t)rds_buf_sptr, left);
193 bcopy((caddr_t)rds_print_buf + left,
194 (caddr_t)rds_debug_buf, len - left);
195 rds_buf_sptr = rds_debug_buf + len - left;
196 } else {
197 bcopy((caddr_t)rds_print_buf, rds_buf_sptr, len);
198 rds_buf_sptr += len;
199 }
200
201 /* add marker */
202 (void) sprintf(rds_buf_sptr, ">>>>");
203 }
204
205 /*
206 * LINTR, L5-L2 message may go to the rds_debug_buf
207 * L1 messages will go to the /var/adm/messages (debug & non-debug).
208 * L0 messages will go to console (debug & non-debug).
209 */
210 switch (level) {
211 case RDS_LOG_LINTR:
212 case RDS_LOG_L5:
213 case RDS_LOG_L4:
214 case RDS_LOG_L3:
215 case RDS_LOG_L2:
216 if (!rds_buffer_dprintf) {
217 cmn_err(CE_CONT, "^%s", rds_print_buf);
218 }
219 break;
220 case RDS_LOG_L1:
221 if (!rds_buffer_dprintf) {
222 cmn_err(CE_CONT, "^%s", rds_print_buf);
223 } else {
224 /* go to messages file */
225 cmn_err(CE_CONT, "!%s", rds_print_buf);
226 }
227 break;
228 case RDS_LOG_L0:
229 /* Strip the "\n" added earlier */
230 if (rds_print_buf[len - 1] == '\n') {
231 rds_print_buf[len - 1] = '\0';
232 }
233 if (msg_ptr[len - 1] == '\n') {
234 msg_ptr[len - 1] = '\0';
235 }
236 /* go to console */
237 cmn_err(CE_CONT, "^%s", rds_print_buf);
238 break;
239 }
240
241 mutex_exit(&rds_debug_mutex);
242 }
243
244 void
rds_dprintf_intr(char * name,char * fmt,...)245 rds_dprintf_intr(char *name, char *fmt, ...)
246 {
247 va_list ap;
248
249 va_start(ap, fmt);
250 rds_vlog(name, RDS_LOG_LINTR, fmt, ap);
251 va_end(ap);
252 }
253
254 /*
255 * Check individual subsystem err levels
256 */
257 #define RDS_CHECK_ERR_LEVEL(level) \
258 if (rdsdbglvl < level) \
259 return; \
260
261 void
rds_dprintf5(char * name,char * fmt,...)262 rds_dprintf5(char *name, char *fmt, ...)
263 {
264 va_list ap;
265
266 RDS_CHECK_ERR_LEVEL(RDS_LOG_L5);
267
268 va_start(ap, fmt);
269 rds_vlog(name, RDS_LOG_L5, fmt, ap);
270 va_end(ap);
271 }
272
273 void
rds_dprintf4(char * name,char * fmt,...)274 rds_dprintf4(char *name, char *fmt, ...)
275 {
276 va_list ap;
277
278 RDS_CHECK_ERR_LEVEL(RDS_LOG_L4);
279
280 va_start(ap, fmt);
281 rds_vlog(name, RDS_LOG_L4, fmt, ap);
282 va_end(ap);
283 }
284
285 void
rds_dprintf3(char * name,char * fmt,...)286 rds_dprintf3(char *name, char *fmt, ...)
287 {
288 va_list ap;
289
290 RDS_CHECK_ERR_LEVEL(RDS_LOG_L3);
291
292 va_start(ap, fmt);
293 rds_vlog(name, RDS_LOG_L3, fmt, ap);
294 va_end(ap);
295 }
296
297 void
rds_dprintf2(char * name,char * fmt,...)298 rds_dprintf2(char *name, char *fmt, ...)
299 {
300 va_list ap;
301
302 RDS_CHECK_ERR_LEVEL(RDS_LOG_L2);
303
304 va_start(ap, fmt);
305 rds_vlog(name, RDS_LOG_L2, fmt, ap);
306 va_end(ap);
307 }
308
309 void
rds_dprintf1(char * name,char * fmt,...)310 rds_dprintf1(char *name, char *fmt, ...)
311 {
312 va_list ap;
313
314 va_start(ap, fmt);
315 rds_vlog(name, RDS_LOG_L1, fmt, ap);
316 va_end(ap);
317 }
318
319
320 /*
321 * Function:
322 * rds_dprintf0
323 * Input:
324 * name - Name of the function generating the debug message
325 * fmt - The message to be displayed.
326 * Output:
327 * none
328 * Returns:
329 * none
330 * Description:
331 * A generic log function to display RDS debug messages.
332 */
333 void
rds_dprintf0(char * name,char * fmt,...)334 rds_dprintf0(char *name, char *fmt, ...)
335 {
336 va_list ap;
337
338 va_start(ap, fmt);
339 rds_vlog(name, RDS_LOG_L0, fmt, ap);
340 va_end(ap);
341 }
342