Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 311791
b: refs/heads/master
c: 5becfb1
h: refs/heads/master
i:
  311789: 2b744ff
  311787: 81cd720
  311783: f5037ba
  311775: c785cf4
v: v3
  • Loading branch information
Kay Sievers authored and Greg Kroah-Hartman committed Jul 9, 2012
1 parent a15bcd8 commit a67d905
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 43 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eb02dac93708f581c99858a19162af8ca2b6bfcb
refs/heads/master: 5becfb1df5ac8e491338e64b1029685ccad4b39c
120 changes: 78 additions & 42 deletions trunk/kernel/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,10 @@ static int console_may_schedule;
*/

enum log_flags {
LOG_DEFAULT = 0,
LOG_NOCONS = 1, /* already flushed, do not print to console */
LOG_NOCONS = 1, /* already flushed, do not print to console */
LOG_NEWLINE = 2, /* text ended with a newline */
LOG_PREFIX = 4, /* text started with a prefix */
LOG_CONT = 8, /* text is a fragment of a continuation line */
};

struct log {
Expand All @@ -217,6 +219,7 @@ static DEFINE_RAW_SPINLOCK(logbuf_lock);
/* the next printk record to read by syslog(READ) or /proc/kmsg */
static u64 syslog_seq;
static u32 syslog_idx;
static enum log_flags syslog_prev;
static size_t syslog_partial;

/* index and sequence number of the first record stored in the buffer */
Expand Down Expand Up @@ -839,13 +842,26 @@ static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
return len;
}

static size_t msg_print_text(const struct log *msg, bool syslog,
char *buf, size_t size)
static size_t msg_print_text(const struct log *msg, enum log_flags prev,
bool syslog, char *buf, size_t size)
{
const char *text = log_text(msg);
size_t text_size = msg->text_len;
bool prefix = true;
bool newline = true;
size_t len = 0;

if ((prev & LOG_CONT) && !(msg->flags & LOG_PREFIX))
prefix = false;

if (msg->flags & LOG_CONT) {
if ((prev & LOG_CONT) && !(prev & LOG_NEWLINE))
prefix = false;

if (!(msg->flags & LOG_NEWLINE))
newline = false;
}

do {
const char *next = memchr(text, '\n', text_size);
size_t text_len;
Expand All @@ -863,16 +879,22 @@ static size_t msg_print_text(const struct log *msg, bool syslog,
text_len + 1>= size - len)
break;

len += print_prefix(msg, syslog, buf + len);
if (prefix)
len += print_prefix(msg, syslog, buf + len);
memcpy(buf + len, text, text_len);
len += text_len;
buf[len++] = '\n';
if (next || newline)
buf[len++] = '\n';
} else {
/* SYSLOG_ACTION_* buffer size only calculation */
len += print_prefix(msg, syslog, NULL);
len += text_len + 1;
if (prefix)
len += print_prefix(msg, syslog, NULL);
len += text_len;
if (next || newline)
len++;
}

prefix = true;
text = next;
} while (text);

Expand All @@ -898,6 +920,7 @@ static int syslog_print(char __user *buf, int size)
/* messages are gone, move to first one */
syslog_seq = log_first_seq;
syslog_idx = log_first_idx;
syslog_prev = 0;
syslog_partial = 0;
}
if (syslog_seq == log_next_seq) {
Expand All @@ -907,11 +930,12 @@ static int syslog_print(char __user *buf, int size)

skip = syslog_partial;
msg = log_from_idx(syslog_idx);
n = msg_print_text(msg, true, text, LOG_LINE_MAX);
n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX);
if (n - syslog_partial <= size) {
/* message fits into buffer, move forward */
syslog_idx = log_next(syslog_idx);
syslog_seq++;
syslog_prev = msg->flags;
n -= syslog_partial;
syslog_partial = 0;
} else if (!len){
Expand Down Expand Up @@ -954,6 +978,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
u64 next_seq;
u64 seq;
u32 idx;
enum log_flags prev;

if (clear_seq < log_first_seq) {
/* messages are gone, move to first available one */
Expand All @@ -967,21 +992,23 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
*/
seq = clear_seq;
idx = clear_idx;
prev = 0;
while (seq < log_next_seq) {
struct log *msg = log_from_idx(idx);

len += msg_print_text(msg, true, NULL, 0);
len += msg_print_text(msg, prev, true, NULL, 0);
idx = log_next(idx);
seq++;
}

/* move first record forward until length fits into the buffer */
seq = clear_seq;
idx = clear_idx;
prev = 0;
while (len > size && seq < log_next_seq) {
struct log *msg = log_from_idx(idx);

len -= msg_print_text(msg, true, NULL, 0);
len -= msg_print_text(msg, prev, true, NULL, 0);
idx = log_next(idx);
seq++;
}
Expand All @@ -990,17 +1017,19 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
next_seq = log_next_seq;

len = 0;
prev = 0;
while (len >= 0 && seq < next_seq) {
struct log *msg = log_from_idx(idx);
int textlen;

textlen = msg_print_text(msg, true, text, LOG_LINE_MAX);
textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX);
if (textlen < 0) {
len = textlen;
break;
}
idx = log_next(idx);
seq++;
prev = msg->flags;

raw_spin_unlock_irq(&logbuf_lock);
if (copy_to_user(buf + len, text, textlen))
Expand All @@ -1013,6 +1042,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
/* messages are gone, move to next one */
seq = log_first_seq;
idx = log_first_idx;
prev = 0;
}
}
}
Expand Down Expand Up @@ -1117,6 +1147,7 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
/* messages are gone, move to first one */
syslog_seq = log_first_seq;
syslog_idx = log_first_idx;
syslog_prev = 0;
syslog_partial = 0;
}
if (from_file) {
Expand All @@ -1127,18 +1158,18 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
*/
error = log_next_idx - syslog_idx;
} else {
u64 seq;
u32 idx;
u64 seq = syslog_seq;
u32 idx = syslog_idx;
enum log_flags prev = syslog_prev;

error = 0;
seq = syslog_seq;
idx = syslog_idx;
while (seq < log_next_seq) {
struct log *msg = log_from_idx(idx);

error += msg_print_text(msg, true, NULL, 0);
error += msg_print_text(msg, prev, true, NULL, 0);
idx = log_next(idx);
seq++;
prev = msg->flags;
}
error -= syslog_partial;
}
Expand Down Expand Up @@ -1408,10 +1439,9 @@ asmlinkage int vprintk_emit(int facility, int level,
static char textbuf[LOG_LINE_MAX];
char *text = textbuf;
size_t text_len;
enum log_flags lflags = 0;
unsigned long flags;
int this_cpu;
bool newline = false;
bool prefix = false;
int printed_len = 0;

boot_delay_msec();
Expand Down Expand Up @@ -1450,7 +1480,7 @@ asmlinkage int vprintk_emit(int facility, int level,
recursion_bug = 0;
printed_len += strlen(recursion_msg);
/* emit KERN_CRIT message */
log_store(0, 2, LOG_DEFAULT, 0,
log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0,
NULL, 0, recursion_msg, printed_len);
}

Expand All @@ -1463,7 +1493,7 @@ asmlinkage int vprintk_emit(int facility, int level,
/* mark and strip a trailing newline */
if (text_len && text[text_len-1] == '\n') {
text_len--;
newline = true;
lflags |= LOG_NEWLINE;
}

/* strip syslog prefix and extract log level or control flags */
Expand All @@ -1473,7 +1503,7 @@ asmlinkage int vprintk_emit(int facility, int level,
if (level == -1)
level = text[1] - '0';
case 'd': /* KERN_DEFAULT */
prefix = true;
lflags |= LOG_PREFIX;
case 'c': /* KERN_CONT */
text += 3;
text_len -= 3;
Expand All @@ -1483,22 +1513,20 @@ asmlinkage int vprintk_emit(int facility, int level,
if (level == -1)
level = default_message_loglevel;

if (dict) {
prefix = true;
newline = true;
}
if (dict)
lflags |= LOG_PREFIX|LOG_NEWLINE;

if (!newline) {
if (!(lflags & LOG_NEWLINE)) {
/*
* Flush the conflicting buffer. An earlier newline was missing,
* or another task also prints continuation lines.
*/
if (cont.len && (prefix || cont.owner != current))
if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
cont_flush();

/* buffer line if possible, otherwise store it right away */
if (!cont_add(facility, level, text, text_len))
log_store(facility, level, LOG_DEFAULT, 0,
log_store(facility, level, lflags | LOG_CONT, 0,
dict, dictlen, text, text_len);
} else {
bool stored = false;
Expand All @@ -1510,13 +1538,13 @@ asmlinkage int vprintk_emit(int facility, int level,
* flush it out and store this line separately.
*/
if (cont.len && cont.owner == current) {
if (!prefix)
if (!(lflags & LOG_PREFIX))
stored = cont_add(facility, level, text, text_len);
cont_flush();
}

if (!stored)
log_store(facility, level, LOG_DEFAULT, 0,
log_store(facility, level, lflags, 0,
dict, dictlen, text, text_len);
}
printed_len += text_len;
Expand Down Expand Up @@ -1615,8 +1643,8 @@ static struct cont {
static struct log *log_from_idx(u32 idx) { return NULL; }
static u32 log_next(u32 idx) { return 0; }
static void call_console_drivers(int level, const char *text, size_t len) {}
static size_t msg_print_text(const struct log *msg, bool syslog,
char *buf, size_t size) { return 0; }
static size_t msg_print_text(const struct log *msg, enum log_flags prev,
bool syslog, char *buf, size_t size) { return 0; }
static size_t cont_print_text(char *text, size_t size) { return 0; }

#endif /* CONFIG_PRINTK */
Expand Down Expand Up @@ -1892,6 +1920,7 @@ void wake_up_klogd(void)
/* the next printk record to write to the console */
static u64 console_seq;
static u32 console_idx;
static enum log_flags console_prev;

/**
* console_unlock - unlock the console system
Expand Down Expand Up @@ -1952,6 +1981,7 @@ void console_unlock(void)
/* messages are gone, move to first one */
console_seq = log_first_seq;
console_idx = log_first_idx;
console_prev = 0;
}
skip:
if (console_seq == log_next_seq)
Expand All @@ -1975,10 +2005,11 @@ void console_unlock(void)
}

level = msg->level;
len = msg_print_text(msg, false, text, sizeof(text));

len = msg_print_text(msg, console_prev, false,
text, sizeof(text));
console_idx = log_next(console_idx);
console_seq++;
console_prev = msg->flags;
raw_spin_unlock(&logbuf_lock);

stop_critical_timings(); /* don't trace print latency */
Expand Down Expand Up @@ -2241,6 +2272,7 @@ void register_console(struct console *newcon)
raw_spin_lock_irqsave(&logbuf_lock, flags);
console_seq = syslog_seq;
console_idx = syslog_idx;
console_prev = syslog_prev;
raw_spin_unlock_irqrestore(&logbuf_lock, flags);
/*
* We're about to replay the log buffer. Only do this to the
Expand Down Expand Up @@ -2534,8 +2566,7 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
}

msg = log_from_idx(dumper->cur_idx);
l = msg_print_text(msg, syslog,
line, size);
l = msg_print_text(msg, 0, syslog, line, size);

dumper->cur_idx = log_next(dumper->cur_idx);
dumper->cur_seq++;
Expand Down Expand Up @@ -2575,6 +2606,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
u32 idx;
u64 next_seq;
u32 next_idx;
enum log_flags prev;
size_t l = 0;
bool ret = false;

Expand All @@ -2597,38 +2629,42 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
/* calculate length of entire buffer */
seq = dumper->cur_seq;
idx = dumper->cur_idx;
prev = 0;
while (seq < dumper->next_seq) {
struct log *msg = log_from_idx(idx);

l += msg_print_text(msg, true, NULL, 0);
l += msg_print_text(msg, prev, true, NULL, 0);
idx = log_next(idx);
seq++;
prev = msg->flags;
}

/* move first record forward until length fits into the buffer */
seq = dumper->cur_seq;
idx = dumper->cur_idx;
prev = 0;
while (l > size && seq < dumper->next_seq) {
struct log *msg = log_from_idx(idx);

l -= msg_print_text(msg, true, NULL, 0);
l -= msg_print_text(msg, prev, true, NULL, 0);
idx = log_next(idx);
seq++;
prev = msg->flags;
}

/* last message in next interation */
next_seq = seq;
next_idx = idx;

l = 0;
prev = 0;
while (seq < dumper->next_seq) {
struct log *msg = log_from_idx(idx);

l += msg_print_text(msg, syslog,
buf + l, size - l);

l += msg_print_text(msg, prev, syslog, buf + l, size - l);
idx = log_next(idx);
seq++;
prev = msg->flags;
}

dumper->next_seq = next_seq;
Expand Down

0 comments on commit a67d905

Please sign in to comment.