aboutsummaryrefslogtreecommitdiffstats
path: root/fs/pstore/platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/pstore/platform.c')
-rw-r--r--fs/pstore/platform.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index ca60ebcfb15f..0472924024cc 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -28,6 +28,7 @@
28#include <linux/timer.h> 28#include <linux/timer.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <linux/hardirq.h>
31#include <linux/workqueue.h> 32#include <linux/workqueue.h>
32 33
33#include "internal.h" 34#include "internal.h"
@@ -88,13 +89,20 @@ static void pstore_dump(struct kmsg_dumper *dumper,
88 u64 id; 89 u64 id;
89 int hsize; 90 int hsize;
90 unsigned int part = 1; 91 unsigned int part = 1;
92 unsigned long flags = 0;
93 int is_locked = 0;
91 94
92 if (reason < ARRAY_SIZE(reason_str)) 95 if (reason < ARRAY_SIZE(reason_str))
93 why = reason_str[reason]; 96 why = reason_str[reason];
94 else 97 else
95 why = "Unknown"; 98 why = "Unknown";
96 99
97 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);
98 oopscount++; 106 oopscount++;
99 while (total < kmsg_bytes) { 107 while (total < kmsg_bytes) {
100 dst = psinfo->buf; 108 dst = psinfo->buf;
@@ -123,7 +131,11 @@ static void pstore_dump(struct kmsg_dumper *dumper,
123 total += l1_cpy + l2_cpy; 131 total += l1_cpy + l2_cpy;
124 part++; 132 part++;
125 } 133 }
126 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);
127} 139}
128 140
129static struct kmsg_dumper pstore_dumper = { 141static struct kmsg_dumper pstore_dumper = {
@@ -188,11 +200,12 @@ void pstore_get_records(int quiet)
188 enum pstore_type_id type; 200 enum pstore_type_id type;
189 struct timespec time; 201 struct timespec time;
190 int failed = 0, rc; 202 int failed = 0, rc;
203 unsigned long flags;
191 204
192 if (!psi) 205 if (!psi)
193 return; 206 return;
194 207
195 mutex_lock(&psinfo->buf_mutex); 208 spin_lock_irqsave(&psinfo->buf_lock, flags);
196 rc = psi->open(psi); 209 rc = psi->open(psi);
197 if (rc) 210 if (rc)
198 goto out; 211 goto out;
@@ -205,7 +218,7 @@ void pstore_get_records(int quiet)
205 } 218 }
206 psi->close(psi); 219 psi->close(psi);
207out: 220out:
208 mutex_unlock(&psinfo->buf_mutex); 221 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
209 222
210 if (failed) 223 if (failed)
211 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",
@@ -233,7 +246,8 @@ static void pstore_timefunc(unsigned long dummy)
233 */ 246 */
234int 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)
235{ 248{
236 u64 id; 249 u64 id;
250 unsigned long flags;
237 251
238 if (!psinfo) 252 if (!psinfo)
239 return -ENODEV; 253 return -ENODEV;
@@ -241,13 +255,13 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
241 if (size > psinfo->bufsize) 255 if (size > psinfo->bufsize)
242 return -EFBIG; 256 return -EFBIG;
243 257
244 mutex_lock(&psinfo->buf_mutex); 258 spin_lock_irqsave(&psinfo->buf_lock, flags);
245 memcpy(psinfo->buf, buf, size); 259 memcpy(psinfo->buf, buf, size);
246 id = psinfo->write(type, 0, size, psinfo); 260 id = psinfo->write(type, 0, size, psinfo);
247 if (pstore_is_mounted()) 261 if (pstore_is_mounted())
248 pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf, 262 pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
249 size, CURRENT_TIME, psinfo); 263 size, CURRENT_TIME, psinfo);
250 mutex_unlock(&psinfo->buf_mutex); 264 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
251 265
252 return 0; 266 return 0;
253} 267}