rdsib_debug.c revision 3302:e75a684d1697
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 2006 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
59int	rds_suppress_dprintf;		/* Suppress debug printing */
60int	rds_buffer_dprintf = 1;		/* Use debug buffer (0 == console) */
61int	rds_debug_buf_size = RDS_DEBUG_BUF_SIZE; /* Sz of Debug buf */
62int	rds_allow_intr_msgs = 0;	/* log "intr" messages */
63char	*rds_debug_buf = NULL;		/* The Debug Buf */
64char	*rds_buf_sptr, *rds_buf_eptr;	/* debug buffer temp pointer */
65int	rds_clear_debug_buf_flag = 0;	/* Clear debug buffer */
66extern uint_t	rdsdbglvl;
67
68/*
69 * Print Buffer protected by mutex for debug stuff. The mutex also
70 * ensures serializing debug messages.
71 */
72static kmutex_t	rds_debug_mutex;
73static char	rds_print_buf[RDS_PRINT_BUF_LEN];
74
75/* Function Prototypes */
76static void	rds_clear_print_buf();
77
78/* RDS logging init */
79void
80rds_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 */
108void
109rds_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 */
128static void
129rds_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
142static void
143rds_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 log buf in non-debug kernels and
208	 * to console and log buf in debug kernels
209	 * L0 messages are warnings and will go to msgbuf in non-debug kernels
210	 * and to console and log buf in debug kernels
211	 */
212	switch (level) {
213	case RDS_LOG_LINTR:
214	case RDS_LOG_L5:
215	case RDS_LOG_L4:
216	case RDS_LOG_L3:
217	case RDS_LOG_L2:
218		if (!rds_buffer_dprintf) {
219			cmn_err(CE_CONT, "^%s", rds_print_buf);
220		}
221		break;
222	case RDS_LOG_L1:
223#ifdef DEBUG
224		cmn_err(CE_CONT, "%s", rds_print_buf);
225#else
226		if (!rds_buffer_dprintf) {
227			cmn_err(CE_CONT, "^%s", rds_print_buf);
228		}
229#endif
230		break;
231	case RDS_LOG_L0:
232		/* Strip the "\n" added earlier */
233		if (rds_print_buf[len - 1] == '\n') {
234			rds_print_buf[len - 1] = '\0';
235		}
236		if (msg_ptr[len - 1] == '\n') {
237			msg_ptr[len - 1] = '\0';
238		}
239#ifdef DEBUG
240		cmn_err(CE_CONT, rds_print_buf);
241#else
242		cmn_err(CE_CONT, "!%s", rds_print_buf);
243#endif
244		break;
245	}
246
247	mutex_exit(&rds_debug_mutex);
248}
249
250void
251rds_dprintf_intr(char *name, char *fmt, ...)
252{
253	va_list ap;
254
255	va_start(ap, fmt);
256	rds_vlog(name, RDS_LOG_LINTR, fmt, ap);
257	va_end(ap);
258}
259
260/*
261 * Check individual subsystem err levels
262 */
263#define	RDS_CHECK_ERR_LEVEL(level)		\
264	if (rdsdbglvl < level)			\
265		return;				\
266
267void
268rds_dprintf5(char *name, char *fmt, ...)
269{
270	va_list ap;
271
272	RDS_CHECK_ERR_LEVEL(RDS_LOG_L5);
273
274	va_start(ap, fmt);
275	rds_vlog(name, RDS_LOG_L5, fmt, ap);
276	va_end(ap);
277}
278
279void
280rds_dprintf4(char *name, char *fmt, ...)
281{
282	va_list ap;
283
284	RDS_CHECK_ERR_LEVEL(RDS_LOG_L4);
285
286	va_start(ap, fmt);
287	rds_vlog(name, RDS_LOG_L4, fmt, ap);
288	va_end(ap);
289}
290
291void
292rds_dprintf3(char *name, char *fmt, ...)
293{
294	va_list ap;
295
296	RDS_CHECK_ERR_LEVEL(RDS_LOG_L3);
297
298	va_start(ap, fmt);
299	rds_vlog(name, RDS_LOG_L3, fmt, ap);
300	va_end(ap);
301}
302
303void
304rds_dprintf2(char *name, char *fmt, ...)
305{
306	va_list ap;
307
308	RDS_CHECK_ERR_LEVEL(RDS_LOG_L2);
309
310	va_start(ap, fmt);
311	rds_vlog(name, RDS_LOG_L2, fmt, ap);
312	va_end(ap);
313}
314
315void
316rds_dprintf1(char *name, char *fmt, ...)
317{
318	va_list ap;
319
320	va_start(ap, fmt);
321	rds_vlog(name, RDS_LOG_L1, fmt, ap);
322	va_end(ap);
323}
324
325
326/*
327 * Function:
328 *      rds_dprintf0
329 * Input:
330 *      name	- Name of the function generating the debug message
331 *  	fmt	- The message to be displayed.
332 * Output:
333 *      none
334 * Returns:
335 *      none
336 * Description:
337 *  	A generic log function to display RDS debug messages.
338 */
339void
340rds_dprintf0(char *name, char *fmt, ...)
341{
342	va_list ap;
343
344	va_start(ap, fmt);
345	rds_vlog(name, RDS_LOG_L0, fmt, ap);
346	va_end(ap);
347}
348