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