Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 311142
b: refs/heads/master
c: e2ae715
h: refs/heads/master
v: v3
  • Loading branch information
Kay Sievers authored and Greg Kroah-Hartman committed Jun 15, 2012
1 parent 7a9cdfd commit 3cf3c27
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 138 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: 1bd289d1e8e29c09be0e783a53f16a1dc80684be
refs/heads/master: e2ae715d66bf4becfb85eb84b7150e23cf27df30
61 changes: 7 additions & 54 deletions trunk/arch/powerpc/platforms/pseries/nvram.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ static const char *pseries_nvram_os_partitions[] = {
};

static void oops_to_nvram(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason,
const char *old_msgs, unsigned long old_len,
const char *new_msgs, unsigned long new_len);
enum kmsg_dump_reason reason);

static struct kmsg_dumper nvram_kmsg_dumper = {
.dump = oops_to_nvram
Expand Down Expand Up @@ -503,28 +501,6 @@ int __init pSeries_nvram_init(void)
return 0;
}

/*
* Try to capture the last capture_len bytes of the printk buffer. Return
* the amount actually captured.
*/
static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
const char *new_msgs, size_t new_len,
char *captured, size_t capture_len)
{
if (new_len >= capture_len) {
memcpy(captured, new_msgs + (new_len - capture_len),
capture_len);
return capture_len;
} else {
/* Grab the end of old_msgs. */
size_t old_tail_len = min(old_len, capture_len - new_len);
memcpy(captured, old_msgs + (old_len - old_tail_len),
old_tail_len);
memcpy(captured + old_tail_len, new_msgs, new_len);
return old_tail_len + new_len;
}
}

/*
* Are we using the ibm,rtas-log for oops/panic reports? And if so,
* would logging this oops/panic overwrite an RTAS event that rtas_errd
Expand All @@ -541,27 +517,6 @@ static int clobbering_unread_rtas_event(void)
NVRAM_RTAS_READ_TIMEOUT);
}

/* Squeeze out each line's <n> severity prefix. */
static size_t elide_severities(char *buf, size_t len)
{
char *in, *out, *buf_end = buf + len;
/* Assume a <n> at the very beginning marks the start of a line. */
int newline = 1;

in = out = buf;
while (in < buf_end) {
if (newline && in+3 <= buf_end &&
*in == '<' && isdigit(in[1]) && in[2] == '>') {
in += 3;
newline = 0;
} else {
newline = (*in == '\n');
*out++ = *in++;
}
}
return out - buf;
}

/* Derived from logfs_compress() */
static int nvram_compress(const void *in, void *out, size_t inlen,
size_t outlen)
Expand Down Expand Up @@ -619,9 +574,7 @@ static int zip_oops(size_t text_len)
* partition. If that's too much, go back and capture uncompressed text.
*/
static void oops_to_nvram(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason,
const char *old_msgs, unsigned long old_len,
const char *new_msgs, unsigned long new_len)
enum kmsg_dump_reason reason)
{
static unsigned int oops_count = 0;
static bool panicking = false;
Expand Down Expand Up @@ -660,14 +613,14 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
return;

if (big_oops_buf) {
text_len = capture_last_msgs(old_msgs, old_len,
new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
text_len = elide_severities(big_oops_buf, text_len);
kmsg_dump_get_buffer(dumper, false,
big_oops_buf, big_oops_buf_sz, &text_len);
rc = zip_oops(text_len);
}
if (rc != 0) {
text_len = capture_last_msgs(old_msgs, old_len,
new_msgs, new_len, oops_data, oops_data_sz);
kmsg_dump_rewind(dumper);
kmsg_dump_get_buffer(dumper, true,
oops_data, oops_data_sz, &text_len);
err_type = ERR_TYPE_KERNEL_PANIC;
*oops_len = (u16) text_len;
}
Expand Down
13 changes: 5 additions & 8 deletions trunk/arch/x86/platform/mrst/early_printk_mrst.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,16 @@ static struct kmsg_dumper dw_dumper;
static int dumper_registered;

static void dw_kmsg_dump(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason,
const char *s1, unsigned long l1,
const char *s2, unsigned long l2)
enum kmsg_dump_reason reason)
{
int i;
static char line[1024];
size_t len;

/* When run to this, we'd better re-init the HW */
mrst_early_console_init();

for (i = 0; i < l1; i++)
early_mrst_console.write(&early_mrst_console, s1 + i, 1);
for (i = 0; i < l2; i++)
early_mrst_console.write(&early_mrst_console, s2 + i, 1);
while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
early_mrst_console.write(&early_mrst_console, line, len);
}

/* Set the ratio rate to 115200, 8n1, IRQ disabled */
Expand Down
22 changes: 4 additions & 18 deletions trunk/drivers/mtd/mtdoops.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,32 +304,17 @@ static void find_next_position(struct mtdoops_context *cxt)
}

static void mtdoops_do_dump(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
const char *s2, unsigned long l2)
enum kmsg_dump_reason reason)
{
struct mtdoops_context *cxt = container_of(dumper,
struct mtdoops_context, dump);
unsigned long s1_start, s2_start;
unsigned long l1_cpy, l2_cpy;
char *dst;

if (reason != KMSG_DUMP_OOPS &&
reason != KMSG_DUMP_PANIC)
return;

/* Only dump oopses if dump_oops is set */
if (reason == KMSG_DUMP_OOPS && !dump_oops)
return;

dst = cxt->oops_buf + MTDOOPS_HEADER_SIZE; /* Skip the header */
l2_cpy = min(l2, record_size - MTDOOPS_HEADER_SIZE);
l1_cpy = min(l1, record_size - MTDOOPS_HEADER_SIZE - l2_cpy);

s2_start = l2 - l2_cpy;
s1_start = l1 - l1_cpy;

memcpy(dst, s1 + s1_start, l1_cpy);
memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
record_size - MTDOOPS_HEADER_SIZE, NULL);

/* Panics must be written immediately */
if (reason != KMSG_DUMP_OOPS)
Expand Down Expand Up @@ -375,6 +360,7 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
return;
}

cxt->dump.max_reason = KMSG_DUMP_OOPS;
cxt->dump.dump = mtdoops_do_dump;
err = kmsg_dump_register(&cxt->dump);
if (err) {
Expand Down
34 changes: 12 additions & 22 deletions trunk/fs/pstore/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,15 @@ static const char *get_reason_str(enum kmsg_dump_reason reason)
* as we can from the end of the buffer.
*/
static void pstore_dump(struct kmsg_dumper *dumper,
enum kmsg_dump_reason reason,
const char *s1, unsigned long l1,
const char *s2, unsigned long l2)
enum kmsg_dump_reason reason)
{
unsigned long s1_start, s2_start;
unsigned long l1_cpy, l2_cpy;
unsigned long size, total = 0;
char *dst;
unsigned long total = 0;
const char *why;
u64 id;
int hsize, ret;
unsigned int part = 1;
unsigned long flags = 0;
int is_locked = 0;
int ret;

why = get_reason_str(reason);

Expand All @@ -119,30 +114,25 @@ static void pstore_dump(struct kmsg_dumper *dumper,
spin_lock_irqsave(&psinfo->buf_lock, flags);
oopscount++;
while (total < kmsg_bytes) {
char *dst;
unsigned long size;
int hsize;
size_t len;

dst = psinfo->buf;
hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
size = psinfo->bufsize - hsize;
dst += hsize;

l2_cpy = min(l2, size);
l1_cpy = min(l1, size - l2_cpy);

if (l1_cpy + l2_cpy == 0)
if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len))
break;

s2_start = l2 - l2_cpy;
s1_start = l1 - l1_cpy;

memcpy(dst, s1 + s1_start, l1_cpy);
memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);

ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part,
hsize + l1_cpy + l2_cpy, psinfo);
hsize + len, psinfo);
if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
pstore_new_entry = 1;
l1 -= l1_cpy;
l2 -= l2_cpy;
total += l1_cpy + l2_cpy;

total += hsize + len;
part++;
}
if (in_nmi()) {
Expand Down
45 changes: 38 additions & 7 deletions trunk/include/linux/kmsg_dump.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* is passed to the kernel.
*/
enum kmsg_dump_reason {
KMSG_DUMP_UNDEF,
KMSG_DUMP_PANIC,
KMSG_DUMP_OOPS,
KMSG_DUMP_EMERG,
Expand All @@ -31,23 +32,37 @@ enum kmsg_dump_reason {

/**
* struct kmsg_dumper - kernel crash message dumper structure
* @dump: The callback which gets called on crashes. The buffer is passed
* as two sections, where s1 (length l1) contains the older
* messages and s2 (length l2) contains the newer.
* @list: Entry in the dumper list (private)
* @dump: Call into dumping code which will retrieve the data with
* through the record iterator
* @max_reason: filter for highest reason number that should be dumped
* @registered: Flag that specifies if this is already registered
*/
struct kmsg_dumper {
void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason,
const char *s1, unsigned long l1,
const char *s2, unsigned long l2);
struct list_head list;
int registered;
void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
enum kmsg_dump_reason max_reason;
bool active;
bool registered;

/* private state of the kmsg iterator */
u32 cur_idx;
u32 next_idx;
u64 cur_seq;
u64 next_seq;
};

#ifdef CONFIG_PRINTK
void kmsg_dump(enum kmsg_dump_reason reason);

bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
char *line, size_t size, size_t *len);

bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
char *buf, size_t size, size_t *len);

void kmsg_dump_rewind(struct kmsg_dumper *dumper);

int kmsg_dump_register(struct kmsg_dumper *dumper);

int kmsg_dump_unregister(struct kmsg_dumper *dumper);
Expand All @@ -56,6 +71,22 @@ static inline void kmsg_dump(enum kmsg_dump_reason reason)
{
}

bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
const char *line, size_t size, size_t *len)
{
return false;
}

bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
char *buf, size_t size, size_t *len)
{
return false;
}

void kmsg_dump_rewind(struct kmsg_dumper *dumper)
{
}

static inline int kmsg_dump_register(struct kmsg_dumper *dumper)
{
return -EINVAL;
Expand Down
Loading

0 comments on commit 3cf3c27

Please sign in to comment.