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 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 /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 244void 245rds_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 261void 262rds_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 273void 274rds_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 285void 286rds_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 297void 298rds_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 309void 310rds_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 */ 333void 334rds_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