# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 874cc0ff214daac1fec3890e083a6ca36b79dbfa
# Parent 0a3d7dacff4ccce72b42ac791971bee86d70e736
[XEN] Fix deadlock in printk().
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/drivers/char/console.c | 56 ++++++++++++++++++++++++++++-----------------
xen/include/xen/config.h | 2 -
2 files changed, 36 insertions(+), 22 deletions(-)
diff -r 0a3d7dacff4c -r 874cc0ff214d xen/drivers/char/console.c
--- a/xen/drivers/char/console.c Tue Oct 31 18:24:57 2006 +0000
+++ b/xen/drivers/char/console.c Wed Nov 01 09:55:43 2006 +0000
@@ -338,12 +338,14 @@ void printk(const char *fmt, ...)
va_list args;
char *p, *q;
unsigned long flags;
- int level = XENLOG_DEFAULT;
+ int level = -1;
int upper_thresh = xenlog_upper_thresh;
int lower_thresh = xenlog_lower_thresh;
int print_regardless = xen_startup;
- spin_lock_irqsave(&console_lock, flags);
+ /* console_lock can be acquired recursively from __printk_ratelimit(). */
+ local_irq_save(flags);
+ spin_lock_recursive(&console_lock);
va_start(args, fmt);
(void)vsnprintf(buf, sizeof(buf), fmt, args);
@@ -351,22 +353,25 @@ void printk(const char *fmt, ...)
p = buf;
- /* Is this print caused by a guest? */
- if ( strncmp("<G>", p, 3) == 0 )
- {
- upper_thresh = xenlog_guest_upper_thresh;
- lower_thresh = xenlog_guest_lower_thresh;
- level = XENLOG_GUEST_DEFAULT;
+ while ( (p[0] == '<') && (p[1] != '\0') && (p[2] == '>') )
+ {
+ switch ( p[1] )
+ {
+ case 'G':
+ upper_thresh = xenlog_guest_upper_thresh;
+ lower_thresh = xenlog_guest_lower_thresh;
+ if ( level == -1 )
+ level = XENLOG_GUEST_DEFAULT;
+ break;
+ case '0' ... '3':
+ level = p[1] - '0';
+ break;
+ }
p += 3;
}
- if ( (p[0] == '<') &&
- (p[1] >= '0') && (p[1] <= ('0' + XENLOG_MAX)) &&
- (p[2] == '>') )
- {
- level = p[1] - '0';
- p += 3;
- }
+ if ( level == -1 )
+ level = XENLOG_DEFAULT;
if ( !print_regardless )
{
@@ -396,7 +401,8 @@ void printk(const char *fmt, ...)
}
out:
- spin_unlock_irqrestore(&console_lock, flags);
+ spin_unlock_recursive(&console_lock);
+ local_irq_restore(flags);
}
void set_printk_prefix(const char *prefix)
@@ -547,9 +553,20 @@ int __printk_ratelimit(int ratelimit_ms,
int lost = missed;
missed = 0;
toks -= ratelimit_ms;
- spin_unlock_irqrestore(&ratelimit_lock, flags);
+ spin_unlock(&ratelimit_lock);
if ( lost )
- printk("printk: %d messages suppressed.\n", lost);
+ {
+ char lost_str[8];
+ snprintf(lost_str, sizeof(lost_str), "%d", lost);
+ /* console_lock may already be acquired by printk(). */
+ spin_lock_recursive(&console_lock);
+ __putstr(printk_prefix);
+ __putstr("printk: ");
+ __putstr(lost_str);
+ __putstr(" messages suppressed.\n");
+ spin_unlock_recursive(&console_lock);
+ }
+ local_irq_restore(flags);
return 1;
}
missed++;
@@ -565,8 +582,7 @@ int printk_ratelimit_burst = 10;
int printk_ratelimit(void)
{
- return __printk_ratelimit(printk_ratelimit_ms,
- printk_ratelimit_burst);
+ return __printk_ratelimit(printk_ratelimit_ms, printk_ratelimit_burst);
}
/*
diff -r 0a3d7dacff4c -r 874cc0ff214d xen/include/xen/config.h
--- a/xen/include/xen/config.h Tue Oct 31 18:24:57 2006 +0000
+++ b/xen/include/xen/config.h Wed Nov 01 09:55:43 2006 +0000
@@ -47,8 +47,6 @@
#define XENLOG_G_WARNING XENLOG_GUEST XENLOG_WARNING
#define XENLOG_G_INFO XENLOG_GUEST XENLOG_INFO
#define XENLOG_G_DEBUG XENLOG_GUEST XENLOG_DEBUG
-
-#define XENLOG_MAX 3
/*
* Some code is copied directly from Linux.
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|