|
|
|
|
@@ -366,7 +366,6 @@ static int current_cpu;
|
|
|
|
|
/* 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 */
|
|
|
|
|
@@ -380,7 +379,6 @@ static u32 log_next_idx;
|
|
|
|
|
/* the next printk record to write to the console */
|
|
|
|
|
static u64 console_seq;
|
|
|
|
|
static u32 console_idx;
|
|
|
|
|
static enum log_flags console_prev;
|
|
|
|
|
|
|
|
|
|
/* the next printk record to read after the last 'clear' command */
|
|
|
|
|
static u64 clear_seq;
|
|
|
|
|
@@ -651,27 +649,15 @@ static void append_char(char **pp, char *e, char c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ssize_t msg_print_ext_header(char *buf, size_t size,
|
|
|
|
|
struct printk_log *msg, u64 seq,
|
|
|
|
|
enum log_flags prev_flags)
|
|
|
|
|
struct printk_log *msg, u64 seq)
|
|
|
|
|
{
|
|
|
|
|
u64 ts_usec = msg->ts_nsec;
|
|
|
|
|
char cont = '-';
|
|
|
|
|
|
|
|
|
|
do_div(ts_usec, 1000);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we couldn't merge continuation line fragments during the print,
|
|
|
|
|
* export the stored flags to allow an optional external merge of the
|
|
|
|
|
* records. Merging the records isn't always neccessarily correct, like
|
|
|
|
|
* when we hit a race during printing. In most cases though, it produces
|
|
|
|
|
* better readable output. 'c' in the record flags mark the first
|
|
|
|
|
* fragment of a line, '+' the following.
|
|
|
|
|
*/
|
|
|
|
|
if (msg->flags & LOG_CONT)
|
|
|
|
|
cont = (prev_flags & LOG_CONT) ? '+' : 'c';
|
|
|
|
|
|
|
|
|
|
return scnprintf(buf, size, "%u,%llu,%llu,%c;",
|
|
|
|
|
(msg->facility << 3) | msg->level, seq, ts_usec, cont);
|
|
|
|
|
(msg->facility << 3) | msg->level, seq, ts_usec,
|
|
|
|
|
msg->flags & LOG_CONT ? 'c' : '-');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ssize_t msg_print_ext_body(char *buf, size_t size,
|
|
|
|
|
@@ -726,7 +712,6 @@ static ssize_t msg_print_ext_body(char *buf, size_t size,
|
|
|
|
|
struct devkmsg_user {
|
|
|
|
|
u64 seq;
|
|
|
|
|
u32 idx;
|
|
|
|
|
enum log_flags prev;
|
|
|
|
|
struct ratelimit_state rs;
|
|
|
|
|
struct mutex lock;
|
|
|
|
|
char buf[CONSOLE_EXT_LOG_MAX];
|
|
|
|
|
@@ -836,12 +821,11 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
|
|
|
|
|
|
|
|
|
|
msg = log_from_idx(user->idx);
|
|
|
|
|
len = msg_print_ext_header(user->buf, sizeof(user->buf),
|
|
|
|
|
msg, user->seq, user->prev);
|
|
|
|
|
msg, user->seq);
|
|
|
|
|
len += msg_print_ext_body(user->buf + len, sizeof(user->buf) - len,
|
|
|
|
|
log_dict(msg), msg->dict_len,
|
|
|
|
|
log_text(msg), msg->text_len);
|
|
|
|
|
|
|
|
|
|
user->prev = msg->flags;
|
|
|
|
|
user->idx = log_next(user->idx);
|
|
|
|
|
user->seq++;
|
|
|
|
|
raw_spin_unlock_irq(&logbuf_lock);
|
|
|
|
|
@@ -1238,26 +1222,12 @@ static size_t print_prefix(const struct printk_log *msg, bool syslog, char *buf)
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev,
|
|
|
|
|
bool syslog, char *buf, size_t size)
|
|
|
|
|
static size_t msg_print_text(const struct printk_log *msg, 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;
|
|
|
|
|
@@ -1275,22 +1245,17 @@ static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev,
|
|
|
|
|
text_len + 1 >= size - len)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (prefix)
|
|
|
|
|
len += print_prefix(msg, syslog, buf + len);
|
|
|
|
|
len += print_prefix(msg, syslog, buf + len);
|
|
|
|
|
memcpy(buf + len, text, text_len);
|
|
|
|
|
len += text_len;
|
|
|
|
|
if (next || newline)
|
|
|
|
|
buf[len++] = '\n';
|
|
|
|
|
buf[len++] = '\n';
|
|
|
|
|
} else {
|
|
|
|
|
/* SYSLOG_ACTION_* buffer size only calculation */
|
|
|
|
|
if (prefix)
|
|
|
|
|
len += print_prefix(msg, syslog, NULL);
|
|
|
|
|
len += print_prefix(msg, syslog, NULL);
|
|
|
|
|
len += text_len;
|
|
|
|
|
if (next || newline)
|
|
|
|
|
len++;
|
|
|
|
|
len++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prefix = true;
|
|
|
|
|
text = next;
|
|
|
|
|
} while (text);
|
|
|
|
|
|
|
|
|
|
@@ -1316,7 +1281,6 @@ 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) {
|
|
|
|
|
@@ -1326,13 +1290,11 @@ static int syslog_print(char __user *buf, int size)
|
|
|
|
|
|
|
|
|
|
skip = syslog_partial;
|
|
|
|
|
msg = log_from_idx(syslog_idx);
|
|
|
|
|
n = msg_print_text(msg, syslog_prev, true, text,
|
|
|
|
|
LOG_LINE_MAX + PREFIX_MAX);
|
|
|
|
|
n = msg_print_text(msg, true, text, LOG_LINE_MAX + PREFIX_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){
|
|
|
|
|
@@ -1375,7 +1337,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
|
|
|
|
|
u64 next_seq;
|
|
|
|
|
u64 seq;
|
|
|
|
|
u32 idx;
|
|
|
|
|
enum log_flags prev;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Find first record that fits, including all following records,
|
|
|
|
|
@@ -1383,12 +1344,10 @@ 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 printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
|
|
|
|
len += msg_print_text(msg, prev, true, NULL, 0);
|
|
|
|
|
prev = msg->flags;
|
|
|
|
|
len += msg_print_text(msg, true, NULL, 0);
|
|
|
|
|
idx = log_next(idx);
|
|
|
|
|
seq++;
|
|
|
|
|
}
|
|
|
|
|
@@ -1396,12 +1355,10 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
|
|
|
|
|
/* 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 printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
|
|
|
|
len -= msg_print_text(msg, prev, true, NULL, 0);
|
|
|
|
|
prev = msg->flags;
|
|
|
|
|
len -= msg_print_text(msg, true, NULL, 0);
|
|
|
|
|
idx = log_next(idx);
|
|
|
|
|
seq++;
|
|
|
|
|
}
|
|
|
|
|
@@ -1414,7 +1371,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
|
|
|
|
|
struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
int textlen;
|
|
|
|
|
|
|
|
|
|
textlen = msg_print_text(msg, prev, true, text,
|
|
|
|
|
textlen = msg_print_text(msg, true, text,
|
|
|
|
|
LOG_LINE_MAX + PREFIX_MAX);
|
|
|
|
|
if (textlen < 0) {
|
|
|
|
|
len = textlen;
|
|
|
|
|
@@ -1422,7 +1379,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
|
|
|
|
|
}
|
|
|
|
|
idx = log_next(idx);
|
|
|
|
|
seq++;
|
|
|
|
|
prev = msg->flags;
|
|
|
|
|
|
|
|
|
|
raw_spin_unlock_irq(&logbuf_lock);
|
|
|
|
|
if (copy_to_user(buf + len, text, textlen))
|
|
|
|
|
@@ -1435,7 +1391,6 @@ 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1536,7 +1491,6 @@ int do_syslog(int type, char __user *buf, int len, int source)
|
|
|
|
|
/* messages are gone, move to first one */
|
|
|
|
|
syslog_seq = log_first_seq;
|
|
|
|
|
syslog_idx = log_first_idx;
|
|
|
|
|
syslog_prev = 0;
|
|
|
|
|
syslog_partial = 0;
|
|
|
|
|
}
|
|
|
|
|
if (source == SYSLOG_FROM_PROC) {
|
|
|
|
|
@@ -1549,16 +1503,14 @@ int do_syslog(int type, char __user *buf, int len, int source)
|
|
|
|
|
} else {
|
|
|
|
|
u64 seq = syslog_seq;
|
|
|
|
|
u32 idx = syslog_idx;
|
|
|
|
|
enum log_flags prev = syslog_prev;
|
|
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
|
while (seq < log_next_seq) {
|
|
|
|
|
struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
|
|
|
|
error += msg_print_text(msg, prev, true, NULL, 0);
|
|
|
|
|
error += msg_print_text(msg, true, NULL, 0);
|
|
|
|
|
idx = log_next(idx);
|
|
|
|
|
seq++;
|
|
|
|
|
prev = msg->flags;
|
|
|
|
|
}
|
|
|
|
|
error -= syslog_partial;
|
|
|
|
|
}
|
|
|
|
|
@@ -1740,7 +1692,7 @@ static size_t cont_print_text(char *text, size_t size)
|
|
|
|
|
size_t textlen = 0;
|
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
|
|
if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) {
|
|
|
|
|
if (cont.cons == 0) {
|
|
|
|
|
textlen += print_time(cont.ts_nsec, text);
|
|
|
|
|
size -= textlen;
|
|
|
|
|
}
|
|
|
|
|
@@ -2018,11 +1970,9 @@ static u64 syslog_seq;
|
|
|
|
|
static u32 syslog_idx;
|
|
|
|
|
static u64 console_seq;
|
|
|
|
|
static u32 console_idx;
|
|
|
|
|
static enum log_flags syslog_prev;
|
|
|
|
|
static u64 log_first_seq;
|
|
|
|
|
static u32 log_first_idx;
|
|
|
|
|
static u64 log_next_seq;
|
|
|
|
|
static enum log_flags console_prev;
|
|
|
|
|
static struct cont {
|
|
|
|
|
size_t len;
|
|
|
|
|
size_t cons;
|
|
|
|
|
@@ -2034,15 +1984,15 @@ static char *log_dict(const struct printk_log *msg) { return NULL; }
|
|
|
|
|
static struct printk_log *log_from_idx(u32 idx) { return NULL; }
|
|
|
|
|
static u32 log_next(u32 idx) { return 0; }
|
|
|
|
|
static ssize_t msg_print_ext_header(char *buf, size_t size,
|
|
|
|
|
struct printk_log *msg, u64 seq,
|
|
|
|
|
enum log_flags prev_flags) { return 0; }
|
|
|
|
|
struct printk_log *msg,
|
|
|
|
|
u64 seq) { return 0; }
|
|
|
|
|
static ssize_t msg_print_ext_body(char *buf, size_t size,
|
|
|
|
|
char *dict, size_t dict_len,
|
|
|
|
|
char *text, size_t text_len) { return 0; }
|
|
|
|
|
static void call_console_drivers(int level,
|
|
|
|
|
const char *ext_text, size_t ext_len,
|
|
|
|
|
const char *text, size_t len) {}
|
|
|
|
|
static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev,
|
|
|
|
|
static size_t msg_print_text(const struct printk_log *msg,
|
|
|
|
|
bool syslog, char *buf, size_t size) { return 0; }
|
|
|
|
|
static size_t cont_print_text(char *text, size_t size) { return 0; }
|
|
|
|
|
static bool suppress_message_printing(int level) { return false; }
|
|
|
|
|
@@ -2430,7 +2380,6 @@ again:
|
|
|
|
|
/* messages are gone, move to first one */
|
|
|
|
|
console_seq = log_first_seq;
|
|
|
|
|
console_idx = log_first_idx;
|
|
|
|
|
console_prev = 0;
|
|
|
|
|
} else {
|
|
|
|
|
len = 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -2455,16 +2404,14 @@ skip:
|
|
|
|
|
* will properly dump everything later.
|
|
|
|
|
*/
|
|
|
|
|
msg->flags &= ~LOG_NOCONS;
|
|
|
|
|
console_prev = msg->flags;
|
|
|
|
|
goto skip;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len += msg_print_text(msg, console_prev, false,
|
|
|
|
|
text + len, sizeof(text) - len);
|
|
|
|
|
len += msg_print_text(msg, false, text + len, sizeof(text) - len);
|
|
|
|
|
if (nr_ext_console_drivers) {
|
|
|
|
|
ext_len = msg_print_ext_header(ext_text,
|
|
|
|
|
sizeof(ext_text),
|
|
|
|
|
msg, console_seq, console_prev);
|
|
|
|
|
msg, console_seq);
|
|
|
|
|
ext_len += msg_print_ext_body(ext_text + ext_len,
|
|
|
|
|
sizeof(ext_text) - ext_len,
|
|
|
|
|
log_dict(msg), msg->dict_len,
|
|
|
|
|
@@ -2472,7 +2419,6 @@ skip:
|
|
|
|
|
}
|
|
|
|
|
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 */
|
|
|
|
|
@@ -2767,7 +2713,6 @@ 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
|
|
|
|
|
@@ -3117,7 +3062,7 @@ bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
msg = log_from_idx(dumper->cur_idx);
|
|
|
|
|
l = msg_print_text(msg, 0, syslog, line, size);
|
|
|
|
|
l = msg_print_text(msg, syslog, line, size);
|
|
|
|
|
|
|
|
|
|
dumper->cur_idx = log_next(dumper->cur_idx);
|
|
|
|
|
dumper->cur_seq++;
|
|
|
|
|
@@ -3186,7 +3131,6 @@ 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;
|
|
|
|
|
|
|
|
|
|
@@ -3209,27 +3153,23 @@ 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 printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
|
|
|
|
l += msg_print_text(msg, prev, true, NULL, 0);
|
|
|
|
|
l += msg_print_text(msg, 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) {
|
|
|
|
|
while (l >= size && seq < dumper->next_seq) {
|
|
|
|
|
struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
|
|
|
|
l -= msg_print_text(msg, prev, true, NULL, 0);
|
|
|
|
|
l -= msg_print_text(msg, true, NULL, 0);
|
|
|
|
|
idx = log_next(idx);
|
|
|
|
|
seq++;
|
|
|
|
|
prev = msg->flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* last message in next interation */
|
|
|
|
|
@@ -3240,10 +3180,9 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
|
|
|
|
|
while (seq < dumper->next_seq) {
|
|
|
|
|
struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
|
|
|
|
l += msg_print_text(msg, prev, syslog, buf + l, size - l);
|
|
|
|
|
l += msg_print_text(msg, syslog, buf + l, size - l);
|
|
|
|
|
idx = log_next(idx);
|
|
|
|
|
seq++;
|
|
|
|
|
prev = msg->flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dumper->next_seq = next_seq;
|
|
|
|
|
|