diff options
author | Kees Cook <keescook@chromium.org> | 2017-03-04 02:28:53 -0500 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2017-03-07 17:00:56 -0500 |
commit | 76cc9580e3fbd323651d06e8184a5a54e0e1066e (patch) | |
tree | 0543b98aec0098cbe571653ce8b6cb14362e133e | |
parent | 125cc42baf8ab2149c207f8a360ea25668b8422d (diff) |
pstore: Replace arguments for write() API
Similar to the pstore_info read() callback, there were too many arguments.
This switches to the new struct pstore_record pointer instead. This adds
"reason" and "part" to the record structure as well.
Signed-off-by: Kees Cook <keescook@chromium.org>
-rw-r--r-- | arch/powerpc/kernel/nvram_64.c | 27 | ||||
-rw-r--r-- | drivers/acpi/apei/erst.c | 18 | ||||
-rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 18 | ||||
-rw-r--r-- | fs/pstore/platform.c | 62 | ||||
-rw-r--r-- | include/linux/pstore.h | 36 |
5 files changed, 76 insertions, 85 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 7f192001d09a..caf2e1f36d6b 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 | */ |
406 | static int nvram_pstore_write(enum pstore_type_id type, | 398 | static 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 | ||
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index bbefb7522f80..440588d189e7 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -926,9 +926,7 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) | |||
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(struct pstore_record *record); | 928 | static ssize_t erst_reader(struct pstore_record *record); |
929 | static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, | 929 | static int erst_writer(struct pstore_record *record); |
930 | u64 *id, unsigned int part, int count, bool compressed, | ||
931 | size_t size, struct pstore_info *psi); | ||
932 | static int erst_clearer(enum pstore_type_id type, u64 id, int count, | 930 | static int erst_clearer(enum pstore_type_id type, u64 id, int count, |
933 | struct timespec time, struct pstore_info *psi); | 931 | struct timespec time, struct pstore_info *psi); |
934 | 932 | ||
@@ -1054,9 +1052,7 @@ out: | |||
1054 | return (rc < 0) ? rc : (len - sizeof(*rcd)); | 1052 | return (rc < 0) ? rc : (len - sizeof(*rcd)); |
1055 | } | 1053 | } |
1056 | 1054 | ||
1057 | static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, | 1055 | static int erst_writer(struct pstore_record *record) |
1058 | u64 *id, unsigned int part, int count, bool compressed, | ||
1059 | size_t size, struct pstore_info *psi) | ||
1060 | { | 1056 | { |
1061 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) | 1057 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) |
1062 | (erst_info.buf - sizeof(*rcd)); | 1058 | (erst_info.buf - sizeof(*rcd)); |
@@ -1071,21 +1067,21 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, | |||
1071 | /* timestamp valid. platform_id, partition_id are invalid */ | 1067 | /* timestamp valid. platform_id, partition_id are invalid */ |
1072 | rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP; | 1068 | rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP; |
1073 | rcd->hdr.timestamp = get_seconds(); | 1069 | rcd->hdr.timestamp = get_seconds(); |
1074 | rcd->hdr.record_length = sizeof(*rcd) + size; | 1070 | rcd->hdr.record_length = sizeof(*rcd) + record->size; |
1075 | rcd->hdr.creator_id = CPER_CREATOR_PSTORE; | 1071 | rcd->hdr.creator_id = CPER_CREATOR_PSTORE; |
1076 | rcd->hdr.notification_type = CPER_NOTIFY_MCE; | 1072 | rcd->hdr.notification_type = CPER_NOTIFY_MCE; |
1077 | rcd->hdr.record_id = cper_next_record_id(); | 1073 | rcd->hdr.record_id = cper_next_record_id(); |
1078 | rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR; | 1074 | rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR; |
1079 | 1075 | ||
1080 | rcd->sec_hdr.section_offset = sizeof(*rcd); | 1076 | rcd->sec_hdr.section_offset = sizeof(*rcd); |
1081 | rcd->sec_hdr.section_length = size; | 1077 | rcd->sec_hdr.section_length = record->size; |
1082 | rcd->sec_hdr.revision = CPER_SEC_REV; | 1078 | rcd->sec_hdr.revision = CPER_SEC_REV; |
1083 | /* fru_id and fru_text is invalid */ | 1079 | /* fru_id and fru_text is invalid */ |
1084 | rcd->sec_hdr.validation_bits = 0; | 1080 | rcd->sec_hdr.validation_bits = 0; |
1085 | rcd->sec_hdr.flags = CPER_SEC_PRIMARY; | 1081 | rcd->sec_hdr.flags = CPER_SEC_PRIMARY; |
1086 | switch (type) { | 1082 | switch (record->type) { |
1087 | case PSTORE_TYPE_DMESG: | 1083 | case PSTORE_TYPE_DMESG: |
1088 | if (compressed) | 1084 | if (record->compressed) |
1089 | rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG_Z; | 1085 | rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG_Z; |
1090 | else | 1086 | else |
1091 | rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG; | 1087 | rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG; |
@@ -1099,7 +1095,7 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, | |||
1099 | rcd->sec_hdr.section_severity = CPER_SEV_FATAL; | 1095 | rcd->sec_hdr.section_severity = CPER_SEV_FATAL; |
1100 | 1096 | ||
1101 | ret = erst_write(&rcd->hdr); | 1097 | ret = erst_write(&rcd->hdr); |
1102 | *id = rcd->hdr.record_id; | 1098 | record->id = rcd->hdr.record_id; |
1103 | 1099 | ||
1104 | return ret; | 1100 | return ret; |
1105 | } | 1101 | } |
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index bda24129e85b..f81e3ec6f1c0 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c | |||
@@ -240,30 +240,28 @@ out: | |||
240 | return size; | 240 | return size; |
241 | } | 241 | } |
242 | 242 | ||
243 | static int efi_pstore_write(enum pstore_type_id type, | 243 | static int efi_pstore_write(struct pstore_record *record) |
244 | enum kmsg_dump_reason reason, u64 *id, | ||
245 | unsigned int part, int count, bool compressed, size_t size, | ||
246 | struct pstore_info *psi) | ||
247 | { | 244 | { |
248 | char name[DUMP_NAME_LEN]; | 245 | char name[DUMP_NAME_LEN]; |
249 | efi_char16_t efi_name[DUMP_NAME_LEN]; | 246 | efi_char16_t efi_name[DUMP_NAME_LEN]; |
250 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; | 247 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; |
251 | int i, ret = 0; | 248 | int i, ret = 0; |
252 | 249 | ||
253 | sprintf(name, "dump-type%u-%u-%d-%lu-%c", type, part, count, | 250 | snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c", |
254 | get_seconds(), compressed ? 'C' : 'D'); | 251 | record->type, record->part, record->count, |
252 | get_seconds(), record->compressed ? 'C' : 'D'); | ||
255 | 253 | ||
256 | for (i = 0; i < DUMP_NAME_LEN; i++) | 254 | for (i = 0; i < DUMP_NAME_LEN; i++) |
257 | efi_name[i] = name[i]; | 255 | efi_name[i] = name[i]; |
258 | 256 | ||
259 | efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES, | 257 | efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES, |
260 | !pstore_cannot_block_path(reason), | 258 | !pstore_cannot_block_path(record->reason), |
261 | size, psi->buf); | 259 | record->size, record->psi->buf); |
262 | 260 | ||
263 | if (reason == KMSG_DUMP_OOPS) | 261 | if (record->reason == KMSG_DUMP_OOPS) |
264 | efivar_run_worker(); | 262 | efivar_run_worker(); |
265 | 263 | ||
266 | *id = part; | 264 | record->id = record->part; |
267 | return ret; | 265 | return ret; |
268 | }; | 266 | }; |
269 | 267 | ||
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 47968c2f2d0d..879658b4c679 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c | |||
@@ -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) |
@@ -618,14 +628,12 @@ static void pstore_register_console(void) {} | |||
618 | static void pstore_unregister_console(void) {} | 628 | static void pstore_unregister_console(void) {} |
619 | #endif | 629 | #endif |
620 | 630 | ||
621 | static int pstore_write_compat(enum pstore_type_id type, | 631 | static int pstore_write_compat(struct pstore_record *record) |
622 | enum kmsg_dump_reason reason, | ||
623 | u64 *id, unsigned int part, int count, | ||
624 | bool compressed, size_t size, | ||
625 | struct pstore_info *psi) | ||
626 | { | 632 | { |
627 | return psi->write_buf(type, reason, id, part, psinfo->buf, compressed, | 633 | return record->psi->write_buf(record->type, record->reason, |
628 | size, psi); | 634 | &record->id, record->part, |
635 | psinfo->buf, record->compressed, | ||
636 | record->size, record->psi); | ||
629 | } | 637 | } |
630 | 638 | ||
631 | static int pstore_write_buf_user_compat(enum pstore_type_id type, | 639 | static int pstore_write_buf_user_compat(enum pstore_type_id type, |
diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 22a46ebbe041..9335f75c3ddb 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h | |||
@@ -54,23 +54,32 @@ struct pstore_info; | |||
54 | * @type: pstore record type | 54 | * @type: pstore record type |
55 | * @id: per-type unique identifier for record | 55 | * @id: per-type unique identifier for record |
56 | * @time: timestamp of the record | 56 | * @time: timestamp of the record |
57 | * @count: for PSTORE_TYPE_DMESG, the Oops count. | ||
58 | * @compressed: for PSTORE_TYPE_DMESG, whether the buffer is compressed | ||
59 | * @buf: pointer to record contents | 57 | * @buf: pointer to record contents |
60 | * @size: size of @buf | 58 | * @size: size of @buf |
61 | * @ecc_notice_size: | 59 | * @ecc_notice_size: |
62 | * ECC information for @buf | 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 | * | ||
63 | */ | 69 | */ |
64 | struct pstore_record { | 70 | struct pstore_record { |
65 | struct pstore_info *psi; | 71 | struct pstore_info *psi; |
66 | enum pstore_type_id type; | 72 | enum pstore_type_id type; |
67 | u64 id; | 73 | u64 id; |
68 | struct timespec time; | 74 | struct timespec time; |
69 | int count; | ||
70 | bool compressed; | ||
71 | char *buf; | 75 | char *buf; |
72 | ssize_t size; | 76 | ssize_t size; |
73 | ssize_t ecc_notice_size; | 77 | ssize_t ecc_notice_size; |
78 | |||
79 | int count; | ||
80 | enum kmsg_dump_reason reason; | ||
81 | unsigned int part; | ||
82 | bool compressed; | ||
74 | }; | 83 | }; |
75 | 84 | ||
76 | /** | 85 | /** |
@@ -125,16 +134,10 @@ struct pstore_record { | |||
125 | * data to be stored has already been written to the registered @buf | 134 | * data to be stored has already been written to the registered @buf |
126 | * of the @psi structure. | 135 | * of the @psi structure. |
127 | * | 136 | * |
128 | * @type: in: pstore record type to write | 137 | * @record: |
129 | * @reason: | 138 | * pointer to record metadata. Note that @buf is NULL, since |
130 | * in: pstore write reason | 139 | * the @buf registered with @psi is what has been written. The |
131 | * @id: out: unique identifier for the record | 140 | * backend is expected to update @id. |
132 | * @part: in: position in a multipart write | ||
133 | * @count: in: increasing from 0 since boot, the number of this Oops | ||
134 | * @compressed: | ||
135 | * in: if the record is compressed | ||
136 | * @size: in: size of the write | ||
137 | * @psi: in: pointer to the struct pstore_info for the backend | ||
138 | * | 141 | * |
139 | * Returns 0 on success, and non-zero on error. | 142 | * Returns 0 on success, and non-zero on error. |
140 | * | 143 | * |
@@ -203,10 +206,7 @@ struct pstore_info { | |||
203 | int (*open)(struct pstore_info *psi); | 206 | int (*open)(struct pstore_info *psi); |
204 | int (*close)(struct pstore_info *psi); | 207 | int (*close)(struct pstore_info *psi); |
205 | ssize_t (*read)(struct pstore_record *record); | 208 | ssize_t (*read)(struct pstore_record *record); |
206 | int (*write)(enum pstore_type_id type, | 209 | int (*write)(struct pstore_record *record); |
207 | enum kmsg_dump_reason reason, u64 *id, | ||
208 | unsigned int part, int count, bool compressed, | ||
209 | size_t size, struct pstore_info *psi); | ||
210 | int (*write_buf)(enum pstore_type_id type, | 210 | int (*write_buf)(enum pstore_type_id type, |
211 | enum kmsg_dump_reason reason, u64 *id, | 211 | enum kmsg_dump_reason reason, u64 *id, |
212 | unsigned int part, const char *buf, bool compressed, | 212 | unsigned int part, const char *buf, bool compressed, |