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 59 int rds_suppress_dprintf; /* Suppress debug printing */ 60 int rds_buffer_dprintf = 1; /* Use debug buffer (0 == console) */ 61 int rds_debug_buf_size = RDS_DEBUG_BUF_SIZE; /* Sz of Debug buf */ 62 int rds_allow_intr_msgs = 0; /* log "intr" messages */ 63 char *rds_debug_buf = NULL; /* The Debug Buf */ 64 char *rds_buf_sptr, *rds_buf_eptr; /* debug buffer temp pointer */ 65 int rds_clear_debug_buf_flag = 0; /* Clear debug buffer */ 66 extern uint_t rdsdbglvl; 67 68 /* 69 * Print Buffer protected by mutex for debug stuff. The mutex also 70 * ensures serializing debug messages. 71 */ 72 static kmutex_t rds_debug_mutex; 73 static char rds_print_buf[RDS_PRINT_BUF_LEN]; 74 75 /* Function Prototypes */ 76 static void rds_clear_print_buf(); 77 78 /* RDS logging init */ 79 void 80 rds_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 */ 108 void 109 rds_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 */ 128 static void 129 rds_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 142 static void 143 rds_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 250 void 251 rds_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 267 void 268 rds_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 279 void 280 rds_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 291 void 292 rds_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 303 void 304 rds_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 315 void 316 rds_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 */ 339 void 340 rds_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