ia64/xen-unstable

changeset 12067:874cc0ff214d

[XEN] Fix deadlock in printk().
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.