[PATCH] Wrong printk return value

From: Guillaume Chazarain
Date: Wed Aug 03 2005 - 04:37:05 EST


What's the true meaning of the printk return value?
Should it include the prioty prefix length of 3? and what about the timing
information? In both cases it was broken:

strace -e write echo 1 > /dev/kmsg
=> write(1, "1\n", 2) = 5

strace -e write echo "<1>1" > /dev/kmsg
=> write(1, "<1>1\n", 5) = 8

The returned length was "length of input string + 3", I made it "length
of printed string including any prefix".

Successful printk calls can have a return value different than the input
length (priority prefix, timing), so /bin/echo will still think there is an error.
So, to avoid breaking programs that assume write(buff, len) != len is an
error, /dev/kmsg should return the buffer length when the call succeeds.

The only drawback is that now it's no more possible to use /dev/kmsg to
check the printk return value :-(

--
Guillaume

--- linux-2.6.13-rc5/kernel/printk.c
+++ linux-2.6.13-rc5/kernel/printk.c
@@ -553,7 +553,7 @@
p[1] <= '7' && p[2] == '>') {
loglev_char = p[1];
p += 3;
- printed_len += 3;
+ printed_len -= 3;
} else {
loglev_char = default_message_loglevel
+ '0';
@@ -568,7 +568,7 @@

for (tp = tbuf; tp < tbuf + tlen; tp++)
emit_log_char(*tp);
- printed_len += tlen - 3;
+ printed_len += tlen;
} else {
if (p[0] != '<' || p[1] < '0' ||
p[1] > '7' || p[2] != '>') {
@@ -576,8 +576,8 @@
emit_log_char(default_message_loglevel
+ '0');
emit_log_char('>');
+ printed_len += 3;
}
- printed_len += 3;
}
log_level_unknown = 0;
if (!*p)
--- linux-2.6.13-rc5/drivers/char/mem.c
+++ linux-2.6.13-rc5/drivers/char/mem.c
@@ -819,7 +819,7 @@ static ssize_t kmsg_write(struct file *
size_t count, loff_t *ppos)
{
char *tmp;
- int ret;
+ ssize_t ret;

tmp = kmalloc(count + 1, GFP_KERNEL);
if (tmp == NULL)
@@ -828,6 +828,9 @@ static ssize_t kmsg_write(struct file *
if (!copy_from_user(tmp, buf, count)) {
tmp[count] = 0;
ret = printk("%s", tmp);
+ if (ret > count)
+ /* printk can add a prefix */
+ ret = count;
}
kfree(tmp);
return ret;