Commit a2d773023552f68baa2db2226dfd6d761c0df5da

Authored by Linus Torvalds

Merge branch 'pstore-efi' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6

* 'pstore-efi' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6:
  efivars: Introduce PSTORE_EFI_ATTRIBUTES
  efivars: Use string functions in pstore_write
  efivars: introduce utf16_strncmp
  efivars: String functions
  efi: Add support for using efivars as a pstore backend
  pstore: Allow the user to explicitly choose a backend
  pstore: Make "part" unsigned
  pstore: Add extra context for writes and erases
  pstore: Extend API for more flexibility in new backends

Showing 9 changed files Side-by-side Diff

Documentation/ABI/testing/pstore
... ... @@ -39,4 +39,9 @@
39 39 multiple) files based on the record size of the underlying
40 40 persistent storage until at least this amount is reached.
41 41 Default is 10 Kbytes.
  42 +
  43 + Pstore only supports one backend at a time. If multiple
  44 + backends are available, the preferred backend may be
  45 + set by passing the pstore.backend= argument to the kernel at
  46 + boot time.
Documentation/kernel-parameters.txt
... ... @@ -2153,6 +2153,8 @@
2153 2153 [HW,MOUSE] Controls Logitech smartscroll autorepeat.
2154 2154 0 = disabled, 1 = enabled (default).
2155 2155  
  2156 + pstore.backend= Specify the name of the pstore backend to use
  2157 +
2156 2158 pt. [PARIDE]
2157 2159 See Documentation/blockdev/paride.txt.
2158 2160  
drivers/acpi/apei/erst.c
... ... @@ -932,8 +932,11 @@
932 932 static int erst_open_pstore(struct pstore_info *psi);
933 933 static int erst_close_pstore(struct pstore_info *psi);
934 934 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
935   - struct timespec *time);
936   -static u64 erst_writer(enum pstore_type_id type, size_t size);
  935 + struct timespec *time, struct pstore_info *psi);
  936 +static u64 erst_writer(enum pstore_type_id type, unsigned int part,
  937 + size_t size, struct pstore_info *psi);
  938 +static int erst_clearer(enum pstore_type_id type, u64 id,
  939 + struct pstore_info *psi);
937 940  
938 941 static struct pstore_info erst_info = {
939 942 .owner = THIS_MODULE,
... ... @@ -942,7 +945,7 @@
942 945 .close = erst_close_pstore,
943 946 .read = erst_reader,
944 947 .write = erst_writer,
945   - .erase = erst_clear
  948 + .erase = erst_clearer
946 949 };
947 950  
948 951 #define CPER_CREATOR_PSTORE \
... ... @@ -983,7 +986,7 @@
983 986 }
984 987  
985 988 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
986   - struct timespec *time)
  989 + struct timespec *time, struct pstore_info *psi)
987 990 {
988 991 int rc;
989 992 ssize_t len = 0;
... ... @@ -1037,7 +1040,8 @@
1037 1040 return (rc < 0) ? rc : (len - sizeof(*rcd));
1038 1041 }
1039 1042  
1040   -static u64 erst_writer(enum pstore_type_id type, size_t size)
  1043 +static u64 erst_writer(enum pstore_type_id type, unsigned int part,
  1044 + size_t size, struct pstore_info *psi)
1041 1045 {
1042 1046 struct cper_pstore_record *rcd = (struct cper_pstore_record *)
1043 1047 (erst_info.buf - sizeof(*rcd));
... ... @@ -1078,6 +1082,12 @@
1078 1082 erst_write(&rcd->hdr);
1079 1083  
1080 1084 return rcd->hdr.record_id;
  1085 +}
  1086 +
  1087 +static int erst_clearer(enum pstore_type_id type, u64 id,
  1088 + struct pstore_info *psi)
  1089 +{
  1090 + return erst_clear(id);
1081 1091 }
1082 1092  
1083 1093 static int __init erst_init(void)
drivers/firmware/efivars.c
... ... @@ -78,6 +78,7 @@
78 78 #include <linux/kobject.h>
79 79 #include <linux/device.h>
80 80 #include <linux/slab.h>
  81 +#include <linux/pstore.h>
81 82  
82 83 #include <asm/uaccess.h>
83 84  
... ... @@ -89,6 +90,8 @@
89 90 MODULE_LICENSE("GPL");
90 91 MODULE_VERSION(EFIVARS_VERSION);
91 92  
  93 +#define DUMP_NAME_LEN 52
  94 +
92 95 /*
93 96 * The maximum size of VariableName + Data = 1024
94 97 * Therefore, it's reasonable to save that much
... ... @@ -119,6 +122,10 @@
119 122 ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
120 123 };
121 124  
  125 +#define PSTORE_EFI_ATTRIBUTES \
  126 + (EFI_VARIABLE_NON_VOLATILE | \
  127 + EFI_VARIABLE_BOOTSERVICE_ACCESS | \
  128 + EFI_VARIABLE_RUNTIME_ACCESS)
122 129  
123 130 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
124 131 struct efivar_attribute efivar_attr_##_name = { \
125 132  
126 133  
127 134  
128 135  
129 136  
130 137  
131 138  
132 139  
133 140  
... ... @@ -141,38 +148,72 @@
141 148  
142 149 /* Return the number of unicode characters in data */
143 150 static unsigned long
144   -utf8_strlen(efi_char16_t *data, unsigned long maxlength)
  151 +utf16_strnlen(efi_char16_t *s, size_t maxlength)
145 152 {
146 153 unsigned long length = 0;
147 154  
148   - while (*data++ != 0 && length < maxlength)
  155 + while (*s++ != 0 && length < maxlength)
149 156 length++;
150 157 return length;
151 158 }
152 159  
  160 +static unsigned long
  161 +utf16_strlen(efi_char16_t *s)
  162 +{
  163 + return utf16_strnlen(s, ~0UL);
  164 +}
  165 +
153 166 /*
154 167 * Return the number of bytes is the length of this string
155 168 * Note: this is NOT the same as the number of unicode characters
156 169 */
157 170 static inline unsigned long
158   -utf8_strsize(efi_char16_t *data, unsigned long maxlength)
  171 +utf16_strsize(efi_char16_t *data, unsigned long maxlength)
159 172 {
160   - return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
  173 + return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
161 174 }
162 175  
  176 +static inline int
  177 +utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
  178 +{
  179 + while (1) {
  180 + if (len == 0)
  181 + return 0;
  182 + if (*a < *b)
  183 + return -1;
  184 + if (*a > *b)
  185 + return 1;
  186 + if (*a == 0) /* implies *b == 0 */
  187 + return 0;
  188 + a++;
  189 + b++;
  190 + len--;
  191 + }
  192 +}
  193 +
163 194 static efi_status_t
164   -get_var_data(struct efivars *efivars, struct efi_variable *var)
  195 +get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
165 196 {
166 197 efi_status_t status;
167 198  
168   - spin_lock(&efivars->lock);
169 199 var->DataSize = 1024;
170 200 status = efivars->ops->get_variable(var->VariableName,
171 201 &var->VendorGuid,
172 202 &var->Attributes,
173 203 &var->DataSize,
174 204 var->Data);
  205 + return status;
  206 +}
  207 +
  208 +static efi_status_t
  209 +get_var_data(struct efivars *efivars, struct efi_variable *var)
  210 +{
  211 + efi_status_t status;
  212 +
  213 + spin_lock(&efivars->lock);
  214 + status = get_var_data_locked(efivars, var);
175 215 spin_unlock(&efivars->lock);
  216 +
176 217 if (status != EFI_SUCCESS) {
177 218 printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
178 219 status);
179 220  
180 221  
... ... @@ -387,13 +428,181 @@
387 428 .default_attrs = def_attrs,
388 429 };
389 430  
  431 +static struct pstore_info efi_pstore_info;
  432 +
390 433 static inline void
391 434 efivar_unregister(struct efivar_entry *var)
392 435 {
393 436 kobject_put(&var->kobj);
394 437 }
395 438  
  439 +#ifdef CONFIG_PSTORE
396 440  
  441 +static int efi_pstore_open(struct pstore_info *psi)
  442 +{
  443 + struct efivars *efivars = psi->data;
  444 +
  445 + spin_lock(&efivars->lock);
  446 + efivars->walk_entry = list_first_entry(&efivars->list,
  447 + struct efivar_entry, list);
  448 + return 0;
  449 +}
  450 +
  451 +static int efi_pstore_close(struct pstore_info *psi)
  452 +{
  453 + struct efivars *efivars = psi->data;
  454 +
  455 + spin_unlock(&efivars->lock);
  456 + return 0;
  457 +}
  458 +
  459 +static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
  460 + struct timespec *timespec, struct pstore_info *psi)
  461 +{
  462 + efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
  463 + struct efivars *efivars = psi->data;
  464 + char name[DUMP_NAME_LEN];
  465 + int i;
  466 + unsigned int part, size;
  467 + unsigned long time;
  468 +
  469 + while (&efivars->walk_entry->list != &efivars->list) {
  470 + if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid,
  471 + vendor)) {
  472 + for (i = 0; i < DUMP_NAME_LEN; i++) {
  473 + name[i] = efivars->walk_entry->var.VariableName[i];
  474 + }
  475 + if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) {
  476 + *id = part;
  477 + timespec->tv_sec = time;
  478 + timespec->tv_nsec = 0;
  479 + get_var_data_locked(efivars, &efivars->walk_entry->var);
  480 + size = efivars->walk_entry->var.DataSize;
  481 + memcpy(psi->buf, efivars->walk_entry->var.Data, size);
  482 + efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
  483 + struct efivar_entry, list);
  484 + return size;
  485 + }
  486 + }
  487 + efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
  488 + struct efivar_entry, list);
  489 + }
  490 + return 0;
  491 +}
  492 +
  493 +static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
  494 + size_t size, struct pstore_info *psi)
  495 +{
  496 + char name[DUMP_NAME_LEN];
  497 + char stub_name[DUMP_NAME_LEN];
  498 + efi_char16_t efi_name[DUMP_NAME_LEN];
  499 + efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
  500 + struct efivars *efivars = psi->data;
  501 + struct efivar_entry *entry, *found = NULL;
  502 + int i;
  503 +
  504 + sprintf(stub_name, "dump-type%u-%u-", type, part);
  505 + sprintf(name, "%s%lu", stub_name, get_seconds());
  506 +
  507 + spin_lock(&efivars->lock);
  508 +
  509 + for (i = 0; i < DUMP_NAME_LEN; i++)
  510 + efi_name[i] = stub_name[i];
  511 +
  512 + /*
  513 + * Clean up any entries with the same name
  514 + */
  515 +
  516 + list_for_each_entry(entry, &efivars->list, list) {
  517 + get_var_data_locked(efivars, &entry->var);
  518 +
  519 + if (efi_guidcmp(entry->var.VendorGuid, vendor))
  520 + continue;
  521 + if (utf16_strncmp(entry->var.VariableName, efi_name,
  522 + utf16_strlen(efi_name)))
  523 + continue;
  524 + /* Needs to be a prefix */
  525 + if (entry->var.VariableName[utf16_strlen(efi_name)] == 0)
  526 + continue;
  527 +
  528 + /* found */
  529 + found = entry;
  530 + efivars->ops->set_variable(entry->var.VariableName,
  531 + &entry->var.VendorGuid,
  532 + PSTORE_EFI_ATTRIBUTES,
  533 + 0, NULL);
  534 + }
  535 +
  536 + if (found)
  537 + list_del(&found->list);
  538 +
  539 + for (i = 0; i < DUMP_NAME_LEN; i++)
  540 + efi_name[i] = name[i];
  541 +
  542 + efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
  543 + size, psi->buf);
  544 +
  545 + spin_unlock(&efivars->lock);
  546 +
  547 + if (found)
  548 + efivar_unregister(found);
  549 +
  550 + if (size)
  551 + efivar_create_sysfs_entry(efivars,
  552 + utf16_strsize(efi_name,
  553 + DUMP_NAME_LEN * 2),
  554 + efi_name, &vendor);
  555 +
  556 + return part;
  557 +};
  558 +
  559 +static int efi_pstore_erase(enum pstore_type_id type, u64 id,
  560 + struct pstore_info *psi)
  561 +{
  562 + efi_pstore_write(type, id, 0, psi);
  563 +
  564 + return 0;
  565 +}
  566 +#else
  567 +static int efi_pstore_open(struct pstore_info *psi)
  568 +{
  569 + return 0;
  570 +}
  571 +
  572 +static int efi_pstore_close(struct pstore_info *psi)
  573 +{
  574 + return 0;
  575 +}
  576 +
  577 +static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
  578 + struct timespec *time, struct pstore_info *psi)
  579 +{
  580 + return -1;
  581 +}
  582 +
  583 +static u64 efi_pstore_write(enum pstore_type_id type, int part, size_t size,
  584 + struct pstore_info *psi)
  585 +{
  586 + return 0;
  587 +}
  588 +
  589 +static int efi_pstore_erase(enum pstore_type_id type, u64 id,
  590 + struct pstore_info *psi)
  591 +{
  592 + return 0;
  593 +}
  594 +#endif
  595 +
  596 +static struct pstore_info efi_pstore_info = {
  597 + .owner = THIS_MODULE,
  598 + .name = "efi",
  599 + .open = efi_pstore_open,
  600 + .close = efi_pstore_close,
  601 + .read = efi_pstore_read,
  602 + .write = efi_pstore_write,
  603 + .erase = efi_pstore_erase,
  604 +};
  605 +
397 606 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
398 607 struct bin_attribute *bin_attr,
399 608 char *buf, loff_t pos, size_t count)
... ... @@ -414,8 +623,8 @@
414 623 * Does this variable already exist?
415 624 */
416 625 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
417   - strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
418   - strsize2 = utf8_strsize(new_var->VariableName, 1024);
  626 + strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
  627 + strsize2 = utf16_strsize(new_var->VariableName, 1024);
419 628 if (strsize1 == strsize2 &&
420 629 !memcmp(&(search_efivar->var.VariableName),
421 630 new_var->VariableName, strsize1) &&
... ... @@ -447,8 +656,8 @@
447 656  
448 657 /* Create the entry in sysfs. Locking is not required here */
449 658 status = efivar_create_sysfs_entry(efivars,
450   - utf8_strsize(new_var->VariableName,
451   - 1024),
  659 + utf16_strsize(new_var->VariableName,
  660 + 1024),
452 661 new_var->VariableName,
453 662 &new_var->VendorGuid);
454 663 if (status) {
... ... @@ -477,8 +686,8 @@
477 686 * Does this variable already exist?
478 687 */
479 688 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
480   - strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
481   - strsize2 = utf8_strsize(del_var->VariableName, 1024);
  689 + strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
  690 + strsize2 = utf16_strsize(del_var->VariableName, 1024);
482 691 if (strsize1 == strsize2 &&
483 692 !memcmp(&(search_efivar->var.VariableName),
484 693 del_var->VariableName, strsize1) &&
... ... @@ -762,6 +971,16 @@
762 971 error = create_efivars_bin_attributes(efivars);
763 972 if (error)
764 973 unregister_efivars(efivars);
  974 +
  975 + efivars->efi_pstore_info = efi_pstore_info;
  976 +
  977 + efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
  978 + if (efivars->efi_pstore_info.buf) {
  979 + efivars->efi_pstore_info.bufsize = 1024;
  980 + efivars->efi_pstore_info.data = efivars;
  981 + mutex_init(&efivars->efi_pstore_info.buf_mutex);
  982 + pstore_register(&efivars->efi_pstore_info);
  983 + }
765 984  
766 985 out:
767 986 kfree(variable_name);
... ... @@ -39,8 +39,9 @@
39 39 #define PSTORE_NAMELEN 64
40 40  
41 41 struct pstore_private {
  42 + struct pstore_info *psi;
  43 + enum pstore_type_id type;
42 44 u64 id;
43   - int (*erase)(u64);
44 45 ssize_t size;
45 46 char data[];
46 47 };
... ... @@ -73,7 +74,7 @@
73 74 {
74 75 struct pstore_private *p = dentry->d_inode->i_private;
75 76  
76   - p->erase(p->id);
  77 + p->psi->erase(p->type, p->id, p->psi);
77 78  
78 79 return simple_unlink(dir, dentry);
79 80 }
... ... @@ -175,8 +176,8 @@
175 176 * Set the mtime & ctime to the date that this record was originally stored.
176 177 */
177 178 int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
178   - char *data, size_t size,
179   - struct timespec time, int (*erase)(u64))
  179 + char *data, size_t size, struct timespec time,
  180 + struct pstore_info *psi)
180 181 {
181 182 struct dentry *root = pstore_sb->s_root;
182 183 struct dentry *dentry;
183 184  
... ... @@ -192,8 +193,9 @@
192 193 private = kmalloc(sizeof *private + size, GFP_KERNEL);
193 194 if (!private)
194 195 goto fail_alloc;
  196 + private->type = type;
195 197 private->id = id;
196   - private->erase = erase;
  198 + private->psi = psi;
197 199  
198 200 switch (type) {
199 201 case PSTORE_TYPE_DMESG:
fs/pstore/internal.h
... ... @@ -2,6 +2,6 @@
2 2 extern void pstore_get_records(void);
3 3 extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
4 4 char *data, size_t size,
5   - struct timespec time, int (*erase)(u64));
  5 + struct timespec time, struct pstore_info *psi);
6 6 extern int pstore_is_mounted(void);
fs/pstore/platform.c
... ... @@ -37,6 +37,8 @@
37 37 static DEFINE_SPINLOCK(pstore_lock);
38 38 static struct pstore_info *psinfo;
39 39  
  40 +static char *backend;
  41 +
40 42 /* How much of the console log to snapshot */
41 43 static unsigned long kmsg_bytes = 10240;
42 44  
... ... @@ -67,7 +69,8 @@
67 69 unsigned long size, total = 0;
68 70 char *dst, *why;
69 71 u64 id;
70   - int hsize, part = 1;
  72 + int hsize;
  73 + unsigned int part = 1;
71 74  
72 75 if (reason < ARRAY_SIZE(reason_str))
73 76 why = reason_str[reason];
... ... @@ -78,7 +81,7 @@
78 81 oopscount++;
79 82 while (total < kmsg_bytes) {
80 83 dst = psinfo->buf;
81   - hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part++);
  84 + hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
82 85 size = psinfo->bufsize - hsize;
83 86 dst += hsize;
84 87  
85 88  
86 89  
... ... @@ -94,14 +97,16 @@
94 97 memcpy(dst, s1 + s1_start, l1_cpy);
95 98 memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
96 99  
97   - id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy);
  100 + id = psinfo->write(PSTORE_TYPE_DMESG, part,
  101 + hsize + l1_cpy + l2_cpy, psinfo);
98 102 if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
99 103 pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
100 104 psinfo->buf, hsize + l1_cpy + l2_cpy,
101   - CURRENT_TIME, psinfo->erase);
  105 + CURRENT_TIME, psinfo);
102 106 l1 -= l1_cpy;
103 107 l2 -= l2_cpy;
104 108 total += l1_cpy + l2_cpy;
  109 + part++;
105 110 }
106 111 mutex_unlock(&psinfo->buf_mutex);
107 112 }
... ... @@ -128,6 +133,12 @@
128 133 spin_unlock(&pstore_lock);
129 134 return -EBUSY;
130 135 }
  136 +
  137 + if (backend && strcmp(backend, psi->name)) {
  138 + spin_unlock(&pstore_lock);
  139 + return -EINVAL;
  140 + }
  141 +
131 142 psinfo = psi;
132 143 spin_unlock(&pstore_lock);
133 144  
134 145  
... ... @@ -166,9 +177,9 @@
166 177 if (rc)
167 178 goto out;
168 179  
169   - while ((size = psi->read(&id, &type, &time)) > 0) {
  180 + while ((size = psi->read(&id, &type, &time, psi)) > 0) {
170 181 if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
171   - time, psi->erase))
  182 + time, psi))
172 183 failed++;
173 184 }
174 185 psi->close(psi);
175 186  
176 187  
... ... @@ -196,13 +207,16 @@
196 207  
197 208 mutex_lock(&psinfo->buf_mutex);
198 209 memcpy(psinfo->buf, buf, size);
199   - id = psinfo->write(type, size);
  210 + id = psinfo->write(type, 0, size, psinfo);
200 211 if (pstore_is_mounted())
201 212 pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
202   - size, CURRENT_TIME, psinfo->erase);
  213 + size, CURRENT_TIME, psinfo);
203 214 mutex_unlock(&psinfo->buf_mutex);
204 215  
205 216 return 0;
206 217 }
207 218 EXPORT_SYMBOL_GPL(pstore_write);
  219 +
  220 +module_param(backend, charp, 0444);
  221 +MODULE_PARM_DESC(backend, "Pstore backend to use");
... ... @@ -19,6 +19,7 @@
19 19 #include <linux/rtc.h>
20 20 #include <linux/ioport.h>
21 21 #include <linux/pfn.h>
  22 +#include <linux/pstore.h>
22 23  
23 24 #include <asm/page.h>
24 25 #include <asm/system.h>
... ... @@ -232,6 +233,9 @@
232 233 #define UV_SYSTEM_TABLE_GUID \
233 234 EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
234 235  
  236 +#define LINUX_EFI_CRASH_GUID \
  237 + EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
  238 +
235 239 typedef struct {
236 240 efi_guid_t guid;
237 241 unsigned long table;
... ... @@ -458,6 +462,8 @@
458 462 struct kset *kset;
459 463 struct bin_attribute *new_var, *del_var;
460 464 const struct efivar_operations *ops;
  465 + struct efivar_entry *walk_entry;
  466 + struct pstore_info efi_pstore_info;
461 467 };
462 468  
463 469 int register_efivars(struct efivars *efivars,
include/linux/pstore.h
... ... @@ -38,9 +38,12 @@
38 38 int (*open)(struct pstore_info *psi);
39 39 int (*close)(struct pstore_info *psi);
40 40 ssize_t (*read)(u64 *id, enum pstore_type_id *type,
41   - struct timespec *time);
42   - u64 (*write)(enum pstore_type_id type, size_t size);
43   - int (*erase)(u64 id);
  41 + struct timespec *time, struct pstore_info *psi);
  42 + u64 (*write)(enum pstore_type_id type, unsigned int part,
  43 + size_t size, struct pstore_info *psi);
  44 + int (*erase)(enum pstore_type_id type, u64 id,
  45 + struct pstore_info *psi);
  46 + void *data;
44 47 };
45 48  
46 49 #ifdef CONFIG_PSTORE