ia64/xen-unstable
changeset 12067:874cc0ff214d
[XEN] Fix deadlock in printk().
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Wed Nov 01 09:55:43 2006 +0000 (2006-11-01) |
parents | 0a3d7dacff4c |
children | 77e1baf0a567 33e9c88aab02 |
files | xen/drivers/char/console.c xen/include/xen/config.h |
line diff
1.1 --- a/xen/drivers/char/console.c Tue Oct 31 18:24:57 2006 +0000 1.2 +++ b/xen/drivers/char/console.c Wed Nov 01 09:55:43 2006 +0000 1.3 @@ -338,12 +338,14 @@ void printk(const char *fmt, ...) 1.4 va_list args; 1.5 char *p, *q; 1.6 unsigned long flags; 1.7 - int level = XENLOG_DEFAULT; 1.8 + int level = -1; 1.9 int upper_thresh = xenlog_upper_thresh; 1.10 int lower_thresh = xenlog_lower_thresh; 1.11 int print_regardless = xen_startup; 1.12 1.13 - spin_lock_irqsave(&console_lock, flags); 1.14 + /* console_lock can be acquired recursively from __printk_ratelimit(). */ 1.15 + local_irq_save(flags); 1.16 + spin_lock_recursive(&console_lock); 1.17 1.18 va_start(args, fmt); 1.19 (void)vsnprintf(buf, sizeof(buf), fmt, args); 1.20 @@ -351,22 +353,25 @@ void printk(const char *fmt, ...) 1.21 1.22 p = buf; 1.23 1.24 - /* Is this print caused by a guest? */ 1.25 - if ( strncmp("<G>", p, 3) == 0 ) 1.26 + while ( (p[0] == '<') && (p[1] != '\0') && (p[2] == '>') ) 1.27 { 1.28 - upper_thresh = xenlog_guest_upper_thresh; 1.29 - lower_thresh = xenlog_guest_lower_thresh; 1.30 - level = XENLOG_GUEST_DEFAULT; 1.31 + switch ( p[1] ) 1.32 + { 1.33 + case 'G': 1.34 + upper_thresh = xenlog_guest_upper_thresh; 1.35 + lower_thresh = xenlog_guest_lower_thresh; 1.36 + if ( level == -1 ) 1.37 + level = XENLOG_GUEST_DEFAULT; 1.38 + break; 1.39 + case '0' ... '3': 1.40 + level = p[1] - '0'; 1.41 + break; 1.42 + } 1.43 p += 3; 1.44 } 1.45 1.46 - if ( (p[0] == '<') && 1.47 - (p[1] >= '0') && (p[1] <= ('0' + XENLOG_MAX)) && 1.48 - (p[2] == '>') ) 1.49 - { 1.50 - level = p[1] - '0'; 1.51 - p += 3; 1.52 - } 1.53 + if ( level == -1 ) 1.54 + level = XENLOG_DEFAULT; 1.55 1.56 if ( !print_regardless ) 1.57 { 1.58 @@ -396,7 +401,8 @@ void printk(const char *fmt, ...) 1.59 } 1.60 1.61 out: 1.62 - spin_unlock_irqrestore(&console_lock, flags); 1.63 + spin_unlock_recursive(&console_lock); 1.64 + local_irq_restore(flags); 1.65 } 1.66 1.67 void set_printk_prefix(const char *prefix) 1.68 @@ -547,9 +553,20 @@ int __printk_ratelimit(int ratelimit_ms, 1.69 int lost = missed; 1.70 missed = 0; 1.71 toks -= ratelimit_ms; 1.72 - spin_unlock_irqrestore(&ratelimit_lock, flags); 1.73 + spin_unlock(&ratelimit_lock); 1.74 if ( lost ) 1.75 - printk("printk: %d messages suppressed.\n", lost); 1.76 + { 1.77 + char lost_str[8]; 1.78 + snprintf(lost_str, sizeof(lost_str), "%d", lost); 1.79 + /* console_lock may already be acquired by printk(). */ 1.80 + spin_lock_recursive(&console_lock); 1.81 + __putstr(printk_prefix); 1.82 + __putstr("printk: "); 1.83 + __putstr(lost_str); 1.84 + __putstr(" messages suppressed.\n"); 1.85 + spin_unlock_recursive(&console_lock); 1.86 + } 1.87 + local_irq_restore(flags); 1.88 return 1; 1.89 } 1.90 missed++; 1.91 @@ -565,8 +582,7 @@ int printk_ratelimit_burst = 10; 1.92 1.93 int printk_ratelimit(void) 1.94 { 1.95 - return __printk_ratelimit(printk_ratelimit_ms, 1.96 - printk_ratelimit_burst); 1.97 + return __printk_ratelimit(printk_ratelimit_ms, printk_ratelimit_burst); 1.98 } 1.99 1.100 /*
2.1 --- a/xen/include/xen/config.h Tue Oct 31 18:24:57 2006 +0000 2.2 +++ b/xen/include/xen/config.h Wed Nov 01 09:55:43 2006 +0000 2.3 @@ -48,8 +48,6 @@ 2.4 #define XENLOG_G_INFO XENLOG_GUEST XENLOG_INFO 2.5 #define XENLOG_G_DEBUG XENLOG_GUEST XENLOG_DEBUG 2.6 2.7 -#define XENLOG_MAX 3 2.8 - 2.9 /* 2.10 * Some code is copied directly from Linux. 2.11 * Match some of the Linux log levels to Xen.