Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

efi_pstore: Add a sequence counter to a variable name

[Issue]

Currently, a variable name, which identifies each entry, consists of type, id and ctime.
But if multiple events happens in a short time, a second/third event may fail to log because
efi_pstore can't distinguish each event with current variable name.

[Solution]

A reasonable way to identify all events precisely is introducing a sequence counter to
the variable name.

The sequence counter has already supported in a pstore layer with "oopscount".
So, this patch adds it to a variable name.
Also, it is passed to read/erase callbacks of platform drivers in accordance with
the modification of the variable name.

<before applying this patch>
a variable name of first event: dump-type0-1-12345678
a variable name of second event: dump-type0-1-12345678

type:0
id:1
ctime:12345678

If multiple events happen in a short time, efi_pstore can't distinguish them because
variable names are same among them.

<after applying this patch>

it can be distinguishable by adding a sequence counter as follows.

a variable name of first event: dump-type0-1-1-12345678
a variable name of Second event: dump-type0-1-2-12345678

type:0
id:1
sequence counter: 1(first event), 2(second event)
ctime:12345678

In case of a write callback executed in pstore_console_write(), "0" is added to
an argument of the write callback because it just logs all kernel messages and
doesn't need to care about multiple events.

Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Mike Waychison <mikew@google.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by

Seiji Aguchi and committed by
Tony Luck
755d4fe4 a9efd39c

+41 -32
+6 -6
drivers/acpi/apei/erst.c
··· 931 931 932 932 static int erst_open_pstore(struct pstore_info *psi); 933 933 static int erst_close_pstore(struct pstore_info *psi); 934 - static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, 934 + static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, 935 935 struct timespec *time, char **buf, 936 936 struct pstore_info *psi); 937 937 static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, 938 - u64 *id, unsigned int part, 938 + u64 *id, unsigned int part, int count, 939 939 size_t size, struct pstore_info *psi); 940 - static int erst_clearer(enum pstore_type_id type, u64 id, 940 + static int erst_clearer(enum pstore_type_id type, u64 id, int count, 941 941 struct timespec time, struct pstore_info *psi); 942 942 943 943 static struct pstore_info erst_info = { ··· 987 987 return 0; 988 988 } 989 989 990 - static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, 990 + static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, 991 991 struct timespec *time, char **buf, 992 992 struct pstore_info *psi) 993 993 { ··· 1055 1055 } 1056 1056 1057 1057 static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, 1058 - u64 *id, unsigned int part, 1058 + u64 *id, unsigned int part, int count, 1059 1059 size_t size, struct pstore_info *psi) 1060 1060 { 1061 1061 struct cper_pstore_record *rcd = (struct cper_pstore_record *) ··· 1101 1101 return ret; 1102 1102 } 1103 1103 1104 - static int erst_clearer(enum pstore_type_id type, u64 id, 1104 + static int erst_clearer(enum pstore_type_id type, u64 id, int count, 1105 1105 struct timespec time, struct pstore_info *psi) 1106 1106 { 1107 1107 return erst_clear(id);
+14 -9
drivers/firmware/efivars.c
··· 658 658 } 659 659 660 660 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 661 - struct timespec *timespec, 661 + int *count, struct timespec *timespec, 662 662 char **buf, struct pstore_info *psi) 663 663 { 664 664 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 665 665 struct efivars *efivars = psi->data; 666 666 char name[DUMP_NAME_LEN]; 667 667 int i; 668 + int cnt; 668 669 unsigned int part, size; 669 670 unsigned long time; 670 671 ··· 675 674 for (i = 0; i < DUMP_NAME_LEN; i++) { 676 675 name[i] = efivars->walk_entry->var.VariableName[i]; 677 676 } 678 - if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) { 677 + if (sscanf(name, "dump-type%u-%u-%d-%lu", 678 + type, &part, &cnt, &time) == 4) { 679 679 *id = part; 680 + *count = cnt; 680 681 timespec->tv_sec = time; 681 682 timespec->tv_nsec = 0; 682 683 get_var_data_locked(efivars, &efivars->walk_entry->var); ··· 701 698 702 699 static int efi_pstore_write(enum pstore_type_id type, 703 700 enum kmsg_dump_reason reason, u64 *id, 704 - unsigned int part, size_t size, struct pstore_info *psi) 701 + unsigned int part, int count, size_t size, 702 + struct pstore_info *psi) 705 703 { 706 704 char name[DUMP_NAME_LEN]; 707 705 efi_char16_t efi_name[DUMP_NAME_LEN]; ··· 729 725 return -ENOSPC; 730 726 } 731 727 732 - sprintf(name, "dump-type%u-%u-%lu", type, part, 728 + sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, 733 729 get_seconds()); 734 730 735 731 for (i = 0; i < DUMP_NAME_LEN; i++) ··· 750 746 return ret; 751 747 }; 752 748 753 - static int efi_pstore_erase(enum pstore_type_id type, u64 id, 749 + static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, 754 750 struct timespec time, struct pstore_info *psi) 755 751 { 756 752 char name[DUMP_NAME_LEN]; ··· 760 756 struct efivar_entry *entry, *found = NULL; 761 757 int i; 762 758 763 - sprintf(name, "dump-type%u-%u-%lu", type, (unsigned int)id, 759 + sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count, 764 760 time.tv_sec); 765 761 766 762 spin_lock(&efivars->lock); ··· 811 807 return 0; 812 808 } 813 809 814 - static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, 810 + static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count, 815 811 struct timespec *timespec, 816 812 char **buf, struct pstore_info *psi) 817 813 { ··· 820 816 821 817 static int efi_pstore_write(enum pstore_type_id type, 822 818 enum kmsg_dump_reason reason, u64 *id, 823 - unsigned int part, size_t size, struct pstore_info *psi) 819 + unsigned int part, int count, size_t size, 820 + struct pstore_info *psi) 824 821 { 825 822 return 0; 826 823 } 827 824 828 - static int efi_pstore_erase(enum pstore_type_id type, u64 id, 825 + static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, 829 826 struct timespec time, struct pstore_info *psi) 830 827 { 831 828 return 0;
+5 -3
fs/pstore/inode.c
··· 49 49 struct pstore_info *psi; 50 50 enum pstore_type_id type; 51 51 u64 id; 52 + int count; 52 53 ssize_t size; 53 54 char data[]; 54 55 }; ··· 176 175 struct pstore_private *p = dentry->d_inode->i_private; 177 176 178 177 if (p->psi->erase) 179 - p->psi->erase(p->type, p->id, dentry->d_inode->i_ctime, 180 - p->psi); 178 + p->psi->erase(p->type, p->id, p->count, 179 + dentry->d_inode->i_ctime, p->psi); 181 180 182 181 return simple_unlink(dir, dentry); 183 182 } ··· 272 271 * Load it up with "size" bytes of data from "buf". 273 272 * Set the mtime & ctime to the date that this record was originally stored. 274 273 */ 275 - int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, 274 + int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count, 276 275 char *data, size_t size, struct timespec time, 277 276 struct pstore_info *psi) 278 277 { ··· 308 307 goto fail_alloc; 309 308 private->type = type; 310 309 private->id = id; 310 + private->count = count; 311 311 private->psi = psi; 312 312 313 313 switch (type) {
+1 -1
fs/pstore/internal.h
··· 50 50 extern void pstore_set_kmsg_bytes(int); 51 51 extern void pstore_get_records(int); 52 52 extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, 53 - char *data, size_t size, 53 + int count, char *data, size_t size, 54 54 struct timespec time, struct pstore_info *psi); 55 55 extern int pstore_is_mounted(void); 56 56
+7 -6
fs/pstore/platform.c
··· 136 136 break; 137 137 138 138 ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part, 139 - hsize + len, psinfo); 139 + oopscount, hsize + len, psinfo); 140 140 if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted()) 141 141 pstore_new_entry = 1; 142 142 ··· 173 173 spin_lock_irqsave(&psinfo->buf_lock, flags); 174 174 } 175 175 memcpy(psinfo->buf, s, c); 176 - psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo); 176 + psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, 0, c, psinfo); 177 177 spin_unlock_irqrestore(&psinfo->buf_lock, flags); 178 178 s += c; 179 179 c = e - s; ··· 197 197 198 198 static int pstore_write_compat(enum pstore_type_id type, 199 199 enum kmsg_dump_reason reason, 200 - u64 *id, unsigned int part, 200 + u64 *id, unsigned int part, int count, 201 201 size_t size, struct pstore_info *psi) 202 202 { 203 203 return psi->write_buf(type, reason, id, part, psinfo->buf, size, psi); ··· 267 267 char *buf = NULL; 268 268 ssize_t size; 269 269 u64 id; 270 + int count; 270 271 enum pstore_type_id type; 271 272 struct timespec time; 272 273 int failed = 0, rc; ··· 279 278 if (psi->open && psi->open(psi)) 280 279 goto out; 281 280 282 - while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) { 283 - rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size, 284 - time, psi); 281 + while ((size = psi->read(&id, &type, &count, &time, &buf, psi)) > 0) { 282 + rc = pstore_mkfile(type, psi->name, id, count, buf, 283 + (size_t)size, time, psi); 285 284 kfree(buf); 286 285 buf = NULL; 287 286 if (rc && (rc != -EEXIST || !quiet))
+3 -4
fs/pstore/ram.c
··· 132 132 } 133 133 134 134 static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, 135 - struct timespec *time, 136 - char **buf, 137 - struct pstore_info *psi) 135 + int *count, struct timespec *time, 136 + char **buf, struct pstore_info *psi) 138 137 { 139 138 ssize_t size; 140 139 struct ramoops_context *cxt = psi->data; ··· 235 236 return 0; 236 237 } 237 238 238 - static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, 239 + static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count, 239 240 struct timespec time, struct pstore_info *psi) 240 241 { 241 242 struct ramoops_context *cxt = psi->data;
+5 -3
include/linux/pstore.h
··· 50 50 int (*open)(struct pstore_info *psi); 51 51 int (*close)(struct pstore_info *psi); 52 52 ssize_t (*read)(u64 *id, enum pstore_type_id *type, 53 - struct timespec *time, char **buf, 53 + int *count, struct timespec *time, char **buf, 54 54 struct pstore_info *psi); 55 55 int (*write)(enum pstore_type_id type, 56 56 enum kmsg_dump_reason reason, u64 *id, 57 - unsigned int part, size_t size, struct pstore_info *psi); 57 + unsigned int part, int count, size_t size, 58 + struct pstore_info *psi); 58 59 int (*write_buf)(enum pstore_type_id type, 59 60 enum kmsg_dump_reason reason, u64 *id, 60 61 unsigned int part, const char *buf, size_t size, 61 62 struct pstore_info *psi); 62 63 int (*erase)(enum pstore_type_id type, u64 id, 63 - struct timespec time, struct pstore_info *psi); 64 + int count, struct timespec time, 65 + struct pstore_info *psi); 64 66 void *data; 65 67 }; 66 68