[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEN] Fix deadlock in printk().



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.