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