diff options
| -rw-r--r-- | fs/pstore/ftrace.c | 9 | ||||
| -rw-r--r-- | fs/pstore/platform.c | 30 | ||||
| -rw-r--r-- | fs/pstore/ram.c | 44 | ||||
| -rw-r--r-- | include/linux/pstore.h | 21 |
4 files changed, 55 insertions, 49 deletions
diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c index 899d0ba0bd6c..a5506ec6995e 100644 --- a/fs/pstore/ftrace.c +++ b/fs/pstore/ftrace.c | |||
| @@ -37,6 +37,12 @@ static void notrace pstore_ftrace_call(unsigned long ip, | |||
| 37 | { | 37 | { |
| 38 | unsigned long flags; | 38 | unsigned long flags; |
| 39 | struct pstore_ftrace_record rec = {}; | 39 | struct pstore_ftrace_record rec = {}; |
| 40 | struct pstore_record record = { | ||
| 41 | .type = PSTORE_TYPE_FTRACE, | ||
| 42 | .buf = (char *)&rec, | ||
| 43 | .size = sizeof(rec), | ||
| 44 | .psi = psinfo, | ||
| 45 | }; | ||
| 40 | 46 | ||
| 41 | if (unlikely(oops_in_progress)) | 47 | if (unlikely(oops_in_progress)) |
| 42 | return; | 48 | return; |
| @@ -47,8 +53,7 @@ static void notrace pstore_ftrace_call(unsigned long ip, | |||
| 47 | rec.parent_ip = parent_ip; | 53 | rec.parent_ip = parent_ip; |
| 48 | pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++); | 54 | pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++); |
| 49 | pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); | 55 | pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); |
| 50 | psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec, | 56 | psinfo->write_buf(&record); |
| 51 | 0, sizeof(rec), psinfo); | ||
| 52 | 57 | ||
| 53 | local_irq_restore(flags); | 58 | local_irq_restore(flags); |
| 54 | } | 59 | } |
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index aa3d6e572ede..5eecf9012459 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c | |||
| @@ -587,8 +587,11 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) | |||
| 587 | const char *e = s + c; | 587 | const char *e = s + c; |
| 588 | 588 | ||
| 589 | while (s < e) { | 589 | while (s < e) { |
| 590 | struct pstore_record record = { | ||
| 591 | .type = PSTORE_TYPE_CONSOLE, | ||
| 592 | .psi = psinfo, | ||
| 593 | }; | ||
| 590 | unsigned long flags; | 594 | unsigned long flags; |
| 591 | u64 id; | ||
| 592 | 595 | ||
| 593 | if (c > psinfo->bufsize) | 596 | if (c > psinfo->bufsize) |
| 594 | c = psinfo->bufsize; | 597 | c = psinfo->bufsize; |
| @@ -599,8 +602,9 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) | |||
| 599 | } else { | 602 | } else { |
| 600 | spin_lock_irqsave(&psinfo->buf_lock, flags); | 603 | spin_lock_irqsave(&psinfo->buf_lock, flags); |
| 601 | } | 604 | } |
| 602 | psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0, | 605 | record.buf = (char *)s; |
| 603 | s, 0, c, psinfo); | 606 | record.size = c; |
| 607 | psinfo->write_buf(&record); | ||
| 604 | spin_unlock_irqrestore(&psinfo->buf_lock, flags); | 608 | spin_unlock_irqrestore(&psinfo->buf_lock, flags); |
| 605 | s += c; | 609 | s += c; |
| 606 | c = e - s; | 610 | c = e - s; |
| @@ -630,10 +634,9 @@ static void pstore_unregister_console(void) {} | |||
| 630 | 634 | ||
| 631 | static int pstore_write_compat(struct pstore_record *record) | 635 | static int pstore_write_compat(struct pstore_record *record) |
| 632 | { | 636 | { |
| 633 | return record->psi->write_buf(record->type, record->reason, | 637 | record->buf = psinfo->buf; |
| 634 | &record->id, record->part, | 638 | |
| 635 | psinfo->buf, record->compressed, | 639 | return record->psi->write_buf(record); |
| 636 | record->size, record->psi); | ||
| 637 | } | 640 | } |
| 638 | 641 | ||
| 639 | static int pstore_write_buf_user_compat(enum pstore_type_id type, | 642 | static int pstore_write_buf_user_compat(enum pstore_type_id type, |
| @@ -653,6 +656,15 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type, | |||
| 653 | bufsize = psinfo->bufsize; | 656 | bufsize = psinfo->bufsize; |
| 654 | spin_lock_irqsave(&psinfo->buf_lock, flags); | 657 | spin_lock_irqsave(&psinfo->buf_lock, flags); |
| 655 | for (i = 0; i < size; ) { | 658 | for (i = 0; i < size; ) { |
| 659 | struct pstore_record record = { | ||
| 660 | .type = type, | ||
| 661 | .reason = reason, | ||
| 662 | .id = id, | ||
| 663 | .part = part, | ||
| 664 | .buf = psinfo->buf, | ||
| 665 | .compressed = compressed, | ||
| 666 | .psi = psi, | ||
| 667 | }; | ||
| 656 | size_t c = min(size - i, bufsize); | 668 | size_t c = min(size - i, bufsize); |
| 657 | 669 | ||
| 658 | ret = __copy_from_user(psinfo->buf, buf + i, c); | 670 | ret = __copy_from_user(psinfo->buf, buf + i, c); |
| @@ -660,8 +672,8 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type, | |||
| 660 | ret = -EFAULT; | 672 | ret = -EFAULT; |
| 661 | break; | 673 | break; |
| 662 | } | 674 | } |
| 663 | ret = psi->write_buf(type, reason, id, part, psinfo->buf, | 675 | record.size = c; |
| 664 | compressed, c, psi); | 676 | ret = psi->write_buf(&record); |
| 665 | if (unlikely(ret < 0)) | 677 | if (unlikely(ret < 0)) |
| 666 | break; | 678 | break; |
| 667 | i += c; | 679 | i += c; |
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index a18575fe32e9..a7cdde60b1f9 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c | |||
| @@ -378,23 +378,18 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz, | |||
| 378 | return len; | 378 | return len; |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, | 381 | static int notrace ramoops_pstore_write_buf(struct pstore_record *record) |
| 382 | enum kmsg_dump_reason reason, | ||
| 383 | u64 *id, unsigned int part, | ||
| 384 | const char *buf, | ||
| 385 | bool compressed, size_t size, | ||
| 386 | struct pstore_info *psi) | ||
| 387 | { | 382 | { |
| 388 | struct ramoops_context *cxt = psi->data; | 383 | struct ramoops_context *cxt = record->psi->data; |
| 389 | struct persistent_ram_zone *prz; | 384 | struct persistent_ram_zone *prz; |
| 390 | size_t hlen; | 385 | size_t size, hlen; |
| 391 | 386 | ||
| 392 | if (type == PSTORE_TYPE_CONSOLE) { | 387 | if (record->type == PSTORE_TYPE_CONSOLE) { |
| 393 | if (!cxt->cprz) | 388 | if (!cxt->cprz) |
| 394 | return -ENOMEM; | 389 | return -ENOMEM; |
| 395 | persistent_ram_write(cxt->cprz, buf, size); | 390 | persistent_ram_write(cxt->cprz, record->buf, record->size); |
| 396 | return 0; | 391 | return 0; |
| 397 | } else if (type == PSTORE_TYPE_FTRACE) { | 392 | } else if (record->type == PSTORE_TYPE_FTRACE) { |
| 398 | int zonenum; | 393 | int zonenum; |
| 399 | 394 | ||
| 400 | if (!cxt->fprzs) | 395 | if (!cxt->fprzs) |
| @@ -407,33 +402,36 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, | |||
| 407 | else | 402 | else |
| 408 | zonenum = 0; | 403 | zonenum = 0; |
| 409 | 404 | ||
| 410 | persistent_ram_write(cxt->fprzs[zonenum], buf, size); | 405 | persistent_ram_write(cxt->fprzs[zonenum], record->buf, |
| 406 | record->size); | ||
| 411 | return 0; | 407 | return 0; |
| 412 | } else if (type == PSTORE_TYPE_PMSG) { | 408 | } else if (record->type == PSTORE_TYPE_PMSG) { |
| 413 | pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__); | 409 | pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__); |
| 414 | return -EINVAL; | 410 | return -EINVAL; |
| 415 | } | 411 | } |
| 416 | 412 | ||
| 417 | if (type != PSTORE_TYPE_DMESG) | 413 | if (record->type != PSTORE_TYPE_DMESG) |
| 418 | return -EINVAL; | 414 | return -EINVAL; |
| 419 | 415 | ||
| 420 | /* Out of the various dmesg dump types, ramoops is currently designed | 416 | /* |
| 417 | * Out of the various dmesg dump types, ramoops is currently designed | ||
| 421 | * to only store crash logs, rather than storing general kernel logs. | 418 | * to only store crash logs, rather than storing general kernel logs. |
| 422 | */ | 419 | */ |
| 423 | if (reason != KMSG_DUMP_OOPS && | 420 | if (record->reason != KMSG_DUMP_OOPS && |
| 424 | reason != KMSG_DUMP_PANIC) | 421 | record->reason != KMSG_DUMP_PANIC) |
| 425 | return -EINVAL; | 422 | return -EINVAL; |
| 426 | 423 | ||
| 427 | /* Skip Oopes when configured to do so. */ | 424 | /* Skip Oopes when configured to do so. */ |
| 428 | if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops) | 425 | if (record->reason == KMSG_DUMP_OOPS && !cxt->dump_oops) |
| 429 | return -EINVAL; | 426 | return -EINVAL; |
| 430 | 427 | ||
| 431 | /* Explicitly only take the first part of any new crash. | 428 | /* |
| 429 | * Explicitly only take the first part of any new crash. | ||
| 432 | * If our buffer is larger than kmsg_bytes, this can never happen, | 430 | * If our buffer is larger than kmsg_bytes, this can never happen, |
| 433 | * and if our buffer is smaller than kmsg_bytes, we don't want the | 431 | * and if our buffer is smaller than kmsg_bytes, we don't want the |
| 434 | * report split across multiple records. | 432 | * report split across multiple records. |
| 435 | */ | 433 | */ |
| 436 | if (part != 1) | 434 | if (record->part != 1) |
| 437 | return -ENOSPC; | 435 | return -ENOSPC; |
| 438 | 436 | ||
| 439 | if (!cxt->dprzs) | 437 | if (!cxt->dprzs) |
| @@ -441,10 +439,12 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, | |||
| 441 | 439 | ||
| 442 | prz = cxt->dprzs[cxt->dump_write_cnt]; | 440 | prz = cxt->dprzs[cxt->dump_write_cnt]; |
| 443 | 441 | ||
| 444 | hlen = ramoops_write_kmsg_hdr(prz, compressed); | 442 | /* Build header and append record contents. */ |
| 443 | hlen = ramoops_write_kmsg_hdr(prz, record->compressed); | ||
| 444 | size = record->size; | ||
| 445 | if (size + hlen > prz->buffer_size) | 445 | if (size + hlen > prz->buffer_size) |
| 446 | size = prz->buffer_size - hlen; | 446 | size = prz->buffer_size - hlen; |
| 447 | persistent_ram_write(prz, buf, size); | ||
