aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-01 13:52:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-01 13:52:29 -0400
commit1c398651518c7e25a9fb3f08b456c73d5ca22469 (patch)
tree116ad4df5c8faa5f8e0d7982c479bf08ea01f2ec
parentf470f8d4e702593ee1d0852871ad80373bce707b (diff)
parentb238b8fa93353ab50c9a2b1e2fa47a0ab01c37cd (diff)
Merge branch 'pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux
* 'pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux: pstore: make pstore write function return normal success/fail value pstore: change mutex locking to spin_locks pstore: defer inserting OOPS entries into pstore
-rw-r--r--drivers/acpi/apei/erst.c12
-rw-r--r--drivers/firmware/efivars.c19
-rw-r--r--fs/pstore/inode.c40
-rw-r--r--fs/pstore/internal.h2
-rw-r--r--fs/pstore/platform.c93
-rw-r--r--include/linux/pstore.h6
6 files changed, 129 insertions, 43 deletions
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 2ca59dc69f7f..127408069ca7 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -933,7 +933,7 @@ static int erst_open_pstore(struct pstore_info *psi);
933static int erst_close_pstore(struct pstore_info *psi); 933static int erst_close_pstore(struct pstore_info *psi);
934static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, 934static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
935 struct timespec *time, struct pstore_info *psi); 935 struct timespec *time, struct pstore_info *psi);
936static u64 erst_writer(enum pstore_type_id type, unsigned int part, 936static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
937 size_t size, struct pstore_info *psi); 937 size_t size, struct pstore_info *psi);
938static int erst_clearer(enum pstore_type_id type, u64 id, 938static int erst_clearer(enum pstore_type_id type, u64 id,
939 struct pstore_info *psi); 939 struct pstore_info *psi);
@@ -1040,11 +1040,12 @@ out:
1040 return (rc < 0) ? rc : (len - sizeof(*rcd)); 1040 return (rc < 0) ? rc : (len - sizeof(*rcd));
1041} 1041}
1042 1042
1043static u64 erst_writer(enum pstore_type_id type, unsigned int part, 1043static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
1044 size_t size, struct pstore_info *psi) 1044 size_t size, struct pstore_info *psi)
1045{ 1045{
1046 struct cper_pstore_record *rcd = (struct cper_pstore_record *) 1046 struct cper_pstore_record *rcd = (struct cper_pstore_record *)
1047 (erst_info.buf - sizeof(*rcd)); 1047 (erst_info.buf - sizeof(*rcd));
1048 int ret;
1048 1049
1049 memset(rcd, 0, sizeof(*rcd)); 1050 memset(rcd, 0, sizeof(*rcd));
1050 memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE); 1051 memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
@@ -1079,9 +1080,10 @@ static u64 erst_writer(enum pstore_type_id type, unsigned int part,
1079 } 1080 }
1080 rcd->sec_hdr.section_severity = CPER_SEV_FATAL; 1081 rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
1081 1082
1082 erst_write(&rcd->hdr); 1083 ret = erst_write(&rcd->hdr);
1084 *id = rcd->hdr.record_id;
1083 1085
1084 return rcd->hdr.record_id; 1086 return ret;
1085} 1087}
1086 1088
1087static int erst_clearer(enum pstore_type_id type, u64 id, 1089static int erst_clearer(enum pstore_type_id type, u64 id,
@@ -1165,7 +1167,7 @@ static int __init erst_init(void)
1165 goto err_release_erange; 1167 goto err_release_erange;
1166 1168
1167 buf = kmalloc(erst_erange.size, GFP_KERNEL); 1169 buf = kmalloc(erst_erange.size, GFP_KERNEL);
1168 mutex_init(&erst_info.buf_mutex); 1170 spin_lock_init(&erst_info.buf_lock);
1169 if (buf) { 1171 if (buf) {
1170 erst_info.buf = buf + sizeof(struct cper_pstore_record); 1172 erst_info.buf = buf + sizeof(struct cper_pstore_record);
1171 erst_info.bufsize = erst_erange.size - 1173 erst_info.bufsize = erst_erange.size -
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index eb80b549ed8d..8370f72d87ff 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -490,8 +490,8 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
490 return 0; 490 return 0;
491} 491}
492 492
493static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part, 493static int efi_pstore_write(enum pstore_type_id type, u64 *id,
494 size_t size, struct pstore_info *psi) 494 unsigned int part, size_t size, struct pstore_info *psi)
495{ 495{
496 char name[DUMP_NAME_LEN]; 496 char name[DUMP_NAME_LEN];
497 char stub_name[DUMP_NAME_LEN]; 497 char stub_name[DUMP_NAME_LEN];
@@ -499,7 +499,7 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
499 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 499 efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
500 struct efivars *efivars = psi->data; 500 struct efivars *efivars = psi->data;
501 struct efivar_entry *entry, *found = NULL; 501 struct efivar_entry *entry, *found = NULL;
502 int i; 502 int i, ret = 0;
503 503
504 sprintf(stub_name, "dump-type%u-%u-", type, part); 504 sprintf(stub_name, "dump-type%u-%u-", type, part);
505 sprintf(name, "%s%lu", stub_name, get_seconds()); 505 sprintf(name, "%s%lu", stub_name, get_seconds());
@@ -548,18 +548,19 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
548 efivar_unregister(found); 548 efivar_unregister(found);
549 549
550 if (size) 550 if (size)
551 efivar_create_sysfs_entry(efivars, 551 ret = efivar_create_sysfs_entry(efivars,
552 utf16_strsize(efi_name, 552 utf16_strsize(efi_name,
553 DUMP_NAME_LEN * 2), 553 DUMP_NAME_LEN * 2),
554 efi_name, &vendor); 554 efi_name, &vendor);
555 555
556 return part; 556 *id = part;
557 return ret;
557}; 558};
558 559
559static int efi_pstore_erase(enum pstore_type_id type, u64 id, 560static int efi_pstore_erase(enum pstore_type_id type, u64 id,
560 struct pstore_info *psi) 561 struct pstore_info *psi)
561{ 562{
562 efi_pstore_write(type, id, 0, psi); 563 efi_pstore_write(type, &id, (unsigned int)id, 0, psi);
563 564
564 return 0; 565 return 0;
565} 566}
@@ -580,8 +581,8 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
580 return -1; 581 return -1;
581} 582}
582 583
583static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part, 584static int efi_pstore_write(enum pstore_type_id type, u64 *id,
584 size_t size, struct pstore_info *psi) 585 unsigned int part, size_t size, struct pstore_info *psi)
585{ 586{
586 return 0; 587 return 0;
587} 588}
@@ -978,7 +979,7 @@ int register_efivars(struct efivars *efivars,
978 if (efivars->efi_pstore_info.buf) { 979 if (efivars->efi_pstore_info.buf) {
979 efivars->efi_pstore_info.bufsize = 1024; 980 efivars->efi_pstore_info.bufsize = 1024;
980 efivars->efi_pstore_info.data = efivars; 981 efivars->efi_pstore_info.data = efivars;
981 mutex_init(&efivars->efi_pstore_info.buf_mutex); 982 spin_lock_init(&efivars->efi_pstore_info.buf_lock);
982 pstore_register(&efivars->efi_pstore_info); 983 pstore_register(&efivars->efi_pstore_info);
983 } 984 }
984 985
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 893b961dcfd8..379a02dc1217 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -24,6 +24,7 @@
24#include <linux/highmem.h> 24#include <linux/highmem.h>
25#include <linux/time.h> 25#include <linux/time.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/list.h>
27#include <linux/string.h> 28#include <linux/string.h>
28#include <linux/mount.h> 29#include <linux/mount.h>
29#include <linux/ramfs.h> 30#include <linux/ramfs.h>
@@ -32,13 +33,18 @@
32#include <linux/magic.h> 33#include <linux/magic.h>
33#include <linux/pstore.h> 34#include <linux/pstore.h>
34#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/spinlock.h>
35#include <linux/uaccess.h> 37#include <linux/uaccess.h>
36 38
37#include "internal.h" 39#include "internal.h"
38 40
39#define PSTORE_NAMELEN 64 41#define PSTORE_NAMELEN 64
40 42
43static DEFINE_SPINLOCK(allpstore_lock);
44static LIST_HEAD(allpstore);
45
41struct pstore_private { 46struct pstore_private {
47 struct list_head list;
42 struct pstore_info *psi; 48 struct pstore_info *psi;
43 enum pstore_type_id type; 49 enum pstore_type_id type;
44 u64 id; 50 u64 id;
@@ -81,8 +87,16 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
81 87
82static void pstore_evict_inode(struct inode *inode) 88static void pstore_evict_inode(struct inode *inode)
83{ 89{
90 struct pstore_private *p = inode->i_private;
91 unsigned long flags;
92
84 end_writeback(inode); 93 end_writeback(inode);
85 kfree(inode->i_private); 94 if (p) {
95 spin_lock_irqsave(&allpstore_lock, flags);
96 list_del(&p->list);
97 spin_unlock_irqrestore(&allpstore_lock, flags);
98 kfree(p);
99 }
86} 100}
87 101
88static const struct inode_operations pstore_dir_inode_operations = { 102static const struct inode_operations pstore_dir_inode_operations = {
@@ -182,9 +196,23 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
182 struct dentry *root = pstore_sb->s_root; 196 struct dentry *root = pstore_sb->s_root;
183 struct dentry *dentry; 197 struct dentry *dentry;
184 struct inode *inode; 198 struct inode *inode;
185 int rc; 199 int rc = 0;
186 char name[PSTORE_NAMELEN]; 200 char name[PSTORE_NAMELEN];
187 struct pstore_private *private; 201 struct pstore_private *private, *pos;
202 unsigned long flags;
203
204 spin_lock_irqsave(&allpstore_lock, flags);
205 list_for_each_entry(pos, &allpstore, list) {
206 if (pos->type == type &&
207 pos->id == id &&
208 pos->psi == psi) {
209 rc = -EEXIST;
210 break;
211 }
212 }
213 spin_unlock_irqrestore(&allpstore_lock, flags);
214 if (rc)
215 return rc;
188 216
189 rc = -ENOMEM; 217 rc = -ENOMEM;
190 inode = pstore_get_inode(pstore_sb, root->d_inode, S_IFREG | 0444, 0); 218 inode = pstore_get_inode(pstore_sb, root->d_inode, S_IFREG | 0444, 0);
@@ -229,6 +257,10 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
229 257
230 d_add(dentry, inode); 258 d_add(dentry, inode);
231 259
260 spin_lock_irqsave(&allpstore_lock, flags);
261 list_add(&private->list, &allpstore);
262 spin_unlock_irqrestore(&allpstore_lock, flags);
263
232 mutex_unlock(&root->d_inode->i_mutex); 264 mutex_unlock(&root->d_inode->i_mutex);
233 265
234 return 0; 266 return 0;
@@ -277,7 +309,7 @@ int pstore_fill_super(struct super_block *sb, void *data, int silent)
277 goto fail; 309 goto fail;
278 } 310 }
279 311
280 pstore_get_records(); 312 pstore_get_records(0);
281 313
282 return 0; 314 return 0;
283fail: 315fail:
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index 611c1b3c46fa..3bde461c3f34 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -1,5 +1,5 @@
1extern void pstore_set_kmsg_bytes(int); 1extern void pstore_set_kmsg_bytes(int);
2extern void pstore_get_records(void); 2extern void pstore_get_records(int);
3extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, 3extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
4 char *data, size_t size, 4 char *data, size_t size,
5 struct timespec time, struct pstore_info *psi); 5 struct timespec time, struct pstore_info *psi);
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index c5300ec31696..2bd620f0d796 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -25,12 +25,30 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/pstore.h> 26#include <linux/pstore.h>
27#include <linux/string.h> 27#include <linux/string.h>
28#include <linux/timer.h>
28#include <linux/slab.h> 29#include <linux/slab.h>
29#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <linux/hardirq.h>
32#include <linux/workqueue.h>
30 33
31#include "internal.h" 34#include "internal.h"
32 35
33/* 36/*
37 * We defer making "oops" entries appear in pstore - see
38 * whether the system is actually still running well enough
39 * to let someone see the entry
40 */
41#define PSTORE_INTERVAL (60 * HZ)
42
43static int pstore_new_entry;
44
45static void pstore_timefunc(unsigned long);
46static DEFINE_TIMER(pstore_timer, pstore_timefunc, 0, 0);
47
48static void pstore_dowork(struct work_struct *);
49static DECLARE_WORK(pstore_work, pstore_dowork);
50
51/*
34 * pstore_lock just protects "psinfo" during 52 * pstore_lock just protects "psinfo" during
35 * calls to pstore_register() 53 * calls to pstore_register()
36 */ 54 */
@@ -69,15 +87,22 @@ static void pstore_dump(struct kmsg_dumper *dumper,
69 unsigned long size, total = 0; 87 unsigned long size, total = 0;
70 char *dst, *why; 88 char *dst, *why;
71 u64 id; 89 u64 id;
72 int hsize; 90 int hsize, ret;
73 unsigned int part = 1; 91 unsigned int part = 1;
92 unsigned long flags = 0;
93 int is_locked = 0;
74 94
75 if (reason < ARRAY_SIZE(reason_str)) 95 if (reason < ARRAY_SIZE(reason_str))
76 why = reason_str[reason]; 96 why = reason_str[reason];
77 else 97 else
78 why = "Unknown"; 98 why = "Unknown";
79 99
80 mutex_lock(&psinfo->buf_mutex); 100 if (in_nmi()) {
101 is_locked = spin_trylock(&psinfo->buf_lock);
102 if (!is_locked)
103 pr_err("pstore dump routine blocked in NMI, may corrupt error record\n");
104 } else
105 spin_lock_irqsave(&psinfo->buf_lock, flags);
81 oopscount++; 106 oopscount++;
82 while (total < kmsg_bytes) { 107 while (total < kmsg_bytes) {
83 dst = psinfo->buf; 108 dst = psinfo->buf;
@@ -97,18 +122,20 @@ static void pstore_dump(struct kmsg_dumper *dumper,
97 memcpy(dst, s1 + s1_start, l1_cpy); 122 memcpy(dst, s1 + s1_start, l1_cpy);
98 memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy); 123 memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
99 124
100 id = psinfo->write(PSTORE_TYPE_DMESG, part, 125 ret = psinfo->write(PSTORE_TYPE_DMESG, &id, part,
101 hsize + l1_cpy + l2_cpy, psinfo); 126 hsize + l1_cpy + l2_cpy, psinfo);
102 if (reason == KMSG_DUMP_OOPS && pstore_is_mounted()) 127 if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
103 pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, 128 pstore_new_entry = 1;
104 psinfo->buf, hsize + l1_cpy + l2_cpy,
105 CURRENT_TIME, psinfo);
106 l1 -= l1_cpy; 129 l1 -= l1_cpy;
107 l2 -= l2_cpy; 130 l2 -= l2_cpy;
108 total += l1_cpy + l2_cpy; 131 total += l1_cpy + l2_cpy;
109 part++; 132 part++;
110 } 133 }
111 mutex_unlock(&psinfo->buf_mutex); 134 if (in_nmi()) {
135 if (is_locked)
136 spin_unlock(&psinfo->buf_lock);
137 } else
138 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
112} 139}
113 140
114static struct kmsg_dumper pstore_dumper = { 141static struct kmsg_dumper pstore_dumper = {
@@ -148,19 +175,24 @@ int pstore_register(struct pstore_info *psi)
148 } 175 }
149 176
150 if (pstore_is_mounted()) 177 if (pstore_is_mounted())
151 pstore_get_records(); 178 pstore_get_records(0);
152 179
153 kmsg_dump_register(&pstore_dumper); 180 kmsg_dump_register(&pstore_dumper);
154 181
182 pstore_timer.expires = jiffies + PSTORE_INTERVAL;
183 add_timer(&pstore_timer);
184
155 return 0; 185 return 0;
156} 186}
157EXPORT_SYMBOL_GPL(pstore_register); 187EXPORT_SYMBOL_GPL(pstore_register);
158 188
159/* 189/*
160 * Read all the records from the persistent store. Create and 190 * Read all the records from the persistent store. Create
161 * file files in our filesystem. 191 * files in our filesystem. Don't warn about -EEXIST errors
192 * when we are re-scanning the backing store looking to add new
193 * error records.
162 */ 194 */
163void pstore_get_records(void) 195void pstore_get_records(int quiet)
164{ 196{
165 struct pstore_info *psi = psinfo; 197 struct pstore_info *psi = psinfo;
166 ssize_t size; 198 ssize_t size;
@@ -168,36 +200,55 @@ void pstore_get_records(void)
168 enum pstore_type_id type; 200 enum pstore_type_id type;
169 struct timespec time; 201 struct timespec time;
170 int failed = 0, rc; 202 int failed = 0, rc;
203 unsigned long flags;
171 204
172 if (!psi) 205 if (!psi)
173 return; 206 return;
174 207
175 mutex_lock(&psinfo->buf_mutex); 208 spin_lock_irqsave(&psinfo->buf_lock, flags);
176 rc = psi->open(psi); 209 rc = psi->open(psi);
177 if (rc) 210 if (rc)
178 goto out; 211 goto out;
179 212
180 while ((size = psi->read(&id, &type, &time, psi)) > 0) { 213 while ((size = psi->read(&id, &type, &time, psi)) > 0) {
181 if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size, 214 rc = pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
182 time, psi)) 215 time, psi);
216 if (rc && (rc != -EEXIST || !quiet))
183 failed++; 217 failed++;
184 } 218 }
185 psi->close(psi); 219 psi->close(psi);
186out: 220out:
187 mutex_unlock(&psinfo->buf_mutex); 221 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
188 222
189 if (failed) 223 if (failed)
190 printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n", 224 printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
191 failed, psi->name); 225 failed, psi->name);
192} 226}
193 227
228static void pstore_dowork(struct work_struct *work)
229{
230 pstore_get_records(1);
231}
232
233static void pstore_timefunc(unsigned long dummy)
234{
235 if (pstore_new_entry) {
236 pstore_new_entry = 0;
237 schedule_work(&pstore_work);
238 }
239
240 mod_timer(&pstore_timer, jiffies + PSTORE_INTERVAL);
241}
242
194/* 243/*
195 * Call platform driver to write a record to the 244 * Call platform driver to write a record to the
196 * persistent store. 245 * persistent store.
197 */ 246 */
198int pstore_write(enum pstore_type_id type, char *buf, size_t size) 247int pstore_write(enum pstore_type_id type, char *buf, size_t size)
199{ 248{
200 u64 id; 249 u64 id;
250 int ret;
251 unsigned long flags;
201 252
202 if (!psinfo) 253 if (!psinfo)
203 return -ENODEV; 254 return -ENODEV;
@@ -205,13 +256,13 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
205 if (size > psinfo->bufsize) 256 if (size > psinfo->bufsize)
206 return -EFBIG; 257 return -EFBIG;
207 258
208 mutex_lock(&psinfo->buf_mutex); 259 spin_lock_irqsave(&psinfo->buf_lock, flags);
209 memcpy(psinfo->buf, buf, size); 260 memcpy(psinfo->buf, buf, size);
210 id = psinfo->write(type, 0, size, psinfo); 261 ret = psinfo->write(type, &id, 0, size, psinfo);
211 if (pstore_is_mounted()) 262 if (ret == 0 && pstore_is_mounted())
212 pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf, 263 pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
213 size, CURRENT_TIME, psinfo); 264 size, CURRENT_TIME, psinfo);
214 mutex_unlock(&psinfo->buf_mutex); 265 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
215 266
216 return 0; 267 return 0;
217} 268}
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index cc03bbf5c4b8..ea567321ae3c 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -32,15 +32,15 @@ enum pstore_type_id {
32struct pstore_info { 32struct pstore_info {
33 struct module *owner; 33 struct module *owner;
34 char *name; 34 char *name;
35 struct mutex buf_mutex; /* serialize access to 'buf' */ 35 spinlock_t buf_lock; /* serialize access to 'buf' */
36 char *buf; 36 char *buf;
37 size_t bufsize; 37 size_t bufsize;
38 int (*open)(struct pstore_info *psi); 38 int (*open)(struct pstore_info *psi);
39 int (*close)(struct pstore_info *psi); 39 int (*close)(struct pstore_info *psi);
40 ssize_t (*read)(u64 *id, enum pstore_type_id *type, 40 ssize_t (*read)(u64 *id, enum pstore_type_id *type,
41 struct timespec *time, struct pstore_info *psi); 41 struct timespec *time, struct pstore_info *psi);
42 u64 (*write)(enum pstore_type_id type, unsigned int part, 42 int (*write)(enum pstore_type_id type, u64 *id,
43 size_t size, struct pstore_info *psi); 43 unsigned int part, size_t size, struct pstore_info *psi);
44 int (*erase)(enum pstore_type_id type, u64 id, 44 int (*erase)(enum pstore_type_id type, u64 id,
45 struct pstore_info *psi); 45 struct pstore_info *psi);
46 void *data; 46 void *data;