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