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