[RFC PATCH] printk: Enable/disable buffering and add printk_flush()

From: Joe Perches
Date: Thu Jun 21 2012 - 16:01:39 EST


Add functions to enable/disable printk buffering.
Add a function to force any buffered output to be emitted.

printk_flush() also emits "printk_flush\n" at KERN_DEFAULT.

---

Perhaps something like this instead of just the one printk_flush()?
Doesn't require any additional KERN_LEVEL '<f>' addition.

Compiled but completely untested...

include/linux/printk.h | 18 ++++++++++++++++++
kernel/printk.c | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/include/linux/printk.h b/include/linux/printk.h
index 1bec2f7..165b6a2 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -111,6 +111,11 @@ asmlinkage int printk_emit(int facility, int level,
asmlinkage __printf(1, 2) __cold
int printk(const char *fmt, ...);

+bool printk_set_buffering(bool enable);
+bool printk_get_buffering(void);
+void printk_flush(void); /* forcibly emit any internal buffers */
+
+
/*
* Special printk facility for scheduler use only, _DO_NOT_USE_ !
*/
@@ -143,6 +148,17 @@ int printk(const char *s, ...)
{
return 0;
}
+static bool printk_set_buffering(bool enable)
+{
+ return false;
+}
+bool printk_get_buffering(void)
+{
+ return false;
+}
+static inline void printk_flush(void)
+{
+}
static inline __printf(1, 2) __cold
int printk_sched(const char *s, ...)
{
@@ -191,6 +207,8 @@ extern void dump_stack(void) __cold;
#define pr_cont(fmt, ...) \
printk(KERN_CONT fmt, ##__VA_ARGS__)

+#define pr_flush printk_flush
+
/* pr_devel() should produce zero code unless DEBUG is defined */
#ifdef DEBUG
#define pr_devel(fmt, ...) \
diff --git a/kernel/printk.c b/kernel/printk.c
index a2276b9..0e35931 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1144,6 +1144,23 @@ module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ignore_loglevel, "ignore loglevel setting, to"
"print all kernel messages to the console.");

+atomic_t printk_buffering = ATOMIC_INIT(1);
+
+bool printk_set_buffering(bool enable)
+{
+ if (enable)
+ return atomic_inc_and_test(&printk_buffering);
+
+ return atomic_dec_and_test(&printk_buffering);
+}
+EXPORT_SYMBOL(printk_set_buffering);
+
+bool printk_get_buffering(void)
+{
+ return atomic_read(&printk_buffering);
+}
+EXPORT_SYMBOL(printk_get_buffering);
+
/*
* Call the console drivers, asking them to write out
* log_buf[start] to log_buf[end - 1].
@@ -1288,6 +1305,7 @@ asmlinkage int vprintk_emit(int facility, int level,
int this_cpu;
bool newline = false;
bool prefix = false;
+ bool buffered = atomic_read(&printk_buffering);
int printed_len = 0;

boot_delay_msec();
@@ -1355,8 +1373,16 @@ asmlinkage int vprintk_emit(int facility, int level,
}
}

- if (level == -1)
+ switch (level) {
+ case -1:
level = default_message_loglevel;
+ break;
+ case -2:
+ prefix = true;
+ level = default_message_loglevel;
+ buffered = false;
+ break;
+ }

if (dict) {
prefix = true;
@@ -1364,7 +1390,7 @@ asmlinkage int vprintk_emit(int facility, int level,
}

if (!newline) {
- if (cont_len && (prefix || cont_task != current)) {
+ if (cont_len && (prefix || cont_task != current || !buffered)) {
/*
* Flush earlier buffer, which is either from a
* different thread, or when we got a new prefix.
@@ -1454,6 +1480,12 @@ asmlinkage int printk_emit(int facility, int level,
}
EXPORT_SYMBOL(printk_emit);

+void printk_flush(void)
+{
+ printk_emit(0, -2, NULL, 0, "printk_flush\n");
+}
+EXPORT_SYMBOL(printk_flush);
+
/**
* printk - print a kernel message
* @fmt: format string


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/