aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2017-03-04 02:28:53 -0500
committerKees Cook <keescook@chromium.org>2017-03-07 17:00:56 -0500
commit76cc9580e3fbd323651d06e8184a5a54e0e1066e (patch)
tree0543b98aec0098cbe571653ce8b6cb14362e133e
parent125cc42baf8ab2149c207f8a360ea25668b8422d (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.c27
-rw-r--r--drivers/acpi/apei/erst.c18
-rw-r--r--drivers/firmware/efi/efi-pstore.c18
-rw-r--r--fs/pstore/platform.c62
-rw-r--r--include/linux/pstore.h36
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 */
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
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)
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(struct pstore_record *record); 928static ssize_t erst_reader(struct pstore_record *record);
929static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, 929static 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);
932static int erst_clearer(enum pstore_type_id type, u64 id, int count, 930static 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
1057static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, 1055static 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
243static int efi_pstore_write(enum pstore_type_id type, 243static 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) {}
618static void pstore_unregister_console(void) {} 628static void pstore_unregister_console(void) {}
619#endif 629#endif
620 630
621static int pstore_write_compat(enum pstore_type_id type, 631static 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
631static int pstore_write_buf_user_compat(enum pstore_type_id type, 639static 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 */
64struct pstore_record { 70struct 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,