diff options
author | Kees Cook <keescook@chromium.org> | 2017-03-04 01:09:18 -0500 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2017-03-07 17:00:55 -0500 |
commit | 125cc42baf8ab2149c207f8a360ea25668b8422d (patch) | |
tree | 85bd4128f1e633e4d611477da9fba6f98fb44940 | |
parent | 1edd1aa397ad3ca5f1fca1961c13910ef53f16e8 (diff) |
pstore: Replace arguments for read() API
The argument list for the pstore_read() interface is unwieldy. This changes
passes the new struct pstore_record instead. The erst backend was already
doing something similar internally.
Signed-off-by: Kees Cook <keescook@chromium.org>
-rw-r--r-- | arch/powerpc/kernel/nvram_64.c | 61 | ||||
-rw-r--r-- | drivers/acpi/apei/erst.c | 38 | ||||
-rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 104 | ||||
-rw-r--r-- | fs/pstore/platform.c | 7 | ||||
-rw-r--r-- | fs/pstore/ram.c | 53 | ||||
-rw-r--r-- | include/linux/pstore.h | 20 |
6 files changed, 124 insertions, 159 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index d5e2b8309939..7f192001d09a 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
@@ -442,10 +442,7 @@ static int nvram_pstore_write(enum pstore_type_id type, | |||
442 | * Returns the length of the data we read from each partition. | 442 | * Returns the length of the data we read from each partition. |
443 | * Returns 0 if we've been called before. | 443 | * Returns 0 if we've been called before. |
444 | */ | 444 | */ |
445 | static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, | 445 | static 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 | { | 446 | { |
450 | struct oops_log_info *oops_hdr; | 447 | struct oops_log_info *oops_hdr; |
451 | unsigned int err_type, id_no, size = 0; | 448 | unsigned int err_type, id_no, size = 0; |
@@ -459,40 +456,40 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, | |||
459 | switch (nvram_type_ids[read_type]) { | 456 | switch (nvram_type_ids[read_type]) { |
460 | case PSTORE_TYPE_DMESG: | 457 | case PSTORE_TYPE_DMESG: |
461 | part = &oops_log_partition; | 458 | part = &oops_log_partition; |
462 | *type = PSTORE_TYPE_DMESG; | 459 | record->type = PSTORE_TYPE_DMESG; |
463 | break; | 460 | break; |
464 | case PSTORE_TYPE_PPC_COMMON: | 461 | case PSTORE_TYPE_PPC_COMMON: |
465 | sig = NVRAM_SIG_SYS; | 462 | sig = NVRAM_SIG_SYS; |
466 | part = &common_partition; | 463 | part = &common_partition; |
467 | *type = PSTORE_TYPE_PPC_COMMON; | 464 | record->type = PSTORE_TYPE_PPC_COMMON; |
468 | *id = PSTORE_TYPE_PPC_COMMON; | 465 | record->id = PSTORE_TYPE_PPC_COMMON; |
469 | time->tv_sec = 0; | 466 | record->time.tv_sec = 0; |
470 | time->tv_nsec = 0; | 467 | record->time.tv_nsec = 0; |
471 | break; | 468 | break; |
472 | #ifdef CONFIG_PPC_PSERIES | 469 | #ifdef CONFIG_PPC_PSERIES |
473 | case PSTORE_TYPE_PPC_RTAS: | 470 | case PSTORE_TYPE_PPC_RTAS: |
474 | part = &rtas_log_partition; | 471 | part = &rtas_log_partition; |
475 | *type = PSTORE_TYPE_PPC_RTAS; | 472 | record->type = PSTORE_TYPE_PPC_RTAS; |
476 | time->tv_sec = last_rtas_event; | 473 | record->time.tv_sec = last_rtas_event; |
477 | time->tv_nsec = 0; | 474 | record->time.tv_nsec = 0; |
478 | break; | 475 | break; |
479 | case PSTORE_TYPE_PPC_OF: | 476 | case PSTORE_TYPE_PPC_OF: |
480 | sig = NVRAM_SIG_OF; | 477 | sig = NVRAM_SIG_OF; |
481 | part = &of_config_partition; | 478 | part = &of_config_partition; |
482 | *type = PSTORE_TYPE_PPC_OF; | 479 | record->type = PSTORE_TYPE_PPC_OF; |
483 | *id = PSTORE_TYPE_PPC_OF; | 480 | record->id = PSTORE_TYPE_PPC_OF; |
484 | time->tv_sec = 0; | 481 | record->time.tv_sec = 0; |
485 | time->tv_nsec = 0; | 482 | record->time.tv_nsec = 0; |
486 | break; | 483 | break; |
487 | #endif | 484 | #endif |
488 | #ifdef CONFIG_PPC_POWERNV | 485 | #ifdef CONFIG_PPC_POWERNV |
489 | case PSTORE_TYPE_PPC_OPAL: | 486 | case PSTORE_TYPE_PPC_OPAL: |
490 | sig = NVRAM_SIG_FW; | 487 | sig = NVRAM_SIG_FW; |
491 | part = &skiboot_partition; | 488 | part = &skiboot_partition; |
492 | *type = PSTORE_TYPE_PPC_OPAL; | 489 | record->type = PSTORE_TYPE_PPC_OPAL; |
493 | *id = PSTORE_TYPE_PPC_OPAL; | 490 | record->id = PSTORE_TYPE_PPC_OPAL; |
494 | time->tv_sec = 0; | 491 | record->time.tv_sec = 0; |
495 | time->tv_nsec = 0; | 492 | record->time.tv_nsec = 0; |
496 | break; | 493 | break; |
497 | #endif | 494 | #endif |
498 | default: | 495 | default: |
@@ -520,10 +517,10 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, | |||
520 | return 0; | 517 | return 0; |
521 | } | 518 | } |
522 | 519 | ||
523 | *count = 0; | 520 | record->count = 0; |
524 | 521 | ||
525 | if (part->os_partition) | 522 | if (part->os_partition) |
526 | *id = id_no; | 523 | record->id = id_no; |
527 | 524 | ||
528 | if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { | 525 | if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { |
529 | size_t length, hdr_size; | 526 | size_t length, hdr_size; |
@@ -533,28 +530,28 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, | |||
533 | /* Old format oops header had 2-byte record size */ | 530 | /* Old format oops header had 2-byte record size */ |
534 | hdr_size = sizeof(u16); | 531 | hdr_size = sizeof(u16); |
535 | length = be16_to_cpu(oops_hdr->version); | 532 | length = be16_to_cpu(oops_hdr->version); |
536 | time->tv_sec = 0; | 533 | record->time.tv_sec = 0; |
537 | time->tv_nsec = 0; | 534 | record->time.tv_nsec = 0; |
538 | } else { | 535 | } else { |
539 | hdr_size = sizeof(*oops_hdr); | 536 | hdr_size = sizeof(*oops_hdr); |
540 | length = be16_to_cpu(oops_hdr->report_length); | 537 | length = be16_to_cpu(oops_hdr->report_length); |
541 | time->tv_sec = be64_to_cpu(oops_hdr->timestamp); | 538 | record->time.tv_sec = be64_to_cpu(oops_hdr->timestamp); |
542 | time->tv_nsec = 0; | 539 | record->time.tv_nsec = 0; |
543 | } | 540 | } |
544 | *buf = kmemdup(buff + hdr_size, length, GFP_KERNEL); | 541 | record->buf = kmemdup(buff + hdr_size, length, GFP_KERNEL); |
545 | kfree(buff); | 542 | kfree(buff); |
546 | if (*buf == NULL) | 543 | if (record->buf == NULL) |
547 | return -ENOMEM; | 544 | return -ENOMEM; |
548 | 545 | ||
549 | *ecc_notice_size = 0; | 546 | record->ecc_notice_size = 0; |
550 | if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) | 547 | if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) |
551 | *compressed = true; | 548 | record->compressed = true; |
552 | else | 549 | else |
553 | *compressed = false; | 550 | record->compressed = false; |
554 | return length; | 551 | return length; |
555 | } | 552 | } |
556 | 553 | ||
557 | *buf = buff; | 554 | record->buf = buff; |
558 | return part->size; | 555 | return part->size; |
559 | } | 556 | } |
560 | 557 | ||
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index ec4f507b524f..bbefb7522f80 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -925,10 +925,7 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) | |||
925 | 925 | ||
926 | static int erst_open_pstore(struct pstore_info *psi); | 926 | static int erst_open_pstore(struct pstore_info *psi); |
927 | static int erst_close_pstore(struct pstore_info *psi); | 927 | static int erst_close_pstore(struct pstore_info *psi); |
928 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, | 928 | static ssize_t erst_reader(struct pstore_record *record); |
929 | struct timespec *time, char **buf, | ||
930 | bool *compressed, ssize_t *ecc_notice_size, | ||
931 | struct pstore_info *psi); | ||
932 | static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, | 929 | static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, |
933 | u64 *id, unsigned int part, int count, bool compressed, | 930 | u64 *id, unsigned int part, int count, bool compressed, |
934 | size_t size, struct pstore_info *psi); | 931 | size_t size, struct pstore_info *psi); |
@@ -986,10 +983,7 @@ static int erst_close_pstore(struct pstore_info *psi) | |||
986 | return 0; | 983 | return 0; |
987 | } | 984 | } |
988 | 985 | ||
989 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, | 986 | static 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 | { | 987 | { |
994 | int rc; | 988 | int rc; |
995 | ssize_t len = 0; | 989 | ssize_t len = 0; |
@@ -1027,33 +1021,33 @@ skip: | |||
1027 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) | 1021 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) |
1028 | goto skip; | 1022 | goto skip; |
1029 | 1023 | ||
1030 | *buf = kmalloc(len, GFP_KERNEL); | 1024 | record->buf = kmalloc(len, GFP_KERNEL); |
1031 | if (*buf == NULL) { | 1025 | if (record->buf == NULL) { |
1032 | rc = -ENOMEM; | 1026 | rc = -ENOMEM; |
1033 | goto out; | 1027 | goto out; |
1034 | } | 1028 | } |
1035 | memcpy(*buf, rcd->data, len - sizeof(*rcd)); | 1029 | memcpy(record->buf, rcd->data, len - sizeof(*rcd)); |
1036 | *id = record_id; | 1030 | record->id = record_id; |
1037 | *compressed = false; | 1031 | record->compressed = false; |
1038 | *ecc_notice_size = 0; | 1032 | record->ecc_notice_size = 0; |
1039 | if (uuid_le_cmp(rcd->sec_hdr.section_type, | 1033 | if (uuid_le_cmp(rcd->sec_hdr.section_type, |
1040 | CPER_SECTION_TYPE_DMESG_Z) == 0) { | 1034 | CPER_SECTION_TYPE_DMESG_Z) == 0) { |
1041 | *type = PSTORE_TYPE_DMESG; | 1035 | record->type = PSTORE_TYPE_DMESG; |
1042 | *compressed = true; | 1036 | record->compressed = true; |
1043 | } else if (uuid_le_cmp(rcd->sec_hdr.section_type, | 1037 | } else if (uuid_le_cmp(rcd->sec_hdr.section_type, |
1044 | CPER_SECTION_TYPE_DMESG) == 0) | 1038 | CPER_SECTION_TYPE_DMESG) == 0) |
1045 | *type = PSTORE_TYPE_DMESG; | 1039 | record->type = PSTORE_TYPE_DMESG; |
1046 | else if (uuid_le_cmp(rcd->sec_hdr.section_type, | 1040 | else if (uuid_le_cmp(rcd->sec_hdr.section_type, |
1047 | CPER_SECTION_TYPE_MCE) == 0) | 1041 | CPER_SECTION_TYPE_MCE) == 0) |
1048 | *type = PSTORE_TYPE_MCE; | 1042 | record->type = PSTORE_TYPE_MCE; |
1049 | else | 1043 | else |
1050 | *type = PSTORE_TYPE_UNKNOWN; | 1044 | record->type = PSTORE_TYPE_UNKNOWN; |
1051 | 1045 | ||
1052 | if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP) | 1046 | if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP) |
1053 | time->tv_sec = rcd->hdr.timestamp; | 1047 | record->time.tv_sec = rcd->hdr.timestamp; |
1054 | else | 1048 | else |
1055 | time->tv_sec = 0; | 1049 | record->time.tv_sec = 0; |
1056 | time->tv_nsec = 0; | 1050 | record->time.tv_nsec = 0; |
1057 | 1051 | ||
1058 | out: | 1052 | out: |
1059 | kfree(rcd); | 1053 | kfree(rcd); |
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index f402ba2eed46..bda24129e85b 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 | ||
31 | struct 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 | |||
41 | static inline u64 generic_id(unsigned long timestamp, | 31 | static 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 | ||
47 | static int efi_pstore_read_func(struct efivar_entry *entry, void *data) | 37 | static 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 | */ |
178 | static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos) | 168 | static 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,36 +216,27 @@ 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 | */ |
228 | static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, | 219 | static 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); | 235 | out: |
236 | if (size <= 0) { | ||
237 | kfree(record->buf); | ||
238 | record->buf = NULL; | ||
239 | } | ||
258 | return size; | 240 | return size; |
259 | } | 241 | } |
260 | 242 | ||
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 168e03fd5e58..47968c2f2d0d 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c | |||
@@ -807,12 +807,7 @@ void pstore_get_records(int quiet) | |||
807 | if (psi->open && psi->open(psi)) | 807 | if (psi->open && psi->open(psi)) |
808 | goto out; | 808 | goto out; |
809 | 809 | ||
810 | while ((record.size = psi->read(&record.id, &record.type, | 810 | while ((record.size = psi->read(&record)) > 0) { |
811 | &record.count, &record.time, | ||
812 | &record.buf, &record.compressed, | ||
813 | &record.ecc_notice_size, | ||
814 | record.psi)) > 0) { | ||
815 | |||
816 | decompress_record(&record); | 811 | decompress_record(&record); |
817 | rc = pstore_mkfile(&record); | 812 | rc = pstore_mkfile(&record); |
818 | 813 | ||
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 11f918d34b1e..ca6e2a814e37 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 | ||
238 | static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, | 238 | static 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 | ||
344 | out: | 349 | out: |
345 | if (free_prz) { | 350 | if (free_prz) { |
diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 745468072d6e..22a46ebbe041 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h | |||
@@ -111,16 +111,11 @@ struct pstore_record { | |||
111 | * Read next available backend record. Called after a successful | 111 | * Read next available backend record. Called after a successful |
112 | * @open. | 112 | * @open. |
113 | * | 113 | * |
114 | * @id: out: unique identifier for the record | 114 | * @record: |
115 | * @type: out: pstore record type | 115 | * pointer to record to populate. @buf should be allocated |
116 | * @count: out: for PSTORE_TYPE_DMESG, the Oops count. | 116 | * by the backend and filled. At least @type and @id should |
117 | * @time: out: timestamp for the record | 117 | * be populated, since these are used when creating pstorefs |
118 | * @buf: out: kmalloc copy of record contents, to be freed by pstore | 118 | * file names. |
119 | * @compressed: | ||
120 | * out: if the record contents are compressed | ||
121 | * @ecc_notice_size: | ||
122 | * out: ECC information | ||
123 | * @psi: in: pointer to the struct pstore_info for the backend | ||
124 | * | 119 | * |
125 | * Returns record size on success, zero when no more records are | 120 | * Returns record size on success, zero when no more records are |
126 | * available, or negative on error. | 121 | * available, or negative on error. |
@@ -207,10 +202,7 @@ struct pstore_info { | |||
207 | 202 | ||
208 | int (*open)(struct pstore_info *psi); | 203 | int (*open)(struct pstore_info *psi); |
209 | int (*close)(struct pstore_info *psi); | 204 | int (*close)(struct pstore_info *psi); |
210 | ssize_t (*read)(u64 *id, enum pstore_type_id *type, | 205 | ssize_t (*read)(struct pstore_record *record); |
211 | int *count, struct timespec *time, char **buf, | ||
212 | bool *compressed, ssize_t *ecc_notice_size, | ||
213 | struct pstore_info *psi); | ||
214 | int (*write)(enum pstore_type_id type, | 206 | int (*write)(enum pstore_type_id type, |
215 | enum kmsg_dump_reason reason, u64 *id, | 207 | enum kmsg_dump_reason reason, u64 *id, |
216 | unsigned int part, int count, bool compressed, | 208 | unsigned int part, int count, bool compressed, |