aboutsummaryrefslogtreecommitdiffstats
path: root/fs/pstore
diff options
context:
space:
mode:
Diffstat (limited to 'fs/pstore')
-rw-r--r--fs/pstore/inode.c40
-rw-r--r--fs/pstore/internal.h2
-rw-r--r--fs/pstore/platform.c54
3 files changed, 82 insertions, 14 deletions
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..ca60ebcfb15f 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -25,12 +25,29 @@
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/workqueue.h>
30 32
31#include "internal.h" 33#include "internal.h"
32 34
33/* 35/*
36 * We defer making "oops" entries appear in pstore - see
37 * whether the system is actually still running well enough
38 * to let someone see the entry
39 */
40#define PSTORE_INTERVAL (60 * HZ)
41
42static int pstore_new_entry;
43
44static void pstore_timefunc(unsigned long);
45static DEFINE_TIMER(pstore_timer, pstore_timefunc, 0, 0);
46
47static void pstore_dowork(struct work_struct *);
48static DECLARE_WORK(pstore_work, pstore_dowork);
49
50/*
34 * pstore_lock just protects "psinfo" during 51 * pstore_lock just protects "psinfo" during
35 * calls to pstore_register() 52 * calls to pstore_register()
36 */ 53 */
@@ -100,9 +117,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
100 id = psinfo->write(PSTORE_TYPE_DMESG, part, 117 id = psinfo->write(PSTORE_TYPE_DMESG, part,
101 hsize + l1_cpy + l2_cpy, psinfo); 118 hsize + l1_cpy + l2_cpy, psinfo);
102 if (reason == KMSG_DUMP_OOPS && pstore_is_mounted()) 119 if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
103 pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, 120 pstore_new_entry = 1;
104 psinfo->buf, hsize + l1_cpy + l2_cpy,
105 CURRENT_TIME, psinfo);
106 l1 -= l1_cpy; 121 l1 -= l1_cpy;
107 l2 -= l2_cpy; 122 l2 -= l2_cpy;
108 total += l1_cpy + l2_cpy; 123 total += l1_cpy + l2_cpy;
@@ -148,19 +163,24 @@ int pstore_register(struct pstore_info *psi)
148 } 163 }
149 164
150 if (pstore_is_mounted()) 165 if (pstore_is_mounted())
151 pstore_get_records(); 166 pstore_get_records(0);
152 167
153 kmsg_dump_register(&pstore_dumper); 168 kmsg_dump_register(&pstore_dumper);
154 169
170 pstore_timer.expires = jiffies + PSTORE_INTERVAL;
171 add_timer(&pstore_timer);
172
155 return 0; 173 return 0;
156} 174}
157EXPORT_SYMBOL_GPL(pstore_register); 175EXPORT_SYMBOL_GPL(pstore_register);
158 176
159/* 177/*
160 * Read all the records from the persistent store. Create and 178 * Read all the records from the persistent store. Create
161 * file files in our filesystem. 179 * files in our filesystem. Don't warn about -EEXIST errors
180 * when we are re-scanning the backing store looking to add new
181 * error records.
162 */ 182 */
163void pstore_get_records(void) 183void pstore_get_records(int quiet)
164{ 184{
165 struct pstore_info *psi = psinfo; 185 struct pstore_info *psi = psinfo;
166 ssize_t size; 186 ssize_t size;
@@ -178,8 +198,9 @@ void pstore_get_records(void)
178 goto out; 198 goto out;
179 199
180 while ((size = psi->read(&id, &type, &time, psi)) > 0) { 200 while ((size = psi->read(&id, &type, &time, psi)) > 0) {
181 if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size, 201 rc = pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
182 time, psi)) 202 time, psi);
203 if (rc && (rc != -EEXIST || !quiet))
183 failed++; 204 failed++;
184 } 205 }
185 psi->close(psi); 206 psi->close(psi);
@@ -191,6 +212,21 @@ out:
191 failed, psi->name); 212 failed, psi->name);
192} 213}
193 214
215static void pstore_dowork(struct work_struct *work)
216{
217 pstore_get_records(1);
218}
219
220static void pstore_timefunc(unsigned long dummy)
221{
222 if (pstore_new_entry) {
223 pstore_new_entry = 0;
224 schedule_work(&pstore_work);
225 }
226
227 mod_timer(&pstore_timer, jiffies + PSTORE_INTERVAL);
228}
229
194/* 230/*
195 * Call platform driver to write a record to the 231 * Call platform driver to write a record to the
196 * persistent store. 232 * persistent store.