aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-02 13:35:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-02 13:35:45 -0400
commit2575be8ad32f9910d7e7c118e73f529b8d5b8b7b (patch)
treeae27a631c15914e0870813af57d443fbd4ad0acf
parentc58d4055c054fc6dc72f1be8bc71bd6fff209e48 (diff)
parent3a7d2fd16c57a1ef47dc2891171514231c9c7c6e (diff)
Merge tag 'pstore-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull pstore updates from Kees Cook: "This has a large internal refactoring along with several smaller fixes. - constify compression structures; Bhumika Goyal - restore powerpc dumping; Ankit Kumar - fix more bugs in the rarely exercises module unloading logic - reorganize filesystem locking to fix problems noticed by lockdep - refactor internal pstore APIs to make development and review easier: - improve error reporting - add kernel-doc structure and function comments - avoid insane argument passing by using a common record structure" * tag 'pstore-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (23 commits) pstore: Solve lockdep warning by moving inode locks pstore: Fix flags to enable dumps on powerpc pstore: Remove unused vmalloc.h in pmsg pstore: simplify write_user_compat() pstore: Remove write_buf() callback pstore: Replace arguments for write_buf_user() API pstore: Replace arguments for write_buf() API pstore: Replace arguments for erase() API pstore: Do not duplicate record metadata pstore: Allocate records on heap instead of stack pstore: Pass record contents instead of copying pstore: Always allocate buffer for decompression pstore: Replace arguments for write() API pstore: Replace arguments for read() API pstore: Switch pstore_mkfile to pass record pstore: Move record decompression to function pstore: Extract common arguments into structure pstore: Add kernel-doc for struct pstore_info pstore: Improve register_pstore() error reporting pstore: Avoid race in module unloading ...
-rw-r--r--arch/powerpc/kernel/nvram_64.c89
-rw-r--r--drivers/acpi/apei/erst.c64
-rw-r--r--drivers/firmware/efi/efi-pstore.c148
-rw-r--r--fs/pstore/ftrace.c11
-rw-r--r--fs/pstore/inode.c147
-rw-r--r--fs/pstore/internal.h8
-rw-r--r--fs/pstore/platform.c301
-rw-r--r--fs/pstore/pmsg.c12
-rw-r--r--fs/pstore/ram.c130
-rw-r--r--fs/pstore/ram_core.c2
-rw-r--r--include/linux/pstore.h156
11 files changed, 607 insertions, 461 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index d5e2b8309939..eae61b044e9e 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -389,51 +389,40 @@ static int nvram_pstore_open(struct pstore_info *psi)
389 389
390/** 390/**
391 * nvram_pstore_write - pstore write callback for nvram 391 * nvram_pstore_write - pstore write callback for nvram
392 * @type: Type of message logged 392 * @record: pstore record to write, with @id to be set
393 * @reason: reason behind dump (oops/panic)
394 * @id: identifier to indicate the write performed
395 * @part: pstore writes data to registered buffer in parts,
396 * part number will indicate the same.
397 * @count: Indicates oops count
398 * @compressed: Flag to indicate the log is compressed
399 * @size: number of bytes written to the registered buffer
400 * @psi: registered pstore_info structure
401 * 393 *
402 * Called by pstore_dump() when an oops or panic report is logged in the 394 * Called by pstore_dump() when an oops or panic report is logged in the
403 * printk buffer. 395 * printk buffer.
404 * Returns 0 on successful write. 396 * Returns 0 on successful write.
405 */ 397 */
406static int nvram_pstore_write(enum pstore_type_id type, 398static int nvram_pstore_write(struct pstore_record *record)
407 enum kmsg_dump_reason reason,
408 u64 *id, unsigned int part, int count,
409 bool compressed, size_t size,
410 struct pstore_info *psi)
411{ 399{
412 int rc; 400 int rc;
413 unsigned int err_type = ERR_TYPE_KERNEL_PANIC; 401 unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
414 struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf; 402 struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
415 403
416 /* part 1 has the recent messages from printk buffer */ 404 /* part 1 has the recent messages from printk buffer */
417 if (part > 1 || (type != PSTORE_TYPE_DMESG)) 405 if (record->part > 1 || (record->type != PSTORE_TYPE_DMESG))
418 return -1; 406 return -1;
419 407
420 if (clobbering_unread_rtas_event()) 408 if (clobbering_unread_rtas_event())
421 return -1; 409 return -1;
422 410
423 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); 411 oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
424 oops_hdr->report_length = cpu_to_be16(size); 412 oops_hdr->report_length = cpu_to_be16(record->size);
425 oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds()); 413 oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
426 414
427 if (compressed) 415 if (record->compressed)
428 err_type = ERR_TYPE_KERNEL_PANIC_GZ; 416 err_type = ERR_TYPE_KERNEL_PANIC_GZ;
429 417
430 rc = nvram_write_os_partition(&oops_log_partition, oops_buf, 418 rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
431 (int) (sizeof(*oops_hdr) + size), err_type, count); 419 (int) (sizeof(*oops_hdr) + record->size), err_type,
420 record->count);
432 421
433 if (rc != 0) 422 if (rc != 0)
434 return rc; 423 return rc;
435 424
436 *id = part; 425 record->id = record->part;
437 return 0; 426 return 0;
438} 427}
439 428
@@ -442,10 +431,7 @@ static int nvram_pstore_write(enum pstore_type_id type,
442 * Returns the length of the data we read from each partition. 431 * Returns the length of the data we read from each partition.
443 * Returns 0 if we've been called before. 432 * Returns 0 if we've been called before.
444 */ 433 */
445static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, 434static ssize_t nvram_pstore_read(struct pstore_record *record)
446 int *count, struct timespec *time, char **buf,
447 bool *compressed, ssize_t *ecc_notice_size,
448 struct pstore_info *psi)
449{ 435{
450 struct oops_log_info *oops_hdr; 436 struct oops_log_info *oops_hdr;
451 unsigned int err_type, id_no, size = 0; 437 unsigned int err_type, id_no, size = 0;
@@ -459,40 +445,40 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
459 switch (nvram_type_ids[read_type]) { 445 switch (nvram_type_ids[read_type]) {
460 case PSTORE_TYPE_DMESG: 446 case PSTORE_TYPE_DMESG:
461 part = &oops_log_partition; 447 part = &oops_log_partition;
462 *type = PSTORE_TYPE_DMESG; 448 record->type = PSTORE_TYPE_DMESG;
463 break; 449 break;
464 case PSTORE_TYPE_PPC_COMMON: 450 case PSTORE_TYPE_PPC_COMMON:
465 sig = NVRAM_SIG_SYS; 451 sig = NVRAM_SIG_SYS;
466 part = &common_partition; 452 part = &common_partition;
467 *type = PSTORE_TYPE_PPC_COMMON; 453 record->type = PSTORE_TYPE_PPC_COMMON;
468 *id = PSTORE_TYPE_PPC_COMMON; 454 record->id = PSTORE_TYPE_PPC_COMMON;
469 time->tv_sec = 0; 455 record->time.tv_sec = 0;
470 time->tv_nsec = 0; 456 record->time.tv_nsec = 0;
471 break; 457 break;
472#ifdef CONFIG_PPC_PSERIES 458#ifdef CONFIG_PPC_PSERIES
473 case PSTORE_TYPE_PPC_RTAS: 459 case PSTORE_TYPE_PPC_RTAS:
474 part = &rtas_log_partition; 460 part = &rtas_log_partition;
475 *type = PSTORE_TYPE_PPC_RTAS; 461 record->type = PSTORE_TYPE_PPC_RTAS;
476 time->tv_sec = last_rtas_event; 462 record->time.tv_sec = last_rtas_event;
477 time->tv_nsec = 0; 463 record->time.tv_nsec = 0;
478 break; 464 break;
479 case PSTORE_TYPE_PPC_OF: 465 case PSTORE_TYPE_PPC_OF:
480 sig = NVRAM_SIG_OF; 466 sig = NVRAM_SIG_OF;
481 part = &of_config_partition; 467 part = &of_config_partition;
482 *type = PSTORE_TYPE_PPC_OF; 468 record->type = PSTORE_TYPE_PPC_OF;
483 *id = PSTORE_TYPE_PPC_OF; 469 record->id = PSTORE_TYPE_PPC_OF;
484 time->tv_sec = 0; 470 record->time.tv_sec = 0;
485 time->tv_nsec = 0; 471 record->time.tv_nsec = 0;
486 break; 472 break;
487#endif 473#endif
488#ifdef CONFIG_PPC_POWERNV 474#ifdef CONFIG_PPC_POWERNV
489 case PSTORE_TYPE_PPC_OPAL: 475 case PSTORE_TYPE_PPC_OPAL:
490 sig = NVRAM_SIG_FW; 476 sig = NVRAM_SIG_FW;
491 part = &skiboot_partition; 477 part = &skiboot_partition;
492 *type = PSTORE_TYPE_PPC_OPAL; 478 record->type = PSTORE_TYPE_PPC_OPAL;
493 *id = PSTORE_TYPE_PPC_OPAL; 479 record->id = PSTORE_TYPE_PPC_OPAL;
494 time->tv_sec = 0; 480 record->time.tv_sec = 0;
495 time->tv_nsec = 0; 481 record->time.tv_nsec = 0;
496 break; 482 break;
497#endif 483#endif
498 default: 484 default:
@@ -520,10 +506,10 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
520 return 0; 506 return 0;
521 } 507 }
522 508
523 *count = 0; 509 record->count = 0;
524 510
525 if (part->os_partition) 511 if (part->os_partition)
526 *id = id_no; 512 record->id = id_no;
527 513
528 if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { 514 if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
529 size_t length, hdr_size; 515 size_t length, hdr_size;
@@ -533,34 +519,35 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
533 /* Old format oops header had 2-byte record size */ 519 /* Old format oops header had 2-byte record size */
534 hdr_size = sizeof(u16); 520 hdr_size = sizeof(u16);
535 length = be16_to_cpu(oops_hdr->version); 521 length = be16_to_cpu(oops_hdr->version);
536 time->tv_sec = 0; 522 record->time.tv_sec = 0;
537 time->tv_nsec = 0; 523 record->time.tv_nsec = 0;
538 } else { 524 } else {
539 hdr_size = sizeof(*oops_hdr); 525 hdr_size = sizeof(*oops_hdr);
540 length = be16_to_cpu(oops_hdr->report_length); 526 length = be16_to_cpu(oops_hdr->report_length);
541 time->tv_sec = be64_to_cpu(oops_hdr->timestamp); 527 record->time.tv_sec = be64_to_cpu(oops_hdr->timestamp);
542 time->tv_nsec = 0; 528 record->time.tv_nsec = 0;
543 } 529 }
544 *buf = kmemdup(buff + hdr_size, length, GFP_KERNEL); 530 record->buf = kmemdup(buff + hdr_size, length, GFP_KERNEL);
545 kfree(buff); 531 kfree(buff);
546 if (*buf == NULL) 532 if (record->buf == NULL)
547 return -ENOMEM; 533 return -ENOMEM;
548 534
549 *ecc_notice_size = 0; 535 record->ecc_notice_size = 0;
550 if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) 536 if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
551 *compressed = true; 537 record->compressed = true;
552 else 538 else
553 *compressed = false; 539 record->compressed = false;
554 return length; 540 return length;
555 } 541 }
556 542
557 *buf = buff; 543 record->buf = buff;
558 return part->size; 544 return part->size;
559} 545}
560 546
561static struct pstore_info nvram_pstore_info = { 547static struct pstore_info nvram_pstore_info = {
562 .owner = THIS_MODULE, 548 .owner = THIS_MODULE,
563 .name = "nvram", 549 .name = "nvram",
550 .flags = PSTORE_FLAGS_DMESG,
564 .open = nvram_pstore_open, 551 .open = nvram_pstore_open,
565 .read = nvram_pstore_read, 552 .read = nvram_pstore_read,
566 .write = nvram_pstore_write, 553 .write = nvram_pstore_write,
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index ec4f507b524f..7207e5fc9d3d 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -925,15 +925,9 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
925 925
926static int erst_open_pstore(struct pstore_info *psi); 926static int erst_open_pstore(struct pstore_info *psi);
927static int erst_close_pstore(struct pstore_info *psi); 927static int erst_close_pstore(struct pstore_info *psi);
928static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, 928static ssize_t erst_reader(struct pstore_record *record);
929 struct timespec *time, char **buf, 929static int erst_writer(struct pstore_record *record);
930 bool *compressed, ssize_t *ecc_notice_size, 930static int erst_clearer(struct pstore_record *record);
931 struct pstore_info *psi);
932static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
933 u64 *id, unsigned int part, int count, bool compressed,
934 size_t size, struct pstore_info *psi);
935static int erst_clearer(enum pstore_type_id type, u64 id, int count,
936 struct timespec time, struct pstore_info *psi);
937 931
938static struct pstore_info erst_info = { 932static struct pstore_info erst_info = {
939 .owner = THIS_MODULE, 933 .owner = THIS_MODULE,
@@ -986,10 +980,7 @@ static int erst_close_pstore(struct pstore_info *psi)
986 return 0; 980 return 0;
987} 981}
988 982
989static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, 983static ssize_t erst_reader(struct pstore_record *record)
990 struct timespec *time, char **buf,
991 bool *compressed, ssize_t *ecc_notice_size,
992 struct pstore_info *psi)
993{ 984{
994 int rc; 985 int rc;
995 ssize_t len = 0; 986 ssize_t len = 0;
@@ -1027,42 +1018,40 @@ skip:
1027 if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) 1018 if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
1028 goto skip; 1019 goto skip;
1029 1020
1030 *buf = kmalloc(len, GFP_KERNEL); 1021 record->buf = kmalloc(len, GFP_KERNEL);
1031 if (*buf == NULL) { 1022 if (record->buf == NULL) {
1032 rc = -ENOMEM; 1023 rc = -ENOMEM;
1033 goto out; 1024 goto out;
1034 } 1025 }
1035 memcpy(*buf, rcd->data, len - sizeof(*rcd)); 1026 memcpy(record->buf, rcd->data, len - sizeof(*rcd));
1036 *id = record_id; 1027 record->id = record_id;
1037 *compressed = false; 1028 record->compressed = false;
1038 *ecc_notice_size = 0; 1029 record->ecc_notice_size = 0;
1039 if (uuid_le_cmp(rcd->sec_hdr.section_type, 1030 if (uuid_le_cmp(rcd->sec_hdr.section_type,
1040 CPER_SECTION_TYPE_DMESG_Z) == 0) { 1031 CPER_SECTION_TYPE_DMESG_Z) == 0) {
1041 *type = PSTORE_TYPE_DMESG; 1032 record->type = PSTORE_TYPE_DMESG;
1042 *compressed = true; 1033 record->compressed = true;
1043 } else if (uuid_le_cmp(rcd->sec_hdr.section_type, 1034 } else if (uuid_le_cmp(rcd->sec_hdr.section_type,
1044 CPER_SECTION_TYPE_DMESG) == 0) 1035 CPER_SECTION_TYPE_DMESG) == 0)
1045 *type = PSTORE_TYPE_DMESG; 1036 record->type = PSTORE_TYPE_DMESG;
1046 else if (uuid_le_cmp(rcd->sec_hdr.section_type, 1037 else if (uuid_le_cmp(rcd->sec_hdr.section_type,
1047 CPER_SECTION_TYPE_MCE) == 0) 1038 CPER_SECTION_TYPE_MCE) == 0)
1048 *type = PSTORE_TYPE_MCE; 1039 record->type = PSTORE_TYPE_MCE;
1049 else 1040 else
1050 *type = PSTORE_TYPE_UNKNOWN; 1041 record->type = PSTORE_TYPE_UNKNOWN;
1051 1042
1052 if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP) 1043 if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP)
1053 time->tv_sec = rcd->hdr.timestamp; 1044 record->time.tv_sec = rcd->hdr.timestamp;
1054 else 1045 else
1055 time->tv_sec = 0; 1046 record->time.tv_sec = 0;
1056 time->tv_nsec = 0; 1047 record->time.tv_nsec = 0;
1057 1048
1058out: 1049out:
1059 kfree(rcd); 1050 kfree(rcd);
1060 return (rc < 0) ? rc : (len - sizeof(*rcd)); 1051 return (rc < 0) ? rc : (len - sizeof(*rcd));
1061} 1052}
1062 1053
1063static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, 1054static int erst_writer(struct pstore_record *record)
1064 u64 *id, unsigned int part, int count, bool compressed,
1065 size_t size, struct pstore_info *psi)
1066{ 1055{
1067 struct cper_pstore_record *rcd = (struct cper_pstore_record *) 1056 struct cper_pstore_record *rcd = (struct cper_pstore_record *)
1068 (erst_info.buf - sizeof(*rcd)); 1057 (erst_info.buf - sizeof(*rcd));
@@ -1077,21 +1066,21 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
1077 /* timestamp valid. platform_id, partition_id are invalid */ 1066 /* timestamp valid. platform_id, partition_id are invalid */
1078 rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP; 1067 rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP;
1079 rcd->hdr.timestamp = get_seconds(); 1068 rcd->hdr.timestamp = get_seconds();
1080 rcd->hdr.record_length = sizeof(*rcd) + size; 1069 rcd->hdr.record_length = sizeof(*rcd) + record->size;
1081 rcd->hdr.creator_id = CPER_CREATOR_PSTORE; 1070 rcd->hdr.creator_id = CPER_CREATOR_PSTORE;
1082 rcd->hdr.notification_type = CPER_NOTIFY_MCE; 1071 rcd->hdr.notification_type = CPER_NOTIFY_MCE;
1083 rcd->hdr.record_id = cper_next_record_id(); 1072 rcd->hdr.record_id = cper_next_record_id();
1084 rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR; 1073 rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR;
1085 1074
1086 rcd->sec_hdr.section_offset = sizeof(*rcd); 1075 rcd->sec_hdr.section_offset = sizeof(*rcd);
1087 rcd->sec_hdr.section_length = size; 1076 rcd->sec_hdr.section_length = record->size;
1088 rcd->sec_hdr.revision = CPER_SEC_REV; 1077 rcd->sec_hdr.revision = CPER_SEC_REV;
1089 /* fru_id and fru_text is invalid */ 1078 /* fru_id and fru_text is invalid */
1090 rcd->sec_hdr.validation_bits = 0; 1079 rcd->sec_hdr.validation_bits = 0;
1091 rcd->sec_hdr.flags = CPER_SEC_PRIMARY; 1080 rcd->sec_hdr.flags = CPER_SEC_PRIMARY;
1092 switch (type) { 1081 switch (record->type) {
1093 case PSTORE_TYPE_DMESG: 1082 case PSTORE_TYPE_DMESG:
1094 if (compressed) 1083 if (record->compressed)
1095 rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG_Z; 1084 rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG_Z;
1096 else 1085 else
1097 rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG; 1086 rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG;
@@ -1105,15 +1094,14 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
1105 rcd->sec_hdr.section_severity = CPER_SEV_FATAL; 1094 rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
1106 1095
1107 ret = erst_write(&rcd->hdr); 1096 ret = erst_write(&rcd->hdr);
1108 *id = rcd->hdr.record_id; 1097 record->id = rcd->hdr.record_id;
1109 1098
1110 return ret; 1099 return ret;
1111} 1100}
1112 1101
1113static int erst_clearer(enum pstore_type_id type, u64 id, int count, 1102static int erst_clearer(struct pstore_record *record)
1114 struct timespec time, struct pstore_info *psi)
1115{ 1103{
1116 return erst_clear(id); 1104 return erst_clear(record->id);
1117} 1105}
1118 1106
1119static int __init erst_init(void) 1107static int __init erst_init(void)
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index 6b5acefce6b3..ed3137c1ceb0 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -28,26 +28,16 @@ static int efi_pstore_close(struct pstore_info *psi)
28 return 0; 28 return 0;
29} 29}
30 30
31struct pstore_read_data {
32 u64 *id;
33 enum pstore_type_id *type;
34 int *count;
35 struct timespec *timespec;
36 bool *compressed;
37 ssize_t *ecc_notice_size;
38 char **buf;
39};
40
41static inline u64 generic_id(unsigned long timestamp, 31static inline u64 generic_id(unsigned long timestamp,
42 unsigned int part, int count) 32 unsigned int part, int count)
43{ 33{
44 return ((u64) timestamp * 100 + part) * 1000 + count; 34 return ((u64) timestamp * 100 + part) * 1000 + count;
45} 35}
46 36
47static int efi_pstore_read_func(struct efivar_entry *entry, void *data) 37static int efi_pstore_read_func(struct efivar_entry *entry,
38 struct pstore_record *record)
48{ 39{
49 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 40 efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
50 struct pstore_read_data *cb_data = data;
51 char name[DUMP_NAME_LEN], data_type; 41 char name[DUMP_NAME_LEN], data_type;
52 int i; 42 int i;
53 int cnt; 43 int cnt;
@@ -61,37 +51,37 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
61 name[i] = entry->var.VariableName[i]; 51 name[i] = entry->var.VariableName[i];
62 52
63 if (sscanf(name, "dump-type%u-%u-%d-%lu-%c", 53 if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
64 cb_data->type, &part, &cnt, &time, &data_type) == 5) { 54 &record->type, &part, &cnt, &time, &data_type) == 5) {
65 *cb_data->id = generic_id(time, part, cnt); 55 record->id = generic_id(time, part, cnt);
66 *cb_data->count = cnt; 56 record->count = cnt;
67 cb_data->timespec->tv_sec = time; 57 record->time.tv_sec = time;
68 cb_data->timespec->tv_nsec = 0; 58 record->time.tv_nsec = 0;
69 if (data_type == 'C') 59 if (data_type == 'C')
70 *cb_data->compressed = true; 60 record->compressed = true;
71 else 61 else
72 *cb_data->compressed = false; 62 record->compressed = false;
73 *cb_data->ecc_notice_size = 0; 63 record->ecc_notice_size = 0;
74 } else if (sscanf(name, "dump-type%u-%u-%d-%lu", 64 } else if (sscanf(name, "dump-type%u-%u-%d-%lu",
75 cb_data->type, &part, &cnt, &time) == 4) { 65 &record->type, &part, &cnt, &time) == 4) {
76 *cb_data->id = generic_id(time, part, cnt); 66 record->id = generic_id(time, part, cnt);
77 *cb_data->count = cnt; 67 record->count = cnt;
78 cb_data->timespec->tv_sec = time; 68 record->time.tv_sec = time;
79 cb_data->timespec->tv_nsec = 0; 69 record->time.tv_nsec = 0;
80 *cb_data->compressed = false; 70 record->compressed = false;
81 *cb_data->ecc_notice_size = 0; 71 record->ecc_notice_size = 0;
82 } else if (sscanf(name, "dump-type%u-%u-%lu", 72 } else if (sscanf(name, "dump-type%u-%u-%lu",
83 cb_data->type, &part, &time) == 3) { 73 &record->type, &part, &time) == 3) {
84 /* 74 /*
85 * Check if an old format, 75 * Check if an old format,
86 * which doesn't support holding 76 * which doesn't support holding
87 * multiple logs, remains. 77 * multiple logs, remains.
88 */ 78 */
89 *cb_data->id = generic_id(time, part, 0); 79 record->id = generic_id(time, part, 0);
90 *cb_data->count = 0; 80 record->count = 0;
91 cb_data->timespec->tv_sec = time; 81 record->time.tv_sec = time;
92 cb_data->timespec->tv_nsec = 0; 82 record->time.tv_nsec = 0;
93 *cb_data->compressed = false; 83 record->compressed = false;
94 *cb_data->ecc_notice_size = 0; 84 record->ecc_notice_size = 0;
95 } else 85 } else
96 return 0; 86 return 0;
97 87
@@ -99,7 +89,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
99 __efivar_entry_get(entry, &entry->var.Attributes, 89 __efivar_entry_get(entry, &entry->var.Attributes,
100 &entry->var.DataSize, entry->var.Data); 90 &entry->var.DataSize, entry->var.Data);
101 size = entry->var.DataSize; 91 size = entry->var.DataSize;
102 memcpy(*cb_data->buf, entry->var.Data, 92 memcpy(record->buf, entry->var.Data,
103 (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size)); 93 (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size));
104 94
105 return size; 95 return size;
@@ -164,7 +154,7 @@ static int efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
164/** 154/**
165 * efi_pstore_sysfs_entry_iter 155 * efi_pstore_sysfs_entry_iter
166 * 156 *
167 * @data: function-specific data to pass to callback 157 * @record: pstore record to pass to callback
168 * @pos: entry to begin iterating from 158 * @pos: entry to begin iterating from
169 * 159 *
170 * You MUST call efivar_enter_iter_begin() before this function, and 160 * You MUST call efivar_enter_iter_begin() before this function, and
@@ -175,7 +165,8 @@ static int efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
175 * the next entry of the last one passed to efi_pstore_read_func(). 165 * the next entry of the last one passed to efi_pstore_read_func().
176 * To begin iterating from the beginning of the list @pos must be %NULL. 166 * To begin iterating from the beginning of the list @pos must be %NULL.
177 */ 167 */
178static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos) 168static int efi_pstore_sysfs_entry_iter(struct pstore_record *record,
169 struct efivar_entry **pos)
179{ 170{
180 struct efivar_entry *entry, *n; 171 struct efivar_entry *entry, *n;
181 struct list_head *head = &efivar_sysfs_list; 172 struct list_head *head = &efivar_sysfs_list;
@@ -186,7 +177,7 @@ static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos)
186 list_for_each_entry_safe(entry, n, head, list) { 177 list_for_each_entry_safe(entry, n, head, list) {
187 efi_pstore_scan_sysfs_enter(entry, n, head); 178 efi_pstore_scan_sysfs_enter(entry, n, head);
188 179
189 size = efi_pstore_read_func(entry, data); 180 size = efi_pstore_read_func(entry, record);
190 ret = efi_pstore_scan_sysfs_exit(entry, n, head, 181 ret = efi_pstore_scan_sysfs_exit(entry, n, head,
191 size < 0); 182 size < 0);
192 if (ret) 183 if (ret)
@@ -201,7 +192,7 @@ static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos)
201 list_for_each_entry_safe_from((*pos), n, head, list) { 192 list_for_each_entry_safe_from((*pos), n, head, list) {
202 efi_pstore_scan_sysfs_enter((*pos), n, head); 193 efi_pstore_scan_sysfs_enter((*pos), n, head);
203 194
204 size = efi_pstore_read_func((*pos), data); 195 size = efi_pstore_read_func((*pos), record);
205 ret = efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0); 196 ret = efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0);
206 if (ret) 197 if (ret)
207 return ret; 198 return ret;
@@ -225,71 +216,57 @@ static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos)
225 * size < 0: Failed to get data of entry logging via efi_pstore_write(), 216 * size < 0: Failed to get data of entry logging via efi_pstore_write(),
226 * and pstore will stop reading entry. 217 * and pstore will stop reading entry.
227 */ 218 */
228static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 219static ssize_t efi_pstore_read(struct pstore_record *record)
229 int *count, struct timespec *timespec,
230 char **buf, bool *compressed,
231 ssize_t *ecc_notice_size,
232 struct pstore_info *psi)
233{ 220{
234 struct pstore_read_data data; 221 struct efivar_entry *entry = (struct efivar_entry *)record->psi->data;
235 ssize_t size; 222 ssize_t size;
236 223
237 data.id = id; 224 record->buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
238 data.type = type; 225 if (!record->buf)
239 data.count = count;
240 data.timespec = timespec;
241 data.compressed = compressed;
242 data.ecc_notice_size = ecc_notice_size;
243 data.buf = buf;
244
245 *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
246 if (!*data.buf)
247 return -ENOMEM; 226 return -ENOMEM;
248 227
249 if (efivar_entry_iter_begin()) { 228 if (efivar_entry_iter_begin()) {
250 kfree(*data.buf); 229 size = -EINTR;
251 return -EINTR; 230 goto out;
252 } 231 }
253 size = efi_pstore_sysfs_entry_iter(&data, 232 size = efi_pstore_sysfs_entry_iter(record, &entry);
254 (struct efivar_entry **)&psi->data);
255 efivar_entry_iter_end(); 233 efivar_entry_iter_end();
256 if (size <= 0) 234
257 kfree(*data.buf); 235out:
236 if (size <= 0) {
237 kfree(record->buf);
238 record->buf = NULL;
239 }
258 return size; 240 return size;
259} 241}
260 242
261static int efi_pstore_write(enum pstore_type_id type, 243static int efi_pstore_write(struct pstore_record *record)
262 enum kmsg_dump_reason reason, u64 *id,
263 unsigned int part, int count, bool compressed, size_t size,
264 struct pstore_info *psi)
265{ 244{
266 char name[DUMP_NAME_LEN]; 245 char name[DUMP_NAME_LEN];
267 efi_char16_t efi_name[DUMP_NAME_LEN]; 246 efi_char16_t efi_name[DUMP_NAME_LEN];
268 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 247 efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
269 int i, ret = 0; 248 int i, ret = 0;
270 249
271 sprintf(name, "dump-type%u-%u-%d-%lu-%c", type, part, count, 250 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c",
272 get_seconds(), compressed ? 'C' : 'D'); 251 record->type, record->part, record->count,
252 get_seconds(), record->compressed ? 'C' : 'D');
273 253
274 for (i = 0; i < DUMP_NAME_LEN; i++) 254 for (i = 0; i < DUMP_NAME_LEN; i++)
275 efi_name[i] = name[i]; 255 efi_name[i] = name[i];
276 256
277 ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES, 257 ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES,
278 !pstore_cannot_block_path(reason), 258 !pstore_cannot_block_path(record->reason),
279 size, psi->buf); 259 record->size, record->psi->buf);
280 260
281 if (reason == KMSG_DUMP_OOPS) 261 if (record->reason == KMSG_DUMP_OOPS)
282 efivar_run_worker(); 262 efivar_run_worker();
283 263
284 *id = part; 264 record->id = record->part;
285 return ret; 265 return ret;
286}; 266};
287 267
288struct pstore_erase_data { 268struct pstore_erase_data {
289 u64 id; 269 struct pstore_record *record;
290 enum pstore_type_id type;
291 int count;
292 struct timespec time;
293 efi_char16_t *name; 270 efi_char16_t *name;
294}; 271};
295 272
@@ -315,8 +292,9 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
315 * Check if an old format, which doesn't support 292 * Check if an old format, which doesn't support
316 * holding multiple logs, remains. 293 * holding multiple logs, remains.
317 */ 294 */
318 sprintf(name_old, "dump-type%u-%u-%lu", ed->type, 295 snprintf(name_old, sizeof(name_old), "dump-type%u-%u-%lu",
319 (unsigned int)ed->id, ed->time.tv_sec); 296 ed->record->type, (unsigned int)ed->record->id,
297 ed->record->time.tv_sec);
320 298
321 for (i = 0; i < DUMP_NAME_LEN; i++) 299 for (i = 0; i < DUMP_NAME_LEN; i++)
322 efi_name_old[i] = name_old[i]; 300 efi_name_old[i] = name_old[i];
@@ -341,8 +319,7 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
341 return 1; 319 return 1;
342} 320}
343 321
344static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, 322static int efi_pstore_erase(struct pstore_record *record)
345 struct timespec time, struct pstore_info *psi)
346{ 323{
347 struct pstore_erase_data edata; 324 struct pstore_erase_data edata;
348 struct efivar_entry *entry = NULL; 325 struct efivar_entry *entry = NULL;
@@ -351,17 +328,16 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
351 int found, i; 328 int found, i;
352 unsigned int part; 329 unsigned int part;
353 330
354 do_div(id, 1000); 331 do_div(record->id, 1000);
355 part = do_div(id, 100); 332 part = do_div(record->id, 100);
356 sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, time.tv_sec); 333 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu",
334 record->type, record->part, record->count,
335 record->time.tv_sec);
357 336
358 for (i = 0; i < DUMP_NAME_LEN; i++) 337 for (i = 0; i < DUMP_NAME_LEN; i++)
359 efi_name[i] = name[i]; 338 efi_name[i] = name[i];
360 339
361 edata.id = part; 340 edata.record = record;
362 edata.type = type;
363 edata.count = count;
364 edata.time = time;
365 edata.name = efi_name; 341 edata.name = efi_name;
366 342
367 if (efivar_entry_iter_begin()) 343 if (efivar_entry_iter_begin())
diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c
index 899d0ba0bd6c..06aab07b6bb7 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(&record);
51 0, sizeof(rec), psinfo);
52 57
53 local_irq_restore(flags); 58 local_irq_restore(flags);
54} 59}
@@ -117,7 +122,7 @@ void pstore_register_ftrace(void)
117{ 122{
118 struct dentry *file; 123 struct dentry *file;
119 124
120 if (!psinfo->write_buf) 125 if (!psinfo->write)
121 return; 126 return;
122 127
123 pstore_ftrace_dir = debugfs_create_dir("pstore", NULL); 128 pstore_ftrace_dir = debugfs_create_dir("pstore", NULL);
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 57c0646479f5..792a4e5f9226 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -47,12 +47,8 @@ static LIST_HEAD(allpstore);
47 47
48struct pstore_private { 48struct pstore_private {
49 struct list_head list; 49 struct list_head list;
50 struct pstore_info *psi; 50 struct pstore_record *record;
51 enum pstore_type_id type; 51 size_t total_size;
52 u64 id;
53 int count;
54 ssize_t size;
55 char data[];
56}; 52};
57 53
58struct pstore_ftrace_seq_data { 54struct pstore_ftrace_seq_data {
@@ -63,6 +59,17 @@ struct pstore_ftrace_seq_data {
63 59
64#define REC_SIZE sizeof(struct pstore_ftrace_record) 60#define REC_SIZE sizeof(struct pstore_ftrace_record)
65 61
62static void free_pstore_private(struct pstore_private *private)
63{
64 if (!private)
65 return;
66 if (private->record) {
67 kfree(private->record->buf);
68 kfree(private->record);
69 }
70 kfree(private);
71}
72
66static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos) 73static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
67{ 74{
68 struct pstore_private *ps = s->private; 75 struct pstore_private *ps = s->private;
@@ -72,9 +79,9 @@ static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
72 if (!data) 79 if (!data)
73 return NULL; 80 return NULL;
74 81
75 data->off = ps->size % REC_SIZE; 82 data->off = ps->total_size % REC_SIZE;
76 data->off += *pos * REC_SIZE; 83 data->off += *pos * REC_SIZE;
77 if (data->off + REC_SIZE > ps->size) { 84 if (data->off + REC_SIZE > ps->total_size) {
78 kfree(data); 85 kfree(data);
79 return NULL; 86 return NULL;
80 } 87 }
@@ -94,7 +101,7 @@ static void *pstore_ftrace_seq_next(struct seq_file *s, void *v, loff_t *pos)
94 struct pstore_ftrace_seq_data *data = v; 101 struct pstore_ftrace_seq_data *data = v;
95 102
96 data->off += REC_SIZE; 103 data->off += REC_SIZE;
97 if (data->off + REC_SIZE > ps->size) 104 if (data->off + REC_SIZE > ps->total_size)
98 return NULL; 105 return NULL;
99 106
100 (*pos)++; 107 (*pos)++;
@@ -105,7 +112,9 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
105{ 112{
106 struct pstore_private *ps = s->private; 113 struct pstore_private *ps = s->private;
107 struct pstore_ftrace_seq_data *data = v; 114 struct pstore_ftrace_seq_data *data = v;
108 struct pstore_ftrace_record *rec = (void *)(ps->data + data->off); 115 struct pstore_ftrace_record *rec;
116
117 rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off);
109 118
110 seq_printf(s, "CPU:%d ts:%llu %08lx %08lx %pf <- %pF\n", 119 seq_printf(s, "CPU:%d ts:%llu %08lx %08lx %pf <- %pF\n",
111 pstore_ftrace_decode_cpu(rec), 120 pstore_ftrace_decode_cpu(rec),
@@ -125,7 +134,7 @@ static const struct seq_operations pstore_ftrace_seq_ops = {
125 134
126static int pstore_check_syslog_permissions(struct pstore_private *ps) 135static int pstore_check_syslog_permissions(struct pstore_private *ps)
127{ 136{
128 switch (ps->type) { 137 switch (ps->record->type) {
129 case PSTORE_TYPE_DMESG: 138 case PSTORE_TYPE_DMESG:
130 case PSTORE_TYPE_CONSOLE: 139 case PSTORE_TYPE_CONSOLE:
131 return check_syslog_permissions(SYSLOG_ACTION_READ_ALL, 140 return check_syslog_permissions(SYSLOG_ACTION_READ_ALL,
@@ -141,9 +150,10 @@ static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
141 struct seq_file *sf = file->private_data; 150 struct seq_file *sf = file->private_data;
142 struct pstore_private *ps = sf->private; 151 struct pstore_private *ps = sf->private;
143 152
144 if (ps->type == PSTORE_TYPE_FTRACE) 153 if (ps->record->type == PSTORE_TYPE_FTRACE)
145 return seq_read(file, userbuf, count, ppos); 154 return seq_read(file, userbuf, count, ppos);
146 return simple_read_from_buffer(userbuf, count, ppos, ps->data, ps->size); 155 return simple_read_from_buffer(userbuf, count, ppos,
156 ps->record->buf, ps->total_size);
147} 157}
148 158
149static int pstore_file_open(struct inode *inode, struct file *file) 159static int pstore_file_open(struct inode *inode, struct file *file)
@@ -157,7 +167,7 @@ static int pstore_file_open(struct inode *inode, struct file *file)
157 if (err) 167 if (err)
158 return err; 168 return err;
159 169
160 if (ps->type == PSTORE_TYPE_FTRACE) 170 if (ps->record->type == PSTORE_TYPE_FTRACE)
161 sops = &pstore_ftrace_seq_ops; 171 sops = &pstore_ftrace_seq_ops;
162 172
163 err = seq_open(file, sops); 173 err = seq_open(file, sops);
@@ -193,20 +203,19 @@ static const struct file_operations pstore_file_operations = {
193static int pstore_unlink(struct inode *dir, struct dentry *dentry) 203static int pstore_unlink(struct inode *dir, struct dentry *dentry)
194{ 204{
195 struct pstore_private *p = d_inode(dentry)->i_private; 205 struct pstore_private *p = d_inode(dentry)->i_private;
206 struct pstore_record *record = p->record;
196 int err; 207 int err;
197 208
198 err = pstore_check_syslog_permissions(p); 209 err = pstore_check_syslog_permissions(p);
199 if (err) 210 if (err)
200 return err; 211 return err;
201 212
202 if (p->psi->erase) { 213 if (!record->psi->erase)
203 mutex_lock(&p->psi->read_mutex);
204 p->psi->erase(p->type, p->id, p->count,
205 d_inode(dentry)->i_ctime, p->psi);
206 mutex_unlock(&p->psi->read_mutex);
207 } else {
208 return -EPERM; 214 return -EPERM;
209 } 215
216 mutex_lock(&record->psi->read_mutex);
217 record->psi->erase(record);
218 mutex_unlock(&record->psi->read_mutex);
210 219
211 return simple_unlink(dir, dentry); 220 return simple_unlink(dir, dentry);
212} 221}
@@ -221,7 +230,7 @@ static void pstore_evict_inode(struct inode *inode)
221 spin_lock_irqsave(&allpstore_lock, flags); 230 spin_lock_irqsave(&allpstore_lock, flags);
222 list_del(&p->list); 231 list_del(&p->list);
223 spin_unlock_irqrestore(&allpstore_lock, flags); 232 spin_unlock_irqrestore(&allpstore_lock, flags);
224 kfree(p); 233 free_pstore_private(p);
225 } 234 }
226} 235}
227 236
@@ -302,23 +311,23 @@ bool pstore_is_mounted(void)
302 * Load it up with "size" bytes of data from "buf". 311 * Load it up with "size" bytes of data from "buf".
303 * Set the mtime & ctime to the date that this record was originally stored. 312 * Set the mtime & ctime to the date that this record was originally stored.
304 */ 313 */
305int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count, 314int pstore_mkfile(struct dentry *root, struct pstore_record *record)
306 char *data, bool compressed, size_t size,
307 struct timespec time, struct pstore_info *psi)
308{ 315{
309 struct dentry *root = pstore_sb->s_root;
310 struct dentry *dentry; 316 struct dentry *dentry;
311 struct inode *inode; 317 struct inode *inode;
312 int rc = 0; 318 int rc = 0;
313 char name[PSTORE_NAMELEN]; 319 char name[PSTORE_NAMELEN];
314 struct pstore_private *private, *pos; 320 struct pstore_private *private, *pos;
315 unsigned long flags; 321 unsigned long flags;
322 size_t size = record->size + record->ecc_notice_size;
323
324 WARN_ON(!inode_is_locked(d_inode(root)));
316 325
317 spin_lock_irqsave(&allpstore_lock, flags); 326 spin_lock_irqsave(&allpstore_lock, flags);
318 list_for_each_entry(pos, &allpstore, list) { 327 list_for_each_entry(pos, &allpstore, list) {
319 if (pos->type == type && 328 if (pos->record->type == record->type &&
320 pos->id == id && 329 pos->record->id == record->id &&
321 pos->psi == psi) { 330 pos->record->psi == record->psi) {
322 rc = -EEXIST; 331 rc = -EEXIST;
323 break; 332 break;
324 } 333 }
@@ -328,72 +337,74 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
328 return rc; 337 return rc;
329 338
330 rc = -ENOMEM; 339 rc = -ENOMEM;
331 inode = pstore_get_inode(pstore_sb); 340 inode = pstore_get_inode(root->d_sb);
332 if (!inode) 341 if (!inode)
333 goto fail; 342 goto fail;
334 inode->i_mode = S_IFREG | 0444; 343 inode->i_mode = S_IFREG | 0444;
335 inode->i_fop = &pstore_file_operations; 344 inode->i_fop = &pstore_file_operations;
336 private = kmalloc(sizeof *private + size, GFP_KERNEL); 345 private = kzalloc(sizeof(*private), GFP_KERNEL);
337 if (!private) 346 if (!private)
338 goto fail_alloc; 347 goto fail_alloc;
339 private->type = type; 348 private->record = record;
340 private->id = id;
341 private->count = count;
342 private->psi = psi;
343 349
344 switch (type) { 350 switch (record->type) {
345 case PSTORE_TYPE_DMESG: 351 case PSTORE_TYPE_DMESG:
346 scnprintf(name, sizeof(name), "dmesg-%s-%lld%s", 352 scnprintf(name, sizeof(name), "dmesg-%s-%lld%s",
347 psname, id, compressed ? ".enc.z" : ""); 353 record->psi->name, record->id,
354 record->compressed ? ".enc.z" : "");
348 break; 355 break;
349 case PSTORE_TYPE_CONSOLE: 356 case PSTORE_TYPE_CONSOLE:
350 scnprintf(name, sizeof(name), "console-%s-%lld", psname, id); 357 scnprintf(name, sizeof(name), "console-%s-%lld",
358 record->psi->name, record->id);
351 break; 359 break;
352 case PSTORE_TYPE_FTRACE: 360 case PSTORE_TYPE_FTRACE:
353 scnprintf(name, sizeof(name), "ftrace-%s-%lld", psname, id); 361 scnprintf(name, sizeof(name), "ftrace-%s-%lld",
362 record->psi->name, record->id);
354 break; 363 break;
355 case PSTORE_TYPE_MCE: 364 case PSTORE_TYPE_MCE:
356 scnprintf(name, sizeof(name), "mce-%s-%lld", psname, id); 365 scnprintf(name, sizeof(name), "mce-%s-%lld",
366 record->psi->name, record->id);
357 break; 367 break;
358 case PSTORE_TYPE_PPC_RTAS: 368 case PSTORE_TYPE_PPC_RTAS:
359 scnprintf(name, sizeof(name), "rtas-%s-%lld", psname, id); 369 scnprintf(name, sizeof(name), "rtas-%s-%lld",
370 record->psi->name, record->id);
360 break; 371 break;
361 case PSTORE_TYPE_PPC_OF: 372 case PSTORE_TYPE_PPC_OF:
362 scnprintf(name, sizeof(name), "powerpc-ofw-%s-%lld", 373 scnprintf(name, sizeof(name), "powerpc-ofw-%s-%lld",
363 psname, id); 374 record->psi->name, record->id);
364 break; 375 break;
365 case PSTORE_TYPE_PPC_COMMON: 376 case PSTORE_TYPE_PPC_COMMON:
366 scnprintf(name, sizeof(name), "powerpc-common-%s-%lld", 377 scnprintf(name, sizeof(name), "powerpc-common-%s-%lld",
367 psname, id); 378 record->psi->name, record->id);
368 break; 379 break;
369 case PSTORE_TYPE_PMSG: 380 case PSTORE_TYPE_PMSG:
370 scnprintf(name, sizeof(name), "pmsg-%s-%lld", psname, id); 381 scnprintf(name, sizeof(name), "pmsg-%s-%lld",
382 record->psi->name, record->id);
371 break; 383 break;
372 case PSTORE_TYPE_PPC_OPAL: 384 case PSTORE_TYPE_PPC_OPAL:
373 sprintf(name, "powerpc-opal-%s-%lld", psname, id); 385 scnprintf(name, sizeof(name), "powerpc-opal-%s-%lld",
386 record->psi->name, record->id);
374 break; 387 break;
375 case PSTORE_TYPE_UNKNOWN: 388 case PSTORE_TYPE_UNKNOWN:
376 scnprintf(name, sizeof(name), "unknown-%s-%lld", psname, id); 389 scnprintf(name, sizeof(name), "unknown-%s-%lld",
390 record->psi->name, record->id);
377 break; 391 break;
378 default: 392 default:
379 scnprintf(name, sizeof(name), "type%d-%s-%lld", 393 scnprintf(name, sizeof(name), "type%d-%s-%lld",
380 type, psname, id); 394 record->type, record->psi->name, record->id);
381 break; 395 break;
382 } 396 }
383 397
384 inode_lock(d_inode(root));
385
386 dentry = d_alloc_name(root, name); 398 dentry = d_alloc_name(root, name);
387 if (!dentry) 399 if (!dentry)
388 goto fail_lockedalloc; 400 goto fail_private;
389 401
390 memcpy(private->data, data, size); 402 inode->i_size = private->total_size = size;
391 inode->i_size = private->size = size;
392 403
393 inode->i_private = private; 404 inode->i_private = private;
394 405
395 if (time.tv_sec) 406 if (record->time.tv_sec)
396 inode->i_mtime = inode->i_ctime = time; 407 inode->i_mtime = inode->i_ctime = record->time;
397 408
398 d_add(dentry, inode); 409 d_add(dentry, inode);
399 410
@@ -401,13 +412,10 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
401 list_add(&private->list, &allpstore); 412 list_add(&private->list, &allpstore);
402 spin_unlock_irqrestore(&allpstore_lock, flags); 413 spin_unlock_irqrestore(&allpstore_lock, flags);
403 414
404 inode_unlock(d_inode(root));
405
406 return 0; 415 return 0;
407 416
408fail_lockedalloc: 417fail_private:
409 inode_unlock(d_inode(root)); 418 free_pstore_private(private);
410 kfree(private);
411fail_alloc: 419fail_alloc:
412 iput(inode); 420 iput(inode);
413 421
@@ -415,6 +423,27 @@ fail:
415 return rc; 423 return rc;
416} 424}
417 425
426/*
427 * Read all the records from the persistent store. Create
428 * files in our filesystem. Don't warn about -EEXIST errors
429 * when we are re-scanning the backing store looking to add new
430 * error records.
431 */
432void pstore_get_records(int quiet)
433{
434 struct pstore_info *psi = psinfo;
435 struct dentry *root;
436
437 if (!psi || !pstore_sb)
438 return;
439
440 root = pstore_sb->s_root;
441
442 inode_lock(d_inode(root));
443 pstore_get_backend_records(psi, root, quiet);
444 inode_unlock(d_inode(root));
445}
446
418static int pstore_fill_super(struct super_block *sb, void *data, int silent) 447static int pstore_fill_super(struct super_block *sb, void *data, int silent)
419{ 448{
420 struct inode *inode; 449 struct inode *inode;
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index da416e6591c9..c416e653dc4f 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -25,10 +25,10 @@ extern struct pstore_info *psinfo;
25 25
26extern void pstore_set_kmsg_bytes(int); 26extern void pstore_set_kmsg_bytes(int);
27extern void pstore_get_records(int); 27extern void pstore_get_records(int);
28extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, 28extern void pstore_get_backend_records(struct pstore_info *psi,
29 int count, char *data, bool compressed, 29 struct dentry *root, int quiet);
30 size_t size, struct timespec time, 30extern int pstore_mkfile(struct dentry *root,
31 struct pstore_info *psi); 31 struct pstore_record *record);
32extern bool pstore_is_mounted(void); 32extern bool pstore_is_mounted(void);
33 33
34#endif 34#endif
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index efab7b64925b..d468eec9b8a6 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -267,7 +267,7 @@ static void free_zlib(void)
267 big_oops_buf_sz = 0; 267 big_oops_buf_sz = 0;
268} 268}
269 269
270static struct pstore_zbackend backend_zlib = { 270static const struct pstore_zbackend backend_zlib = {
271 .compress = compress_zlib, 271 .compress = compress_zlib,
272 .decompress = decompress_zlib, 272 .decompress = decompress_zlib,
273 .allocate = allocate_zlib, 273 .allocate = allocate_zlib,
@@ -328,7 +328,7 @@ static void free_lzo(void)
328 big_oops_buf_sz = 0; 328 big_oops_buf_sz = 0;
329} 329}
330 330
331static struct pstore_zbackend backend_lzo = { 331static const struct pstore_zbackend backend_lzo = {
332 .compress = compress_lzo, 332 .compress = compress_lzo,
333 .decompress = decompress_lzo, 333 .decompress = decompress_lzo,
334 .allocate = allocate_lzo, 334 .allocate = allocate_lzo,
@@ -393,7 +393,7 @@ static void free_lz4(void)
393 big_oops_buf_sz = 0; 393 big_oops_buf_sz = 0;
394} 394}
395 395
396static struct pstore_zbackend backend_lz4 = { 396static const struct pstore_zbackend backend_lz4 = {
397 .compress = compress_lz4, 397 .compress = compress_lz4,
398 .decompress = decompress_lz4, 398 .decompress = decompress_lz4,
399 .allocate = allocate_lz4, 399 .allocate = allocate_lz4,
@@ -402,7 +402,7 @@ static struct pstore_zbackend backend_lz4 = {
402}; 402};
403#endif 403#endif
404 404
405static struct pstore_zbackend *zbackend = 405static const struct pstore_zbackend *zbackend =
406#if defined(CONFIG_PSTORE_ZLIB_COMPRESS) 406#if defined(CONFIG_PSTORE_ZLIB_COMPRESS)
407 &backend_zlib; 407 &backend_zlib;
408#elif defined(CONFIG_PSTORE_LZO_COMPRESS) 408#elif defined(CONFIG_PSTORE_LZO_COMPRESS)
@@ -484,7 +484,6 @@ static void pstore_dump(struct kmsg_dumper *dumper,
484{ 484{
485 unsigned long total = 0; 485 unsigned long total = 0;
486 const char *why; 486 const char *why;
487 u64 id;
488 unsigned int part = 1; 487 unsigned int part = 1;
489 unsigned long flags = 0; 488 unsigned long flags = 0;
490 int is_locked; 489 int is_locked;
@@ -506,48 +505,59 @@ static void pstore_dump(struct kmsg_dumper *dumper,
506 oopscount++; 505 oopscount++;
507 while (total < kmsg_bytes) { 506 while (total < kmsg_bytes) {
508 char *dst; 507 char *dst;
509 unsigned long size; 508 size_t dst_size;
510 int hsize; 509 int header_size;
511 int zipped_len = -1; 510 int zipped_len = -1;
512 size_t len; 511 size_t dump_size;
513 bool compressed = false; 512 struct pstore_record record = {
514 size_t total_len; 513 .type = PSTORE_TYPE_DMESG,
514 .count = oopscount,
515 .reason = reason,
516 .part = part,
517 .compressed = false,
518 .buf = psinfo->buf,
519 .psi = psinfo,
520 };
515 521
516 if (big_oops_buf && is_locked) { 522 if (big_oops_buf && is_locked) {
517 dst = big_oops_buf; 523 dst = big_oops_buf;
518 size = big_oops_buf_sz; 524 dst_size = big_oops_buf_sz;
519 } else { 525 } else {
520 dst = psinfo->buf; 526 dst = psinfo->buf;
521 size = psinfo->bufsize; 527 dst_size = psinfo->bufsize;
522 } 528 }
523 529
524 hsize = sprintf(dst, "%s#%d Part%u\n", why, oopscount, part); 530 /* Write dump header. */
525 size -= hsize; 531 header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
532 oopscount, part);
533 dst_size -= header_size;
526 534
527 if (!kmsg_dump_get_buffer(dumper, true, dst + hsize, 535 /* Write dump contents. */
528 size, &len)) 536 if (!kmsg_dump_get_buffer(dumper, true, dst + header_size,
537 dst_size, &dump_size))
529 break; 538 break;
530 539
531 if (big_oops_buf && is_locked) { 540 if (big_oops_buf && is_locked) {
532 zipped_len = pstore_compress(dst, psinfo->buf, 541 zipped_len = pstore_compress(dst, psinfo->buf,
533 hsize + len, psinfo->bufsize); 542 header_size + dump_size,
543 psinfo->bufsize);
534 544
535 if (zipped_len > 0) { 545 if (zipped_len > 0) {
536 compressed = true; 546 record.compressed = true;
537 total_len = zipped_len; 547 record.size = zipped_len;
538 } else { 548 } else {
539 total_len = copy_kmsg_to_buffer(hsize, len); 549 record.size = copy_kmsg_to_buffer(header_size,
550 dump_size);
540 } 551 }
541 } else { 552 } else {
542 total_len = hsize + len; 553 record.size = header_size + dump_size;
543 } 554 }
544 555
545 ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part, 556 ret = psinfo->write(&record);
546 oopscount, compressed, total_len, psinfo);
547 if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted()) 557 if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
548 pstore_new_entry = 1; 558 pstore_new_entry = 1;
549 559
550 total += total_len; 560 total += record.size;
551 part++; 561 part++;
552 } 562 }
553 if (is_locked) 563 if (is_locked)
@@ -577,8 +587,11 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
577 const char *e = s + c; 587 const char *e = s + c;
578 588
579 while (s < e) { 589 while (s < e) {
590 struct pstore_record record = {
591 .type = PSTORE_TYPE_CONSOLE,
592 .psi = psinfo,
593 };
580 unsigned long flags; 594 unsigned long flags;
581 u64 id;
582 595
583 if (c > psinfo->bufsize) 596 if (c > psinfo->bufsize)
584 c = psinfo->bufsize; 597 c = psinfo->bufsize;
@@ -589,8 +602,9 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
589 } else { 602 } else {
590 spin_lock_irqsave(&psinfo->buf_lock, flags); 603 spin_lock_irqsave(&psinfo->buf_lock, flags);
591 } 604 }
592 psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0, 605 record.buf = (char *)s;
593 s, 0, c, psinfo); 606 record.size = c;
607 psinfo->write(&record);
594 spin_unlock_irqrestore(&psinfo->buf_lock, flags); 608 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
595 s += c; 609 s += c;
596 c = e - s; 610 c = e - s;
@@ -618,48 +632,30 @@ static void pstore_register_console(void) {}
618static void pstore_unregister_console(void) {} 632static void pstore_unregister_console(void) {}
619#endif 633#endif
620 634
621static int pstore_write_compat(enum pstore_type_id type, 635static int pstore_write_user_compat(struct pstore_record *record,
622 enum kmsg_dump_reason reason, 636 const char __user *buf)
623 u64 *id, unsigned int part, int count, 637{
624 bool compressed, size_t size, 638 int ret = 0;
625 struct pstore_info *psi) 639
626{ 640 if (record->buf)
627 return psi->write_buf(type, reason, id, part, psinfo->buf, compressed, 641 return -EINVAL;
628 size, psi); 642
629} 643 record->buf = kmalloc(record->size, GFP_KERNEL);
630 644 if (!record->buf)
631static int pstore_write_buf_user_compat(enum pstore_type_id type, 645 return -ENOMEM;
632 enum kmsg_dump_reason reason, 646
633 u64 *id, unsigned int part, 647 if (unlikely(copy_from_user(record->buf, buf, record->size))) {
634 const char __user *buf, 648 ret = -EFAULT;
635 bool compressed, size_t size, 649 goto out;
636 struct pstore_info *psi)
637{
638 unsigned long flags = 0;
639 size_t i, bufsize = size;
640 long ret = 0;
641
642 if (unlikely(!access_ok(VERIFY_READ, buf, size)))
643 return -EFAULT;
644 if (bufsize > psinfo->bufsize)
645 bufsize = psinfo->bufsize;
646 spin_lock_irqsave(&psinfo->buf_lock, flags);
647 for (i = 0; i < size; ) {
648 size_t c = min(size - i, bufsize);
649
650 ret = __copy_from_user(psinfo->buf, buf + i, c);
651 if (unlikely(ret != 0)) {
652 ret = -EFAULT;
653 break;
654 }
655 ret = psi->write_buf(type, reason, id, part, psinfo->buf,
656 compressed, c, psi);
657 if (unlikely(ret < 0))
658 break;
659 i += c;
660 } 650 }
661 spin_unlock_irqrestore(&psinfo->buf_lock, flags); 651
662 return unlikely(ret < 0) ? ret : size; 652 ret = record->psi->write(record);
653
654out:
655 kfree(record->buf);
656 record->buf = NULL;
657
658 return unlikely(ret < 0) ? ret : record->size;
663} 659}
664 660
665/* 661/*
@@ -673,19 +669,35 @@ int pstore_register(struct pstore_info *psi)
673{ 669{
674 struct module *owner = psi->owner; 670 struct module *owner = psi->owner;
675 671
676 if (backend && strcmp(backend, psi->name)) 672 if (backend && strcmp(backend, psi->name)) {
673 pr_warn("ignoring unexpected backend '%s'\n", psi->name);
677 return -EPERM; 674 return -EPERM;
675 }
676
677 /* Sanity check flags. */
678 if (!psi->flags) {
679 pr_warn("backend '%s' must support at least one frontend\n",
680 psi->name);
681 return -EINVAL;
682 }
683
684 /* Check for required functions. */
685 if (!psi->read || !psi->write) {
686 pr_warn("backend '%s' must implement read() and write()\n",
687 psi->name);
688 return -EINVAL;
689 }
678 690
679 spin_lock(&pstore_lock); 691 spin_lock(&pstore_lock);
680 if (psinfo) { 692 if (psinfo) {
693 pr_warn("backend '%s' already loaded: ignoring '%s'\n",
694 psinfo->name, psi->name);
681 spin_unlock(&pstore_lock); 695 spin_unlock(&pstore_lock);
682 return -EBUSY; 696 return -EBUSY;
683 } 697 }
684 698
685 if (!psi->write) 699 if (!psi->write_user)
686 psi->write = pstore_write_compat; 700 psi->write_user = pstore_write_user_compat;
687 if (!psi->write_buf_user)
688 psi->write_buf_user = pstore_write_buf_user_compat;
689 psinfo = psi; 701 psinfo = psi;
690 mutex_init(&psinfo->read_mutex); 702 mutex_init(&psinfo->read_mutex);
691 spin_unlock(&pstore_lock); 703 spin_unlock(&pstore_lock);
@@ -709,6 +721,7 @@ int pstore_register(struct pstore_info *psi)
709 if (psi->flags & PSTORE_FLAGS_PMSG) 721 if (psi->flags & PSTORE_FLAGS_PMSG)
710 pstore_register_pmsg(); 722 pstore_register_pmsg();
711 723
724 /* Start watching for new records, if desired. */
712 if (pstore_update_ms >= 0) { 725 if (pstore_update_ms >= 0) {
713 pstore_timer.expires = jiffies + 726 pstore_timer.expires = jiffies +
714 msecs_to_jiffies(pstore_update_ms); 727 msecs_to_jiffies(pstore_update_ms);
@@ -721,16 +734,21 @@ int pstore_register(struct pstore_info *psi)
721 */ 734 */
722 backend = psi->name; 735 backend = psi->name;
723 736
724 module_put(owner);
725
726 pr_info("Registered %s as persistent store backend\n", psi->name); 737 pr_info("Registered %s as persistent store backend\n", psi->name);
727 738
739 module_put(owner);
740
728 return 0; 741 return 0;
729} 742}
730EXPORT_SYMBOL_GPL(pstore_register); 743EXPORT_SYMBOL_GPL(pstore_register);
731 744
732void pstore_unregister(struct pstore_info *psi) 745void pstore_unregister(struct pstore_info *psi)
733{ 746{
747 /* Stop timer and make sure all work has finished. */
748 pstore_update_ms = -1;
749 del_timer_sync(&pstore_timer);
750 flush_work(&pstore_work);
751
734 if (psi->flags & PSTORE_FLAGS_PMSG) 752 if (psi->flags & PSTORE_FLAGS_PMSG)
735 pstore_unregister_pmsg(); 753 pstore_unregister_pmsg();
736 if (psi->flags & PSTORE_FLAGS_FTRACE) 754 if (psi->flags & PSTORE_FLAGS_FTRACE)
@@ -747,66 +765,99 @@ void pstore_unregister(struct pstore_info *psi)
747} 765}
748EXPORT_SYMBOL_GPL(pstore_unregister); 766EXPORT_SYMBOL_GPL(pstore_unregister);
749 767
768static void decompress_record(struct pstore_record *record)
769{
770 int unzipped_len;
771 char *decompressed;
772
773 /* Only PSTORE_TYPE_DMESG support compression. */
774 if (!record->compressed || record->type != PSTORE_TYPE_DMESG) {
775 pr_warn("ignored compressed record type %d\n", record->type);
776 return;
777 }
778
779 /* No compression method has created the common buffer. */
780 if (!big_oops_buf) {
781 pr_warn("no decompression buffer allocated\n");
782 return;
783 }
784
785 unzipped_len = pstore_decompress(record->buf, big_oops_buf,
786 record->size, big_oops_buf_sz);
787 if (unzipped_len <= 0) {
788 pr_err("decompression failed: %d\n", unzipped_len);
789 return;
790 }
791
792 /* Build new buffer for decompressed contents. */
793 decompressed = kmalloc(unzipped_len + record->ecc_notice_size,
794 GFP_KERNEL);
795 if (!decompressed) {
796 pr_err("decompression ran out of memory\n");
797 return;
798 }
799 memcpy(decompressed, big_oops_buf, unzipped_len);
800
801 /* Append ECC notice to decompressed buffer. */
802 memcpy(decompressed + unzipped_len, record->buf + record->size,
803 record->ecc_notice_size);
804
805 /* Swap out compresed contents with decompressed contents. */
806 kfree(record->buf);
807 record->buf = decompressed;
808 record->size = unzipped_len;
809 record->compressed = false;
810}
811
750/* 812/*
751 * Read all the records from the persistent store. Create 813 * Read all the records from one persistent store backend. Create
752 * files in our filesystem. Don't warn about -EEXIST errors 814 * files in our filesystem. Don't warn about -EEXIST errors
753 * when we are re-scanning the backing store looking to add new 815 * when we are re-scanning the backing store looking to add new
754 * error records. 816 * error records.
755 */ 817 */
756void pstore_get_records(int quiet) 818void pstore_get_backend_records(struct pstore_info *psi,
757{ 819 struct dentry *root, int quiet)
758 struct pstore_info *psi = psinfo; 820{
759 char *buf = NULL; 821 int failed = 0;
760 ssize_t size; 822
761 u64 id; 823 if (!psi || !root)
762 int count;
763 enum pstore_type_id type;
764 struct timespec time;
765 int failed = 0, rc;
766 bool compressed;
767 int unzipped_len = -1;
768 ssize_t ecc_notice_size = 0;
769
770 if (!psi)
771 return; 824 return;
772 825
773 mutex_lock(&psi->read_mutex); 826 mutex_lock(&psi->read_mutex);
774 if (psi->open && psi->open(psi)) 827 if (psi->open && psi->open(psi))
775 goto out; 828 goto out;
776 829
777 while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed, 830 /*
778 &ecc_notice_size, psi)) > 0) { 831 * Backend callback read() allocates record.buf. decompress_record()
779 if (compressed && (type == PSTORE_TYPE_DMESG)) { 832 * may reallocate record.buf. On success, pstore_mkfile() will keep
780 if (big_oops_buf) 833 * the record.buf, so free it only on failure.
781 unzipped_len = pstore_decompress(buf, 834 */
782 big_oops_buf, size, 835 for (;;) {
783 big_oops_buf_sz); 836 struct pstore_record *record;
784 837 int rc;
785 if (unzipped_len > 0) { 838
786 if (ecc_notice_size) 839 record = kzalloc(sizeof(*record), GFP_KERNEL);
787 memcpy(big_oops_buf + unzipped_len, 840 if (!record) {
788 buf + size, ecc_notice_size); 841 pr_err("out of memory creating record\n");
789 kfree(buf); 842 break;
790 buf = big_oops_buf; 843 }
791 size = unzipped_len; 844 record->psi = psi;
792 compressed = false; 845
793 } else { 846 record->size = psi->read(record);
794 pr_err("decompression failed;returned %d\n", 847
795 unzipped_len); 848 /* No more records left in backend? */
796 compressed = true; 849 if (record->size <= 0)
797 } 850 break;
851
852 decompress_record(record);
853 rc = pstore_mkfile(root, record);
854 if (rc) {
855 /* pstore_mkfile() did not take record, so free it. */
856 kfree(record->buf);
857 kfree(record);
858 if (rc != -EEXIST || !quiet)
859 failed++;
798 } 860 }
799 rc = pstore_mkfile(type, psi->name, id, count, buf,
800 compressed, size + ecc_notice_size,
801 time, psi);
802 if (unzipped_len < 0) {
803 /* Free buffer other than big oops */
804 kfree(buf);
805 buf = NULL;
806 } else
807 unzipped_len = -1;
808 if (rc && (rc != -EEXIST || !quiet))
809 failed++;
810 } 861 }
811 if (psi->close) 862 if (psi->close)
812 psi->close(psi); 863 psi->close(psi);
@@ -830,7 +881,9 @@ static void pstore_timefunc(unsigned long dummy)
830 schedule_work(&pstore_work); 881 schedule_work(&pstore_work);
831 } 882 }
832 883
833 mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms)); 884 if (pstore_update_ms >= 0)
885 mod_timer(&pstore_timer,
886 jiffies + msecs_to_jiffies(pstore_update_ms));
834} 887}
835 888
836module_param(backend, charp, 0444); 889module_param(backend, charp, 0444);
diff --git a/fs/pstore/pmsg.c b/fs/pstore/pmsg.c
index 78f6176c020f..209755e0d7c8 100644
--- a/fs/pstore/pmsg.c
+++ b/fs/pstore/pmsg.c
@@ -15,7 +15,6 @@
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/uaccess.h> 17#include <linux/uaccess.h>
18#include <linux/vmalloc.h>
19#include "internal.h" 18#include "internal.h"
20 19
21static DEFINE_MUTEX(pmsg_lock); 20static DEFINE_MUTEX(pmsg_lock);
@@ -23,19 +22,22 @@ static DEFINE_MUTEX(pmsg_lock);
23static ssize_t write_pmsg(struct file *file, const char __user *buf, 22static ssize_t write_pmsg(struct file *file, const char __user *buf,
24 size_t count, loff_t *ppos) 23 size_t count, loff_t *ppos)
25{ 24{
26 u64 id; 25 struct pstore_record record = {
26 .type = PSTORE_TYPE_PMSG,
27 .size = count,
28 .psi = psinfo,
29 };
27 int ret; 30 int ret;
28 31
29 if (!count) 32 if (!count)
30 return 0; 33 return 0;
31 34
32 /* check outside lock, page in any data. write_buf_user also checks */ 35 /* check outside lock, page in any data. write_user also checks */
33 if (!access_ok(VERIFY_READ, buf, count)) 36 if (!access_ok(VERIFY_READ, buf, count))
34 return -EFAULT; 37 return -EFAULT;
35 38
36 mutex_lock(&pmsg_lock); 39 mutex_lock(&pmsg_lock);
37 ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, count, 40 ret = psinfo->write_user(&record, buf);
38 psinfo);
39 mutex_unlock(&pmsg_lock); 41 mutex_unlock(&pmsg_lock);
40 return ret ? ret : count; 42 return ret ? ret : count;
41} 43}
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 11f918d34b1e..5523df7f17ef 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -235,35 +235,34 @@ static ssize_t ftrace_log_combine(struct persistent_ram_zone *dest,
235 return 0; 235 return 0;
236} 236}
237 237
238static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, 238static ssize_t ramoops_pstore_read(struct pstore_record *record)
239 int *count, struct timespec *time,
240 char **buf, bool *compressed,
241 ssize_t *ecc_notice_size,
242 struct pstore_info *psi)
243{ 239{
244 ssize_t size = 0; 240 ssize_t size = 0;
245 struct ramoops_context *cxt = psi->data; 241 struct ramoops_context *cxt = record->psi->data;
246 struct persistent_ram_zone *prz = NULL; 242 struct persistent_ram_zone *prz = NULL;
247 int header_length = 0; 243 int header_length = 0;
248 bool free_prz = false; 244 bool free_prz = false;
249 245
250 /* Ramoops headers provide time stamps for PSTORE_TYPE_DMESG, but 246 /*
247 * Ramoops headers provide time stamps for PSTORE_TYPE_DMESG, but
251 * PSTORE_TYPE_CONSOLE and PSTORE_TYPE_FTRACE don't currently have 248 * PSTORE_TYPE_CONSOLE and PSTORE_TYPE_FTRACE don't currently have
252 * valid time stamps, so it is initialized to zero. 249 * valid time stamps, so it is initialized to zero.
253 */ 250 */
254 time->tv_sec = 0; 251 record->time.tv_sec = 0;
255 time->tv_nsec = 0; 252 record->time.tv_nsec = 0;
256 *compressed = false; 253 record->compressed = false;
257 254
258 /* Find the next valid persistent_ram_zone for DMESG */ 255 /* Find the next valid persistent_ram_zone for DMESG */
259 while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) { 256 while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) {
260 prz = ramoops_get_next_prz(cxt->dprzs, &cxt->dump_read_cnt, 257 prz = ramoops_get_next_prz(cxt->dprzs, &cxt->dump_read_cnt,
261 cxt->max_dump_cnt, id, type, 258 cxt->max_dump_cnt, &record->id,
259 &record->type,
262 PSTORE_TYPE_DMESG, 1); 260 PSTORE_TYPE_DMESG, 1);
263 if (!prz_ok(prz)) 261 if (!prz_ok(prz))
264 continue; 262 continue;
265 header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz), 263 header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz),
266 time, compressed); 264 &record->time,
265 &record->compressed);
267 /* Clear and skip this DMESG record if it has no valid header */ 266 /* Clear and skip this DMESG record if it has no valid header */
268 if (!header_length) { 267 if (!header_length) {
269 persistent_ram_free_old(prz); 268 persistent_ram_free_old(prz);
@@ -274,18 +273,20 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
274 273
275 if (!prz_ok(prz)) 274 if (!prz_ok(prz))
276 prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, 275 prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt,
277 1, id, type, PSTORE_TYPE_CONSOLE, 0); 276 1, &record->id, &record->type,
277 PSTORE_TYPE_CONSOLE, 0);
278 278
279 if (!prz_ok(prz)) 279 if (!prz_ok(prz))
280 prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt, 280 prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt,
281 1, id, type, PSTORE_TYPE_PMSG, 0); 281 1, &record->id, &record->type,
282 PSTORE_TYPE_PMSG, 0);
282 283
283 /* ftrace is last since it may want to dynamically allocate memory. */ 284 /* ftrace is last since it may want to dynamically allocate memory. */
284 if (!prz_ok(prz)) { 285 if (!prz_ok(prz)) {
285 if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)) { 286 if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)) {
286 prz = ramoops_get_next_prz(cxt->fprzs, 287 prz = ramoops_get_next_prz(cxt->fprzs,
287 &cxt->ftrace_read_cnt, 1, id, type, 288 &cxt->ftrace_read_cnt, 1, &record->id,
288 PSTORE_TYPE_FTRACE, 0); 289 &record->type, PSTORE_TYPE_FTRACE, 0);
289 } else { 290 } else {
290 /* 291 /*
291 * Build a new dummy record which combines all the 292 * Build a new dummy record which combines all the
@@ -302,8 +303,10 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
302 while (cxt->ftrace_read_cnt < cxt->max_ftrace_cnt) { 303 while (cxt->ftrace_read_cnt < cxt->max_ftrace_cnt) {
303 prz_next = ramoops_get_next_prz(cxt->fprzs, 304 prz_next = ramoops_get_next_prz(cxt->fprzs,
304 &cxt->ftrace_read_cnt, 305 &cxt->ftrace_read_cnt,
305 cxt->max_ftrace_cnt, id, 306 cxt->max_ftrace_cnt,
306 type, PSTORE_TYPE_FTRACE, 0); 307 &record->id,
308 &record->type,
309 PSTORE_TYPE_FTRACE, 0);
307 310
308 if (!prz_ok(prz_next)) 311 if (!prz_ok(prz_next))
309 continue; 312 continue;
@@ -316,7 +319,7 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
316 if (size) 319 if (size)
317 goto out; 320 goto out;
318 } 321 }
319 *id = 0; 322 record->id = 0;
320 prz = tmp_prz; 323 prz = tmp_prz;
321 } 324 }
322 } 325 }
@@ -329,17 +332,19 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
329 size = persistent_ram_old_size(prz) - header_length; 332 size = persistent_ram_old_size(prz) - header_length;
330 333
331 /* ECC correction notice */ 334 /* ECC correction notice */
332 *ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); 335 record->ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0);
333 336
334 *buf = kmalloc(size + *ecc_notice_size + 1, GFP_KERNEL); 337 record->buf = kmalloc(size + record->ecc_notice_size + 1, GFP_KERNEL);
335 if (*buf == NULL) { 338 if (record->buf == NULL) {
336 size = -ENOMEM; 339 size = -ENOMEM;
337 goto out; 340 goto out;
338 } 341 }
339 342
340 memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size); 343 memcpy(record->buf, (char *)persistent_ram_old(prz) + header_length,
344 size);
341 345
342 persistent_ram_ecc_string(prz, *buf + size, *ecc_notice_size + 1); 346 persistent_ram_ecc_string(prz, record->buf + size,
347 record->ecc_notice_size + 1);
343 348
344out: 349out:
345 if (free_prz) { 350 if (free_prz) {
@@ -373,23 +378,18 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz,
373 return len; 378 return len;
374} 379}
375 380
376static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, 381static int notrace ramoops_pstore_write(struct pstore_record *record)
377 enum kmsg_dump_reason reason,
378 u64 *id, unsigned int part,
379 const char *buf,
380 bool compressed, size_t size,
381 struct pstore_info *psi)
382{ 382{
383 struct ramoops_context *cxt = psi->data; 383 struct ramoops_context *cxt = record->psi->data;
384 struct persistent_ram_zone *prz; 384 struct persistent_ram_zone *prz;
385 size_t hlen; 385 size_t size, hlen;
386 386
387 if (type == PSTORE_TYPE_CONSOLE) { 387 if (record->type == PSTORE_TYPE_CONSOLE) {
388 if (!cxt->cprz) 388 if (!cxt->cprz)
389 return -ENOMEM; 389 return -ENOMEM;
390 persistent_ram_write(cxt->cprz, buf, size); 390 persistent_ram_write(cxt->cprz, record->buf, record->size);
391 return 0; 391 return 0;
392 } else if (type == PSTORE_TYPE_FTRACE) { 392 } else if (record->type == PSTORE_TYPE_FTRACE) {
393 int zonenum; 393 int zonenum;
394 394
395 if (!cxt->fprzs) 395 if (!cxt->fprzs)
@@ -402,33 +402,36 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
402 else 402 else
403 zonenum = 0; 403 zonenum = 0;
404 404
405 persistent_ram_write(cxt->fprzs[zonenum], buf, size); 405 persistent_ram_write(cxt->fprzs[zonenum], record->buf,
406 record->size);
406 return 0; 407 return 0;
407 } else if (type == PSTORE_TYPE_PMSG) { 408 } else if (record->type == PSTORE_TYPE_PMSG) {
408 pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__); 409 pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__);
409 return -EINVAL; 410 return -EINVAL;
410 } 411 }
411 412
412 if (type != PSTORE_TYPE_DMESG) 413 if (record->type != PSTORE_TYPE_DMESG)
413 return -EINVAL; 414 return -EINVAL;
414 415
415 /* Out of the various dmesg dump types, ramoops is currently designed 416 /*
417 * Out of the various dmesg dump types, ramoops is currently designed
416 * to only store crash logs, rather than storing general kernel logs. 418 * to only store crash logs, rather than storing general kernel logs.
417 */ 419 */
418 if (reason != KMSG_DUMP_OOPS && 420 if (record->reason != KMSG_DUMP_OOPS &&
419 reason != KMSG_DUMP_PANIC) 421 record->reason != KMSG_DUMP_PANIC)
420 return -EINVAL; 422 return -EINVAL;
421 423
422 /* Skip Oopes when configured to do so. */ 424 /* Skip Oopes when configured to do so. */
423 if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops) 425 if (record->reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
424 return -EINVAL; 426 return -EINVAL;
425 427
426 /* Explicitly only take the first part of any new crash. 428 /*
429 * Explicitly only take the first part of any new crash.
427 * 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,
428 * 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
429 * report split across multiple records. 432 * report split across multiple records.
430 */ 433 */
431 if (part != 1) 434 if (record->part != 1)
432 return -ENOSPC; 435 return -ENOSPC;
433 436
434 if (!cxt->dprzs) 437 if (!cxt->dprzs)
@@ -436,53 +439,50 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
436 439
437 prz = cxt->dprzs[cxt->dump_write_cnt]; 440 prz = cxt->dprzs[cxt->dump_write_cnt];
438 441
439 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;
440 if (size + hlen > prz->buffer_size) 445 if (size + hlen > prz->buffer_size)
441 size = prz->buffer_size - hlen; 446 size = prz->buffer_size - hlen;
442 persistent_ram_write(prz, buf, size); 447 persistent_ram_write(prz, record->buf, size);
443 448
444 cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt; 449 cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt;
445 450
446 return 0; 451 return 0;
447} 452}
448 453
449static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type, 454static int notrace ramoops_pstore_write_user(struct pstore_record *record,
450 enum kmsg_dump_reason reason, 455 const char __user *buf)
451 u64 *id, unsigned int part,
452 const char __user *buf,
453 bool compressed, size_t size,
454 struct pstore_info *psi)
455{ 456{
456 if (type == PSTORE_TYPE_PMSG) { 457 if (record->type == PSTORE_TYPE_PMSG) {
457 struct ramoops_context *cxt = psi->data; 458 struct ramoops_context *cxt = record->psi->data;
458 459
459 if (!cxt->mprz) 460 if (!cxt->mprz)
460 return -ENOMEM; 461 return -ENOMEM;
461 return persistent_ram_write_user(cxt->mprz, buf, size); 462 return persistent_ram_write_user(cxt->mprz, buf, record->size);
462 } 463 }
463 464
464 return -EINVAL; 465 return -EINVAL;
465} 466}
466 467
467static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count, 468static int ramoops_pstore_erase(struct pstore_record *record)
468 struct timespec time, struct pstore_info *psi)
469{ 469{
470 struct ramoops_context *cxt = psi->data; 470 struct ramoops_context *cxt = record->psi->data;
471 struct persistent_ram_zone *prz; 471 struct persistent_ram_zone *prz;
472 472
473 switch (type) { 473 switch (record->type) {
474 case PSTORE_TYPE_DMESG: 474 case PSTORE_TYPE_DMESG:
475 if (id >= cxt->max_dump_cnt) 475 if (record->id >= cxt->max_dump_cnt)
476 return -EINVAL; 476 return -EINVAL;
477 prz = cxt->dprzs[id]; 477 prz = cxt->dprzs[record->id];
478 break; 478 break;
479 case PSTORE_TYPE_CONSOLE: 479 case PSTORE_TYPE_CONSOLE:
480 prz = cxt->cprz; 480 prz = cxt->cprz;
481 break; 481 break;
482 case PSTORE_TYPE_FTRACE: 482 case PSTORE_TYPE_FTRACE:
483 if (id >= cxt->max_ftrace_cnt) 483 if (record->id >= cxt->max_ftrace_cnt)
484 return -EINVAL; 484 return -EINVAL;
485 prz = cxt->fprzs[id]; 485 prz = cxt->fprzs[record->id];
486 break; 486 break;
487 case PSTORE_TYPE_PMSG: 487 case PSTORE_TYPE_PMSG:
488 prz = cxt->mprz; 488 prz = cxt->mprz;
@@ -503,8 +503,8 @@ static struct ramoops_context oops_cxt = {
503 .name = "ramoops", 503 .name = "ramoops",
504 .open = ramoops_pstore_open, 504 .open = ramoops_pstore_open,
505 .read = ramoops_pstore_read, 505 .read = ramoops_pstore_read,
506 .write_buf = ramoops_pstore_write_buf, 506 .write = ramoops_pstore_write,
507 .write_buf_user = ramoops_pstore_write_buf_user, 507 .write_user = ramoops_pstore_write_user,
508 .erase = ramoops_pstore_erase, 508 .erase = ramoops_pstore_erase,
509 }, 509 },
510}; 510};
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index bc927e30bdcc..e11672aa4575 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -532,7 +532,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
532 } 532 }
533 533
534 /* Initialize general buffer state. */ 534 /* Initialize general buffer state. */
535 prz->buffer_lock = __RAW_SPIN_LOCK_UNLOCKED(buffer_lock); 535 raw_spin_lock_init(&prz->buffer_lock);
536 prz->flags = flags; 536 prz->flags = flags;
537 537
538 ret = persistent_ram_buffer_map(start, size, prz, memtype); 538 ret = persistent_ram_buffer_map(start, size, prz, memtype);
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 0da29cae009b..e2233f50f428 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -30,7 +30,9 @@
30#include <linux/time.h> 30#include <linux/time.h>
31#include <linux/types.h> 31#include <linux/types.h>
32 32
33/* types */ 33struct module;
34
35/* pstore record types (see fs/pstore/inode.c for filename templates) */
34enum pstore_type_id { 36enum pstore_type_id {
35 PSTORE_TYPE_DMESG = 0, 37 PSTORE_TYPE_DMESG = 0,
36 PSTORE_TYPE_MCE = 1, 38 PSTORE_TYPE_MCE = 1,
@@ -45,42 +47,146 @@ enum pstore_type_id {
45 PSTORE_TYPE_UNKNOWN = 255 47 PSTORE_TYPE_UNKNOWN = 255
46}; 48};
47 49
48struct module; 50struct pstore_info;
51/**
52 * struct pstore_record - details of a pstore record entry
53 * @psi: pstore backend driver information
54 * @type: pstore record type
55 * @id: per-type unique identifier for record
56 * @time: timestamp of the record
57 * @buf: pointer to record contents
58 * @size: size of @buf
59 * @ecc_notice_size:
60 * ECC information for @buf
61 *
62 * Valid for PSTORE_TYPE_DMESG @type:
63 *
64 * @count: Oops count since boot
65 * @reason: kdump reason for notification
66 * @part: position in a multipart record
67 * @compressed: whether the buffer is compressed
68 *
69 */
70struct pstore_record {
71 struct pstore_info *psi;
72 enum pstore_type_id type;
73 u64 id;
74 struct timespec time;
75 char *buf;
76 ssize_t size;
77 ssize_t ecc_notice_size;
49 78
79 int count;
80 enum kmsg_dump_reason reason;
81 unsigned int part;
82 bool compressed;
83};
84
85/**
86 * struct pstore_info - backend pstore driver structure
87 *
88 * @owner: module which is repsonsible for this backend driver
89 * @name: name of the backend driver
90 *
91 * @buf_lock: spinlock to serialize access to @buf
92 * @buf: preallocated crash dump buffer
93 * @bufsize: size of @buf available for crash dump writes
94 *
95 * @read_mutex: serializes @open, @read, @close, and @erase callbacks
96 * @flags: bitfield of frontends the backend can accept writes for
97 * @data: backend-private pointer passed back during callbacks
98 *
99 * Callbacks:
100 *
101 * @open:
102 * Notify backend that pstore is starting a full read of backend
103 * records. Followed by one or more @read calls, and a final @close.
104 *
105 * @psi: in: pointer to the struct pstore_info for the backend
106 *
107 * Returns 0 on success, and non-zero on error.
108 *
109 * @close:
110 * Notify backend that pstore has finished a full read of backend
111 * records. Always preceded by an @open call and one or more @read
112 * calls.
113 *
114 * @psi: in: pointer to the struct pstore_info for the backend
115 *
116 * Returns 0 on success, and non-zero on error. (Though pstore will
117 * ignore the error.)
118 *
119 * @read:
120 * Read next available backend record. Called after a successful
121 * @open.
122 *
123 * @record:
124 * pointer to record to populate. @buf should be allocated
125 * by the backend and filled. At least @type and @id should
126 * be populated, since these are used when creating pstorefs
127 * file names.
128 *
129 * Returns record size on success, zero when no more records are
130 * available, or negative on error.
131 *
132 * @write:
133 * A newly generated record needs to be written to backend storage.
134 *
135 * @record:
136 * pointer to record metadata. When @type is PSTORE_TYPE_DMESG,
137 * @buf will be pointing to the preallocated @psi.buf, since
138 * memory allocation may be broken during an Oops. Regardless,
139 * @buf must be proccesed or copied before returning. The
140 * backend is also expected to write @id with something that
141 8 can help identify this record to a future @erase callback.
142 *
143 * Returns 0 on success, and non-zero on error.
144 *
145 * @write_user:
146 * Perform a frontend write to a backend record, using a specified
147 * buffer that is coming directly from userspace, instead of the
148 * @record @buf.
149 *
150 * @record: pointer to record metadata.
151 * @buf: pointer to userspace contents to write to backend
152 *
153 * Returns 0 on success, and non-zero on error.
154 *
155 * @erase:
156 * Delete a record from backend storage. Different backends
157 * identify records differently, so entire original record is
158 * passed back to assist in identification of what the backend
159 * should remove from storage.
160 *
161 * @record: pointer to record metadata.
162 *
163 * Returns 0 on success, and non-zero on error.
164 *
165 */
50struct pstore_info { 166struct pstore_info {
51 struct module *owner; 167 struct module *owner;
52 char *name; 168 char *name;
53 spinlock_t buf_lock; /* serialize access to 'buf' */ 169
170 spinlock_t buf_lock;
54 char *buf; 171 char *buf;
55 size_t bufsize; 172 size_t bufsize;
56 struct mutex read_mutex; /* serialize open/read/close */ 173
174 struct mutex read_mutex;
175
57 int flags; 176 int flags;
177 void *data;
178
58 int (*open)(struct pstore_info *psi); 179 int (*open)(struct pstore_info *psi);
59 int (*close)(struct pstore_info *psi); 180 int (*close)(struct pstore_info *psi);
60 ssize_t (*read)(u64 *id, enum pstore_type_id *type, 181 ssize_t (*read)(struct pstore_record *record);
61 int *count, struct timespec *time, char **buf, 182 int (*write)(struct pstore_record *record);
62 bool *compressed, ssize_t *ecc_notice_size, 183 int (*write_user)(struct pstore_record *record,
63 struct pstore_info *psi); 184 const char __user *buf);
64 int (*write)(enum pstore_type_id type, 185 int (*erase)(struct pstore_record *record);
65 enum kmsg_dump_reason reason, u64 *id,
66 unsigned int part, int count, bool compressed,
67 size_t size, struct pstore_info *psi);
68 int (*write_buf)(enum pstore_type_id type,
69 enum kmsg_dump_reason reason, u64 *id,
70 unsigned int part, const char *buf, bool compressed,
71 size_t size, struct pstore_info *psi);
72 int (*write_buf_user)(enum pstore_type_id type,
73 enum kmsg_dump_reason reason, u64 *id,
74 unsigned int part, const char __user *buf,
75 bool compressed, size_t size, struct pstore_info *psi);
76 int (*erase)(enum pstore_type_id type, u64 id,
77 int count, struct timespec time,
78 struct pstore_info *psi);
79 void *data;
80}; 186};
81 187
188/* Supported frontends */
82#define PSTORE_FLAGS_DMESG (1 << 0) 189#define PSTORE_FLAGS_DMESG (1 << 0)
83#define PSTORE_FLAGS_FRAGILE PSTORE_FLAGS_DMESG
84#define PSTORE_FLAGS_CONSOLE (1 << 1) 190#define PSTORE_FLAGS_CONSOLE (1 << 1)
85#define PSTORE_FLAGS_FTRACE (1 << 2) 191#define PSTORE_FLAGS_FTRACE (1 << 2)
86#define PSTORE_FLAGS_PMSG (1 << 3) 192#define PSTORE_FLAGS_PMSG (1 << 3)