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