Merge to Fedora kernel-2.6.7-1.492
[linux-2.6.git] / kernel / printk.c
index 3bf268b..32452b3 100644 (file)
@@ -284,6 +284,7 @@ int do_syslog(int type, char __user * buf, int len)
                        error = __put_user(c,buf);
                        buf++;
                        i++;
+                       cond_resched();
                        spin_lock_irq(&logbuf_lock);
                }
                spin_unlock_irq(&logbuf_lock);
@@ -325,6 +326,7 @@ int do_syslog(int type, char __user * buf, int len)
                        c = LOG_BUF(j);
                        spin_unlock_irq(&logbuf_lock);
                        error = __put_user(c,&buf[count-1-i]);
+                       cond_resched();
                        spin_lock_irq(&logbuf_lock);
                }
                spin_unlock_irq(&logbuf_lock);
@@ -340,6 +342,7 @@ int do_syslog(int type, char __user * buf, int len)
                                        error = -EFAULT;
                                        break;
                                }
+                               cond_resched();
                        }
                }
                break;
@@ -380,6 +383,20 @@ asmlinkage long sys_syslog(int type, char __user * buf, int len)
        return do_syslog(type, buf, len);
 }
 
+/*
+ * Netdump special routine. Don't print to global log_buf, just to the
+ * actual console device(s).
+ */
+static void netdump_call_console_drivers(const char *buf, unsigned long len)
+{
+       struct console *con;
+
+       for (con = console_drivers; con; con = con->next) {
+               if ((con->flags & CON_ENABLED) && con->write)
+                       con->write(con, buf, len);
+       }
+}
+
 /*
  * Call the console drivers on a range of log_buf
  */
@@ -529,6 +546,12 @@ asmlinkage int printk(const char *fmt, ...)
        printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
        va_end(args);
 
+       if (unlikely(netdump_mode)) {
+               netdump_call_console_drivers(printk_buf, printed_len);
+               spin_unlock_irqrestore(&logbuf_lock, flags);
+               goto out;
+       }
+
        /*
         * Copy the output into log_buf.  If the caller didn't provide
         * appropriate log level tags, we insert them here
@@ -687,6 +710,47 @@ void console_unblank(void)
 }
 EXPORT_SYMBOL(console_unblank);
 
+/*
+ * Return the console tty driver structure and its associated index
+ */
+struct tty_driver *console_device(int *index)
+{
+       struct console *c;
+       struct tty_driver *driver = NULL;
+
+       acquire_console_sem();
+       for (c = console_drivers; c != NULL; c = c->next) {
+               if (!c->device)
+                       continue;
+               driver = c->device(c, index);
+               if (driver)
+                       break;
+       }
+       release_console_sem();
+       return driver;
+}
+
+/*
+ * Prevent further output on the passed console device so that (for example)
+ * serial drivers can disable console output before suspending a port, and can
+ * re-enable output afterwards.
+ */
+void console_stop(struct console *console)
+{
+       acquire_console_sem();
+       console->flags &= ~CON_ENABLED;
+       release_console_sem();
+}
+EXPORT_SYMBOL(console_stop);
+
+void console_start(struct console *console)
+{
+       acquire_console_sem();
+       console->flags |= CON_ENABLED;
+       release_console_sem();
+}
+EXPORT_SYMBOL(console_start);
+
 /*
  * The console driver calls this routine during kernel initialization
  * to register the console printing procedure with printk() and to