Blame view

fs/pstore/inode.c 11.7 KB
ca01d6dd2   Tony Luck   pstore: new files...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  /*
   * Persistent Storage - ramfs parts.
   *
   * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License version 2 as
   *  published by the Free Software Foundation.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; if not, write to the Free Software
   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
  #include <linux/module.h>
  #include <linux/fs.h>
  #include <linux/fsnotify.h>
  #include <linux/pagemap.h>
  #include <linux/highmem.h>
  #include <linux/time.h>
  #include <linux/init.h>
6dda92669   Tony Luck   pstore: defer ins...
27
  #include <linux/list.h>
ca01d6dd2   Tony Luck   pstore: new files...
28
29
  #include <linux/string.h>
  #include <linux/mount.h>
060287b8c   Anton Vorontsov   pstore: Add persi...
30
  #include <linux/seq_file.h>
ca01d6dd2   Tony Luck   pstore: new files...
31
  #include <linux/ramfs.h>
366f7e7a7   Tony Luck   pstore: use mount...
32
  #include <linux/parser.h>
ca01d6dd2   Tony Luck   pstore: new files...
33
34
35
36
  #include <linux/sched.h>
  #include <linux/magic.h>
  #include <linux/pstore.h>
  #include <linux/slab.h>
6dda92669   Tony Luck   pstore: defer ins...
37
  #include <linux/spinlock.h>
ca01d6dd2   Tony Luck   pstore: new files...
38
39
40
41
42
  #include <linux/uaccess.h>
  
  #include "internal.h"
  
  #define	PSTORE_NAMELEN	64
6dda92669   Tony Luck   pstore: defer ins...
43
44
  static DEFINE_SPINLOCK(allpstore_lock);
  static LIST_HEAD(allpstore);
ca01d6dd2   Tony Luck   pstore: new files...
45
  struct pstore_private {
6dda92669   Tony Luck   pstore: defer ins...
46
  	struct list_head list;
83f70f076   Kees Cook   pstore: Do not du...
47
48
  	struct pstore_record *record;
  	size_t total_size;
ca01d6dd2   Tony Luck   pstore: new files...
49
  };
060287b8c   Anton Vorontsov   pstore: Add persi...
50
51
52
53
54
55
56
  struct pstore_ftrace_seq_data {
  	const void *ptr;
  	size_t off;
  	size_t size;
  };
  
  #define REC_SIZE sizeof(struct pstore_ftrace_record)
1dfff7dd6   Kees Cook   pstore: Pass reco...
57
58
59
60
  static void free_pstore_private(struct pstore_private *private)
  {
  	if (!private)
  		return;
83f70f076   Kees Cook   pstore: Do not du...
61
62
63
64
  	if (private->record) {
  		kfree(private->record->buf);
  		kfree(private->record);
  	}
1dfff7dd6   Kees Cook   pstore: Pass reco...
65
66
  	kfree(private);
  }
060287b8c   Anton Vorontsov   pstore: Add persi...
67
68
69
70
71
72
73
74
  static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos)
  {
  	struct pstore_private *ps = s->private;
  	struct pstore_ftrace_seq_data *data;
  
  	data = kzalloc(sizeof(*data), GFP_KERNEL);
  	if (!data)
  		return NULL;
83f70f076   Kees Cook   pstore: Do not du...
75
  	data->off = ps->total_size % REC_SIZE;
060287b8c   Anton Vorontsov   pstore: Add persi...
76
  	data->off += *pos * REC_SIZE;
83f70f076   Kees Cook   pstore: Do not du...
77
  	if (data->off + REC_SIZE > ps->total_size) {
060287b8c   Anton Vorontsov   pstore: Add persi...
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  		kfree(data);
  		return NULL;
  	}
  
  	return data;
  
  }
  
  static void pstore_ftrace_seq_stop(struct seq_file *s, void *v)
  {
  	kfree(v);
  }
  
  static void *pstore_ftrace_seq_next(struct seq_file *s, void *v, loff_t *pos)
  {
  	struct pstore_private *ps = s->private;
  	struct pstore_ftrace_seq_data *data = v;
  
  	data->off += REC_SIZE;
83f70f076   Kees Cook   pstore: Do not du...
97
  	if (data->off + REC_SIZE > ps->total_size)
060287b8c   Anton Vorontsov   pstore: Add persi...
98
99
100
101
102
103
104
105
106
107
  		return NULL;
  
  	(*pos)++;
  	return data;
  }
  
  static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
  {
  	struct pstore_private *ps = s->private;
  	struct pstore_ftrace_seq_data *data = v;
83f70f076   Kees Cook   pstore: Do not du...
108
109
110
  	struct pstore_ftrace_record *rec;
  
  	rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off);
060287b8c   Anton Vorontsov   pstore: Add persi...
111

fbccdeb8d   Joel Fernandes   pstore: Add ftrac...
112
113
114
115
116
117
  	seq_printf(s, "CPU:%d ts:%llu %08lx  %08lx  %pf <- %pF
  ",
  		   pstore_ftrace_decode_cpu(rec),
  		   pstore_ftrace_read_timestamp(rec),
  		   rec->ip, rec->parent_ip, (void *)rec->ip,
  		   (void *)rec->parent_ip);
060287b8c   Anton Vorontsov   pstore: Add persi...
118
119
120
121
122
123
124
125
126
127
  
  	return 0;
  }
  
  static const struct seq_operations pstore_ftrace_seq_ops = {
  	.start	= pstore_ftrace_seq_start,
  	.next	= pstore_ftrace_seq_next,
  	.stop	= pstore_ftrace_seq_stop,
  	.show	= pstore_ftrace_seq_show,
  };
fbe0aa1f3   Tony Luck   Some fixes for ps...
128
129
130
  static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
  						size_t count, loff_t *ppos)
  {
060287b8c   Anton Vorontsov   pstore: Add persi...
131
132
  	struct seq_file *sf = file->private_data;
  	struct pstore_private *ps = sf->private;
fbe0aa1f3   Tony Luck   Some fixes for ps...
133

83f70f076   Kees Cook   pstore: Do not du...
134
  	if (ps->record->type == PSTORE_TYPE_FTRACE)
060287b8c   Anton Vorontsov   pstore: Add persi...
135
  		return seq_read(file, userbuf, count, ppos);
83f70f076   Kees Cook   pstore: Do not du...
136
137
  	return simple_read_from_buffer(userbuf, count, ppos,
  				       ps->record->buf, ps->total_size);
fbe0aa1f3   Tony Luck   Some fixes for ps...
138
  }
060287b8c   Anton Vorontsov   pstore: Add persi...
139
140
141
142
143
144
  static int pstore_file_open(struct inode *inode, struct file *file)
  {
  	struct pstore_private *ps = inode->i_private;
  	struct seq_file *sf;
  	int err;
  	const struct seq_operations *sops = NULL;
83f70f076   Kees Cook   pstore: Do not du...
145
  	if (ps->record->type == PSTORE_TYPE_FTRACE)
060287b8c   Anton Vorontsov   pstore: Add persi...
146
147
148
149
150
151
152
153
154
155
156
  		sops = &pstore_ftrace_seq_ops;
  
  	err = seq_open(file, sops);
  	if (err < 0)
  		return err;
  
  	sf = file->private_data;
  	sf->private = ps;
  
  	return 0;
  }
965c8e59c   Andrew Morton   lseek: the "whenc...
157
  static loff_t pstore_file_llseek(struct file *file, loff_t off, int whence)
060287b8c   Anton Vorontsov   pstore: Add persi...
158
159
160
161
  {
  	struct seq_file *sf = file->private_data;
  
  	if (sf->op)
965c8e59c   Andrew Morton   lseek: the "whenc...
162
163
  		return seq_lseek(file, off, whence);
  	return default_llseek(file, off, whence);
060287b8c   Anton Vorontsov   pstore: Add persi...
164
  }
fbe0aa1f3   Tony Luck   Some fixes for ps...
165
  static const struct file_operations pstore_file_operations = {
060287b8c   Anton Vorontsov   pstore: Add persi...
166
167
168
169
  	.open		= pstore_file_open,
  	.read		= pstore_file_read,
  	.llseek		= pstore_file_llseek,
  	.release	= seq_release,
fbe0aa1f3   Tony Luck   Some fixes for ps...
170
  };
ca01d6dd2   Tony Luck   pstore: new files...
171
172
173
174
175
176
177
  
  /*
   * When a file is unlinked from our file system we call the
   * platform driver to erase the record from persistent store.
   */
  static int pstore_unlink(struct inode *dir, struct dentry *dentry)
  {
2b0143b5c   David Howells   VFS: normal files...
178
  	struct pstore_private *p = d_inode(dentry)->i_private;
83f70f076   Kees Cook   pstore: Do not du...
179
  	struct pstore_record *record = p->record;
ca01d6dd2   Tony Luck   pstore: new files...
180

a61072aae   Kees Cook   pstore: Replace a...
181
  	if (!record->psi->erase)
bf2883339   Aruna Balakrishnaiah   pstore: Fail to u...
182
  		return -EPERM;
a61072aae   Kees Cook   pstore: Replace a...
183
184
185
186
  
  	mutex_lock(&record->psi->read_mutex);
  	record->psi->erase(record);
  	mutex_unlock(&record->psi->read_mutex);
ca01d6dd2   Tony Luck   pstore: new files...
187
188
189
  
  	return simple_unlink(dir, dentry);
  }
a872d5101   Tony Luck   pstore: fix leaki...
190
191
  static void pstore_evict_inode(struct inode *inode)
  {
6dda92669   Tony Luck   pstore: defer ins...
192
193
  	struct pstore_private	*p = inode->i_private;
  	unsigned long		flags;
dbd5768f8   Jan Kara   vfs: Rename end_w...
194
  	clear_inode(inode);
6dda92669   Tony Luck   pstore: defer ins...
195
196
197
198
  	if (p) {
  		spin_lock_irqsave(&allpstore_lock, flags);
  		list_del(&p->list);
  		spin_unlock_irqrestore(&allpstore_lock, flags);
1dfff7dd6   Kees Cook   pstore: Pass reco...
199
  		free_pstore_private(p);
6dda92669   Tony Luck   pstore: defer ins...
200
  	}
a872d5101   Tony Luck   pstore: fix leaki...
201
  }
ca01d6dd2   Tony Luck   pstore: new files...
202
203
204
205
  static const struct inode_operations pstore_dir_inode_operations = {
  	.lookup		= simple_lookup,
  	.unlink		= pstore_unlink,
  };
22a71c305   Al Viro   pstore: trim psto...
206
  static struct inode *pstore_get_inode(struct super_block *sb)
fbe0aa1f3   Tony Luck   Some fixes for ps...
207
208
  {
  	struct inode *inode = new_inode(sb);
fbe0aa1f3   Tony Luck   Some fixes for ps...
209
210
  	if (inode) {
  		inode->i_ino = get_next_ino();
078cd8279   Deepa Dinamani   fs: Replace CURRE...
211
  		inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
fbe0aa1f3   Tony Luck   Some fixes for ps...
212
213
214
  	}
  	return inode;
  }
366f7e7a7   Tony Luck   pstore: use mount...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  enum {
  	Opt_kmsg_bytes, Opt_err
  };
  
  static const match_table_t tokens = {
  	{Opt_kmsg_bytes, "kmsg_bytes=%u"},
  	{Opt_err, NULL}
  };
  
  static void parse_options(char *options)
  {
  	char		*p;
  	substring_t	args[MAX_OPT_ARGS];
  	int		option;
  
  	if (!options)
  		return;
  
  	while ((p = strsep(&options, ",")) != NULL) {
  		int token;
  
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
  		switch (token) {
  		case Opt_kmsg_bytes:
  			if (!match_int(&args[0], &option))
  				pstore_set_kmsg_bytes(option);
  			break;
  		}
  	}
  }
349d74389   David Howells   pstore: Implement...
248
249
250
251
252
253
254
255
256
  /*
   * Display the mount options in /proc/mounts.
   */
  static int pstore_show_options(struct seq_file *m, struct dentry *root)
  {
  	if (kmsg_bytes != PSTORE_DEFAULT_KMSG_BYTES)
  		seq_printf(m, ",kmsg_bytes=%lu", kmsg_bytes);
  	return 0;
  }
366f7e7a7   Tony Luck   pstore: use mount...
257
258
  static int pstore_remount(struct super_block *sb, int *flags, char *data)
  {
02b9984d6   Theodore Ts'o   fs: push sync_fil...
259
  	sync_filesystem(sb);
366f7e7a7   Tony Luck   pstore: use mount...
260
261
262
263
  	parse_options(data);
  
  	return 0;
  }
ca01d6dd2   Tony Luck   pstore: new files...
264
265
266
  static const struct super_operations pstore_ops = {
  	.statfs		= simple_statfs,
  	.drop_inode	= generic_delete_inode,
a872d5101   Tony Luck   pstore: fix leaki...
267
  	.evict_inode	= pstore_evict_inode,
366f7e7a7   Tony Luck   pstore: use mount...
268
  	.remount_fs	= pstore_remount,
349d74389   David Howells   pstore: Implement...
269
  	.show_options	= pstore_show_options,
ca01d6dd2   Tony Luck   pstore: new files...
270
271
272
  };
  
  static struct super_block *pstore_sb;
ca01d6dd2   Tony Luck   pstore: new files...
273

7e26e9ff0   Geliang Tang   pstore: Fix retur...
274
  bool pstore_is_mounted(void)
ca01d6dd2   Tony Luck   pstore: new files...
275
  {
fbe0aa1f3   Tony Luck   Some fixes for ps...
276
  	return pstore_sb != NULL;
ca01d6dd2   Tony Luck   pstore: new files...
277
278
279
280
281
282
283
  }
  
  /*
   * Make a regular file in the root directory of our file system.
   * Load it up with "size" bytes of data from "buf".
   * Set the mtime & ctime to the date that this record was originally stored.
   */
3a7d2fd16   Kees Cook   pstore: Solve loc...
284
  int pstore_mkfile(struct dentry *root, struct pstore_record *record)
ca01d6dd2   Tony Luck   pstore: new files...
285
  {
ca01d6dd2   Tony Luck   pstore: new files...
286
287
  	struct dentry		*dentry;
  	struct inode		*inode;
6dda92669   Tony Luck   pstore: defer ins...
288
  	int			rc = 0;
ca01d6dd2   Tony Luck   pstore: new files...
289
  	char			name[PSTORE_NAMELEN];
6dda92669   Tony Luck   pstore: defer ins...
290
291
  	struct pstore_private	*private, *pos;
  	unsigned long		flags;
1edd1aa39   Kees Cook   pstore: Switch ps...
292
  	size_t			size = record->size + record->ecc_notice_size;
6dda92669   Tony Luck   pstore: defer ins...
293

3a7d2fd16   Kees Cook   pstore: Solve loc...
294
  	WARN_ON(!inode_is_locked(d_inode(root)));
6dda92669   Tony Luck   pstore: defer ins...
295
296
  	spin_lock_irqsave(&allpstore_lock, flags);
  	list_for_each_entry(pos, &allpstore, list) {
83f70f076   Kees Cook   pstore: Do not du...
297
298
299
  		if (pos->record->type == record->type &&
  		    pos->record->id == record->id &&
  		    pos->record->psi == record->psi) {
6dda92669   Tony Luck   pstore: defer ins...
300
301
302
303
304
305
306
  			rc = -EEXIST;
  			break;
  		}
  	}
  	spin_unlock_irqrestore(&allpstore_lock, flags);
  	if (rc)
  		return rc;
ca01d6dd2   Tony Luck   pstore: new files...
307
308
  
  	rc = -ENOMEM;
3a7d2fd16   Kees Cook   pstore: Solve loc...
309
  	inode = pstore_get_inode(root->d_sb);
ca01d6dd2   Tony Luck   pstore: new files...
310
311
  	if (!inode)
  		goto fail;
22a71c305   Al Viro   pstore: trim psto...
312
313
  	inode->i_mode = S_IFREG | 0444;
  	inode->i_fop = &pstore_file_operations;
1dfff7dd6   Kees Cook   pstore: Pass reco...
314
  	private = kzalloc(sizeof(*private), GFP_KERNEL);
ca01d6dd2   Tony Luck   pstore: new files...
315
316
  	if (!private)
  		goto fail_alloc;
83f70f076   Kees Cook   pstore: Do not du...
317
  	private->record = record;
ca01d6dd2   Tony Luck   pstore: new files...
318

1edd1aa39   Kees Cook   pstore: Switch ps...
319
  	switch (record->type) {
ca01d6dd2   Tony Luck   pstore: new files...
320
  	case PSTORE_TYPE_DMESG:
d3762358a   Kees Cook   pstore: Fix forma...
321
  		scnprintf(name, sizeof(name), "dmesg-%s-%llu%s",
1edd1aa39   Kees Cook   pstore: Switch ps...
322
323
  			  record->psi->name, record->id,
  			  record->compressed ? ".enc.z" : "");
ca01d6dd2   Tony Luck   pstore: new files...
324
  		break;
f29e5956a   Anton Vorontsov   pstore: Add conso...
325
  	case PSTORE_TYPE_CONSOLE:
d3762358a   Kees Cook   pstore: Fix forma...
326
  		scnprintf(name, sizeof(name), "console-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
327
  			  record->psi->name, record->id);
f29e5956a   Anton Vorontsov   pstore: Add conso...
328
  		break;
060287b8c   Anton Vorontsov   pstore: Add persi...
329
  	case PSTORE_TYPE_FTRACE:
d3762358a   Kees Cook   pstore: Fix forma...
330
  		scnprintf(name, sizeof(name), "ftrace-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
331
  			  record->psi->name, record->id);
060287b8c   Anton Vorontsov   pstore: Add persi...
332
  		break;
ca01d6dd2   Tony Luck   pstore: new files...
333
  	case PSTORE_TYPE_MCE:
d3762358a   Kees Cook   pstore: Fix forma...
334
  		scnprintf(name, sizeof(name), "mce-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
335
  			  record->psi->name, record->id);
ca01d6dd2   Tony Luck   pstore: new files...
336
  		break;
69020eea9   Aruna Balakrishnaiah   powerpc/pseries: ...
337
  	case PSTORE_TYPE_PPC_RTAS:
d3762358a   Kees Cook   pstore: Fix forma...
338
  		scnprintf(name, sizeof(name), "rtas-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
339
  			  record->psi->name, record->id);
69020eea9   Aruna Balakrishnaiah   powerpc/pseries: ...
340
  		break;
f33f748c9   Aruna Balakrishnaiah   powerpc/pseries: ...
341
  	case PSTORE_TYPE_PPC_OF:
d3762358a   Kees Cook   pstore: Fix forma...
342
  		scnprintf(name, sizeof(name), "powerpc-ofw-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
343
  			  record->psi->name, record->id);
f33f748c9   Aruna Balakrishnaiah   powerpc/pseries: ...
344
  		break;
a5e4797b0   Aruna Balakrishnaiah   powerpc/pseries: ...
345
  	case PSTORE_TYPE_PPC_COMMON:
d3762358a   Kees Cook   pstore: Fix forma...
346
  		scnprintf(name, sizeof(name), "powerpc-common-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
347
  			  record->psi->name, record->id);
a5e4797b0   Aruna Balakrishnaiah   powerpc/pseries: ...
348
  		break;
9d5438f46   Mark Salyzyn   pstore: Add pmsg ...
349
  	case PSTORE_TYPE_PMSG:
d3762358a   Kees Cook   pstore: Fix forma...
350
  		scnprintf(name, sizeof(name), "pmsg-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
351
  			  record->psi->name, record->id);
9d5438f46   Mark Salyzyn   pstore: Add pmsg ...
352
  		break;
ae011d2e4   Hari Bathini   pstore: Add pstor...
353
  	case PSTORE_TYPE_PPC_OPAL:
d3762358a   Kees Cook   pstore: Fix forma...
354
  		scnprintf(name, sizeof(name), "powerpc-opal-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
355
  			  record->psi->name, record->id);
ae011d2e4   Hari Bathini   pstore: Add pstor...
356
  		break;
ca01d6dd2   Tony Luck   pstore: new files...
357
  	case PSTORE_TYPE_UNKNOWN:
d3762358a   Kees Cook   pstore: Fix forma...
358
  		scnprintf(name, sizeof(name), "unknown-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
359
  			  record->psi->name, record->id);
ca01d6dd2   Tony Luck   pstore: new files...
360
361
  		break;
  	default:
d3762358a   Kees Cook   pstore: Fix forma...
362
  		scnprintf(name, sizeof(name), "type%d-%s-%llu",
1edd1aa39   Kees Cook   pstore: Switch ps...
363
  			  record->type, record->psi->name, record->id);
ca01d6dd2   Tony Luck   pstore: new files...
364
365
  		break;
  	}
ca01d6dd2   Tony Luck   pstore: new files...
366
  	dentry = d_alloc_name(root, name);
c39524e67   Dan Carpenter   pstore: d_alloc_n...
367
  	if (!dentry)
3a7d2fd16   Kees Cook   pstore: Solve loc...
368
  		goto fail_private;
ca01d6dd2   Tony Luck   pstore: new files...
369

83f70f076   Kees Cook   pstore: Do not du...
370
  	inode->i_size = private->total_size = size;
ca01d6dd2   Tony Luck   pstore: new files...
371
372
  
  	inode->i_private = private;
1edd1aa39   Kees Cook   pstore: Switch ps...
373
374
  	if (record->time.tv_sec)
  		inode->i_mtime = inode->i_ctime = record->time;
ca01d6dd2   Tony Luck   pstore: new files...
375

fbe0aa1f3   Tony Luck   Some fixes for ps...
376
  	d_add(dentry, inode);
ca01d6dd2   Tony Luck   pstore: new files...
377

6dda92669   Tony Luck   pstore: defer ins...
378
379
380
  	spin_lock_irqsave(&allpstore_lock, flags);
  	list_add(&private->list, &allpstore);
  	spin_unlock_irqrestore(&allpstore_lock, flags);
fbe0aa1f3   Tony Luck   Some fixes for ps...
381
  	return 0;
ca01d6dd2   Tony Luck   pstore: new files...
382

3a7d2fd16   Kees Cook   pstore: Solve loc...
383
  fail_private:
1dfff7dd6   Kees Cook   pstore: Pass reco...
384
  	free_pstore_private(private);
ca01d6dd2   Tony Luck   pstore: new files...
385
386
387
388
389
390
  fail_alloc:
  	iput(inode);
  
  fail:
  	return rc;
  }
3a7d2fd16   Kees Cook   pstore: Solve loc...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  /*
   * Read all the records from the persistent store. Create
   * files in our filesystem.  Don't warn about -EEXIST errors
   * when we are re-scanning the backing store looking to add new
   * error records.
   */
  void pstore_get_records(int quiet)
  {
  	struct pstore_info *psi = psinfo;
  	struct dentry *root;
  
  	if (!psi || !pstore_sb)
  		return;
  
  	root = pstore_sb->s_root;
  
  	inode_lock(d_inode(root));
  	pstore_get_backend_records(psi, root, quiet);
  	inode_unlock(d_inode(root));
  }
364ed2f46   Anton Vorontsov   pstore/inode: Mak...
411
  static int pstore_fill_super(struct super_block *sb, void *data, int silent)
ca01d6dd2   Tony Luck   pstore: new files...
412
  {
318ceed08   Al Viro   tidy up after d_m...
413
  	struct inode *inode;
ca01d6dd2   Tony Luck   pstore: new files...
414

ca01d6dd2   Tony Luck   pstore: new files...
415
416
417
  	pstore_sb = sb;
  
  	sb->s_maxbytes		= MAX_LFS_FILESIZE;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
418
419
  	sb->s_blocksize		= PAGE_SIZE;
  	sb->s_blocksize_bits	= PAGE_SHIFT;
ca01d6dd2   Tony Luck   pstore: new files...
420
421
422
  	sb->s_magic		= PSTOREFS_MAGIC;
  	sb->s_op		= &pstore_ops;
  	sb->s_time_gran		= 1;
366f7e7a7   Tony Luck   pstore: use mount...
423
  	parse_options(data);
22a71c305   Al Viro   pstore: trim psto...
424
  	inode = pstore_get_inode(sb);
318ceed08   Al Viro   tidy up after d_m...
425
  	if (inode) {
d7caa3368   Kees Cook   pstore: Make defa...
426
  		inode->i_mode = S_IFDIR | 0750;
318ceed08   Al Viro   tidy up after d_m...
427
  		inode->i_op = &pstore_dir_inode_operations;
22a71c305   Al Viro   pstore: trim psto...
428
429
  		inode->i_fop = &simple_dir_operations;
  		inc_nlink(inode);
ca01d6dd2   Tony Luck   pstore: new files...
430
  	}
318ceed08   Al Viro   tidy up after d_m...
431
432
433
  	sb->s_root = d_make_root(inode);
  	if (!sb->s_root)
  		return -ENOMEM;
ca01d6dd2   Tony Luck   pstore: new files...
434

6dda92669   Tony Luck   pstore: defer ins...
435
  	pstore_get_records(0);
ca01d6dd2   Tony Luck   pstore: new files...
436
437
  
  	return 0;
ca01d6dd2   Tony Luck   pstore: new files...
438
  }
fbe0aa1f3   Tony Luck   Some fixes for ps...
439
440
  static struct dentry *pstore_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
ca01d6dd2   Tony Luck   pstore: new files...
441
  {
fbe0aa1f3   Tony Luck   Some fixes for ps...
442
  	return mount_single(fs_type, flags, data, pstore_fill_super);
ca01d6dd2   Tony Luck   pstore: new files...
443
444
445
446
447
448
  }
  
  static void pstore_kill_sb(struct super_block *sb)
  {
  	kill_litter_super(sb);
  	pstore_sb = NULL;
ca01d6dd2   Tony Luck   pstore: new files...
449
450
451
  }
  
  static struct file_system_type pstore_fs_type = {
ee1d26742   Geliang Tang   pstore: add pstor...
452
  	.owner          = THIS_MODULE,
ca01d6dd2   Tony Luck   pstore: new files...
453
  	.name		= "pstore",
fbe0aa1f3   Tony Luck   Some fixes for ps...
454
  	.mount		= pstore_mount,
ca01d6dd2   Tony Luck   pstore: new files...
455
456
457
458
459
  	.kill_sb	= pstore_kill_sb,
  };
  
  static int __init init_pstore_fs(void)
  {
f9bb48825   Eric W. Biederman   sysfs: Create mou...
460
  	int err;
fb0af3f2b   Josh Boyer   pstore: Create a ...
461
462
  
  	/* Create a convenient mount point for people to access pstore */
f9bb48825   Eric W. Biederman   sysfs: Create mou...
463
464
  	err = sysfs_create_mount_point(fs_kobj, "pstore");
  	if (err)
fb0af3f2b   Josh Boyer   pstore: Create a ...
465
  		goto out;
fb0af3f2b   Josh Boyer   pstore: Create a ...
466
467
468
  
  	err = register_filesystem(&pstore_fs_type);
  	if (err < 0)
f9bb48825   Eric W. Biederman   sysfs: Create mou...
469
  		sysfs_remove_mount_point(fs_kobj, "pstore");
fb0af3f2b   Josh Boyer   pstore: Create a ...
470
471
472
  
  out:
  	return err;
ca01d6dd2   Tony Luck   pstore: new files...
473
474
  }
  module_init(init_pstore_fs)
ee1d26742   Geliang Tang   pstore: add pstor...
475
476
477
478
479
480
  static void __exit exit_pstore_fs(void)
  {
  	unregister_filesystem(&pstore_fs_type);
  	sysfs_remove_mount_point(fs_kobj, "pstore");
  }
  module_exit(exit_pstore_fs)
ca01d6dd2   Tony Luck   pstore: new files...
481
482
  MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>");
  MODULE_LICENSE("GPL");