Blame view

fs/pstore/inode.c 10.9 KB
450515395   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
ca01d6dd2   Tony Luck   pstore: new files...
2
3
4
5
  /*
   * Persistent Storage - ramfs parts.
   *
   * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
ca01d6dd2   Tony Luck   pstore: new files...
6
7
8
9
10
11
12
13
14
   */
  
  #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...
15
  #include <linux/list.h>
ca01d6dd2   Tony Luck   pstore: new files...
16
17
  #include <linux/string.h>
  #include <linux/mount.h>
060287b8c   Anton Vorontsov   pstore: Add persi...
18
  #include <linux/seq_file.h>
ca01d6dd2   Tony Luck   pstore: new files...
19
  #include <linux/ramfs.h>
366f7e7a7   Tony Luck   pstore: use mount...
20
  #include <linux/parser.h>
ca01d6dd2   Tony Luck   pstore: new files...
21
22
23
24
25
26
27
28
29
  #include <linux/sched.h>
  #include <linux/magic.h>
  #include <linux/pstore.h>
  #include <linux/slab.h>
  #include <linux/uaccess.h>
  
  #include "internal.h"
  
  #define	PSTORE_NAMELEN	64
db23491c7   Kees Cook   pstore: Convert "...
30
  static DEFINE_MUTEX(records_list_lock);
47af61ffb   Kees Cook   pstore: Rename "a...
31
  static LIST_HEAD(records_list);
6dda92669   Tony Luck   pstore: defer ins...
32

27e5041a8   Kees Cook   pstore: Add locki...
33
34
  static DEFINE_MUTEX(pstore_sb_lock);
  static struct super_block *pstore_sb;
ca01d6dd2   Tony Luck   pstore: new files...
35
  struct pstore_private {
6dda92669   Tony Luck   pstore: defer ins...
36
  	struct list_head list;
609e28bb1   Kees Cook   pstore: Remove fi...
37
  	struct dentry *dentry;
83f70f076   Kees Cook   pstore: Do not du...
38
39
  	struct pstore_record *record;
  	size_t total_size;
ca01d6dd2   Tony Luck   pstore: new files...
40
  };
060287b8c   Anton Vorontsov   pstore: Add persi...
41
42
43
44
45
46
47
  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...
48
49
50
51
  static void free_pstore_private(struct pstore_private *private)
  {
  	if (!private)
  		return;
83f70f076   Kees Cook   pstore: Do not du...
52
53
54
55
  	if (private->record) {
  		kfree(private->record->buf);
  		kfree(private->record);
  	}
1dfff7dd6   Kees Cook   pstore: Pass reco...
56
57
  	kfree(private);
  }
060287b8c   Anton Vorontsov   pstore: Add persi...
58
59
60
61
62
63
64
65
  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...
66
  	data->off = ps->total_size % REC_SIZE;
060287b8c   Anton Vorontsov   pstore: Add persi...
67
  	data->off += *pos * REC_SIZE;
83f70f076   Kees Cook   pstore: Do not du...
68
  	if (data->off + REC_SIZE > ps->total_size) {
060287b8c   Anton Vorontsov   pstore: Add persi...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  		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;
6c871b731   Vasily Averin   pstore: pstore_ft...
86
  	(*pos)++;
060287b8c   Anton Vorontsov   pstore: Add persi...
87
  	data->off += REC_SIZE;
83f70f076   Kees Cook   pstore: Do not du...
88
  	if (data->off + REC_SIZE > ps->total_size)
060287b8c   Anton Vorontsov   pstore: Add persi...
89
  		return NULL;
060287b8c   Anton Vorontsov   pstore: Add persi...
90
91
92
93
94
95
96
  	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...
97
  	struct pstore_ftrace_record *rec;
6c871b731   Vasily Averin   pstore: pstore_ft...
98
99
  	if (!data)
  		return 0;
83f70f076   Kees Cook   pstore: Do not du...
100
  	rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off);
060287b8c   Anton Vorontsov   pstore: Add persi...
101

d75f773c8   Sakari Ailus   treewide: Switch ...
102
103
  	seq_printf(s, "CPU:%d ts:%llu %08lx  %08lx  %ps <- %pS
  ",
fbccdeb8d   Joel Fernandes   pstore: Add ftrac...
104
105
106
107
  		   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...
108
109
110
111
112
113
114
115
116
117
  
  	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...
118
119
120
  static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
  						size_t count, loff_t *ppos)
  {
060287b8c   Anton Vorontsov   pstore: Add persi...
121
122
  	struct seq_file *sf = file->private_data;
  	struct pstore_private *ps = sf->private;
fbe0aa1f3   Tony Luck   Some fixes for ps...
123

83f70f076   Kees Cook   pstore: Do not du...
124
  	if (ps->record->type == PSTORE_TYPE_FTRACE)
060287b8c   Anton Vorontsov   pstore: Add persi...
125
  		return seq_read(file, userbuf, count, ppos);
83f70f076   Kees Cook   pstore: Do not du...
126
127
  	return simple_read_from_buffer(userbuf, count, ppos,
  				       ps->record->buf, ps->total_size);
fbe0aa1f3   Tony Luck   Some fixes for ps...
128
  }
060287b8c   Anton Vorontsov   pstore: Add persi...
129
130
131
132
133
134
  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...
135
  	if (ps->record->type == PSTORE_TYPE_FTRACE)
060287b8c   Anton Vorontsov   pstore: Add persi...
136
137
138
139
140
141
142
143
144
145
146
  		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...
147
  static loff_t pstore_file_llseek(struct file *file, loff_t off, int whence)
060287b8c   Anton Vorontsov   pstore: Add persi...
148
149
150
151
  {
  	struct seq_file *sf = file->private_data;
  
  	if (sf->op)
965c8e59c   Andrew Morton   lseek: the "whenc...
152
153
  		return seq_lseek(file, off, whence);
  	return default_llseek(file, off, whence);
060287b8c   Anton Vorontsov   pstore: Add persi...
154
  }
fbe0aa1f3   Tony Luck   Some fixes for ps...
155
  static const struct file_operations pstore_file_operations = {
060287b8c   Anton Vorontsov   pstore: Add persi...
156
157
158
159
  	.open		= pstore_file_open,
  	.read		= pstore_file_read,
  	.llseek		= pstore_file_llseek,
  	.release	= seq_release,
fbe0aa1f3   Tony Luck   Some fixes for ps...
160
  };
ca01d6dd2   Tony Luck   pstore: new files...
161
162
163
164
165
166
167
  
  /*
   * 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...
168
  	struct pstore_private *p = d_inode(dentry)->i_private;
83f70f076   Kees Cook   pstore: Do not du...
169
  	struct pstore_record *record = p->record;
7a0ad5468   Kees Cook   pstore: Refactor ...
170
  	int rc = 0;
ca01d6dd2   Tony Luck   pstore: new files...
171

a61072aae   Kees Cook   pstore: Replace a...
172
  	if (!record->psi->erase)
bf2883339   Aruna Balakrishnaiah   pstore: Fail to u...
173
  		return -EPERM;
a61072aae   Kees Cook   pstore: Replace a...
174

7a0ad5468   Kees Cook   pstore: Refactor ...
175
176
177
178
179
180
  	/* Make sure we can't race while removing this file. */
  	mutex_lock(&records_list_lock);
  	if (!list_empty(&p->list))
  		list_del_init(&p->list);
  	else
  		rc = -ENOENT;
609e28bb1   Kees Cook   pstore: Remove fi...
181
  	p->dentry = NULL;
7a0ad5468   Kees Cook   pstore: Refactor ...
182
183
184
  	mutex_unlock(&records_list_lock);
  	if (rc)
  		return rc;
a61072aae   Kees Cook   pstore: Replace a...
185
186
187
  	mutex_lock(&record->psi->read_mutex);
  	record->psi->erase(record);
  	mutex_unlock(&record->psi->read_mutex);
ca01d6dd2   Tony Luck   pstore: new files...
188
189
190
  
  	return simple_unlink(dir, dentry);
  }
a872d5101   Tony Luck   pstore: fix leaki...
191
192
  static void pstore_evict_inode(struct inode *inode)
  {
6dda92669   Tony Luck   pstore: defer ins...
193
  	struct pstore_private	*p = inode->i_private;
6dda92669   Tony Luck   pstore: defer ins...
194

dbd5768f8   Jan Kara   vfs: Rename end_w...
195
  	clear_inode(inode);
7a0ad5468   Kees Cook   pstore: Refactor ...
196
  	free_pstore_private(p);
a872d5101   Tony Luck   pstore: fix leaki...
197
  }
ca01d6dd2   Tony Luck   pstore: new files...
198
199
200
201
  static const struct inode_operations pstore_dir_inode_operations = {
  	.lookup		= simple_lookup,
  	.unlink		= pstore_unlink,
  };
22a71c305   Al Viro   pstore: trim psto...
202
  static struct inode *pstore_get_inode(struct super_block *sb)
fbe0aa1f3   Tony Luck   Some fixes for ps...
203
204
  {
  	struct inode *inode = new_inode(sb);
fbe0aa1f3   Tony Luck   Some fixes for ps...
205
206
  	if (inode) {
  		inode->i_ino = get_next_ino();
078cd8279   Deepa Dinamani   fs: Replace CURRE...
207
  		inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
fbe0aa1f3   Tony Luck   Some fixes for ps...
208
209
210
  	}
  	return inode;
  }
366f7e7a7   Tony Luck   pstore: use mount...
211
212
213
214
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
  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...
244
245
246
247
248
249
250
251
252
  /*
   * 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...
253
254
  static int pstore_remount(struct super_block *sb, int *flags, char *data)
  {
02b9984d6   Theodore Ts'o   fs: push sync_fil...
255
  	sync_filesystem(sb);
366f7e7a7   Tony Luck   pstore: use mount...
256
257
258
259
  	parse_options(data);
  
  	return 0;
  }
ca01d6dd2   Tony Luck   pstore: new files...
260
261
262
  static const struct super_operations pstore_ops = {
  	.statfs		= simple_statfs,
  	.drop_inode	= generic_delete_inode,
a872d5101   Tony Luck   pstore: fix leaki...
263
  	.evict_inode	= pstore_evict_inode,
366f7e7a7   Tony Luck   pstore: use mount...
264
  	.remount_fs	= pstore_remount,
349d74389   David Howells   pstore: Implement...
265
  	.show_options	= pstore_show_options,
ca01d6dd2   Tony Luck   pstore: new files...
266
  };
27e5041a8   Kees Cook   pstore: Add locki...
267
  static struct dentry *psinfo_lock_root(void)
ca01d6dd2   Tony Luck   pstore: new files...
268
  {
27e5041a8   Kees Cook   pstore: Add locki...
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  	struct dentry *root;
  
  	mutex_lock(&pstore_sb_lock);
  	/*
  	 * Having no backend is fine -- no records appear.
  	 * Not being mounted is fine -- nothing to do.
  	 */
  	if (!psinfo || !pstore_sb) {
  		mutex_unlock(&pstore_sb_lock);
  		return NULL;
  	}
  
  	root = pstore_sb->s_root;
  	inode_lock(d_inode(root));
  	mutex_unlock(&pstore_sb_lock);
  
  	return root;
ca01d6dd2   Tony Luck   pstore: new files...
286
  }
609e28bb1   Kees Cook   pstore: Remove fi...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  int pstore_put_backend_records(struct pstore_info *psi)
  {
  	struct pstore_private *pos, *tmp;
  	struct dentry *root;
  	int rc = 0;
  
  	root = psinfo_lock_root();
  	if (!root)
  		return 0;
  
  	mutex_lock(&records_list_lock);
  	list_for_each_entry_safe(pos, tmp, &records_list, list) {
  		if (pos->record->psi == psi) {
  			list_del_init(&pos->list);
  			rc = simple_unlink(d_inode(root), pos->dentry);
  			if (WARN_ON(rc))
  				break;
  			d_drop(pos->dentry);
  			dput(pos->dentry);
  			pos->dentry = NULL;
  		}
  	}
  	mutex_unlock(&records_list_lock);
  
  	inode_unlock(d_inode(root));
  
  	return rc;
  }
ca01d6dd2   Tony Luck   pstore: new files...
315
316
317
318
319
  /*
   * 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...
320
  int pstore_mkfile(struct dentry *root, struct pstore_record *record)
ca01d6dd2   Tony Luck   pstore: new files...
321
  {
ca01d6dd2   Tony Luck   pstore: new files...
322
323
  	struct dentry		*dentry;
  	struct inode		*inode;
6dda92669   Tony Luck   pstore: defer ins...
324
  	int			rc = 0;
ca01d6dd2   Tony Luck   pstore: new files...
325
  	char			name[PSTORE_NAMELEN];
6dda92669   Tony Luck   pstore: defer ins...
326
  	struct pstore_private	*private, *pos;
1edd1aa39   Kees Cook   pstore: Switch ps...
327
  	size_t			size = record->size + record->ecc_notice_size;
6dda92669   Tony Luck   pstore: defer ins...
328

27e5041a8   Kees Cook   pstore: Add locki...
329
330
  	if (WARN_ON(!inode_is_locked(d_inode(root))))
  		return -EINVAL;
3a7d2fd16   Kees Cook   pstore: Solve loc...
331

27e5041a8   Kees Cook   pstore: Add locki...
332
333
  	rc = -EEXIST;
  	/* Skip records that are already present in the filesystem. */
db23491c7   Kees Cook   pstore: Convert "...
334
  	mutex_lock(&records_list_lock);
47af61ffb   Kees Cook   pstore: Rename "a...
335
  	list_for_each_entry(pos, &records_list, list) {
83f70f076   Kees Cook   pstore: Do not du...
336
337
  		if (pos->record->type == record->type &&
  		    pos->record->id == record->id &&
27e5041a8   Kees Cook   pstore: Add locki...
338
339
  		    pos->record->psi == record->psi)
  			goto fail;
6dda92669   Tony Luck   pstore: defer ins...
340
  	}
ca01d6dd2   Tony Luck   pstore: new files...
341
342
  
  	rc = -ENOMEM;
3a7d2fd16   Kees Cook   pstore: Solve loc...
343
  	inode = pstore_get_inode(root->d_sb);
ca01d6dd2   Tony Luck   pstore: new files...
344
345
  	if (!inode)
  		goto fail;
22a71c305   Al Viro   pstore: trim psto...
346
347
  	inode->i_mode = S_IFREG | 0444;
  	inode->i_fop = &pstore_file_operations;
f0f23e546   Joel Fernandes (Google)   pstore: Map PSTOR...
348
349
350
351
  	scnprintf(name, sizeof(name), "%s-%s-%llu%s",
  			pstore_type_to_name(record->type),
  			record->psi->name, record->id,
  			record->compressed ? ".enc.z" : "");
ca01d6dd2   Tony Luck   pstore: new files...
352

4c6d80e11   Norbert Manthey   pstore: Fix doubl...
353
354
355
  	private = kzalloc(sizeof(*private), GFP_KERNEL);
  	if (!private)
  		goto fail_inode;
ca01d6dd2   Tony Luck   pstore: new files...
356
  	dentry = d_alloc_name(root, name);
c39524e67   Dan Carpenter   pstore: d_alloc_n...
357
  	if (!dentry)
3a7d2fd16   Kees Cook   pstore: Solve loc...
358
  		goto fail_private;
ca01d6dd2   Tony Luck   pstore: new files...
359

609e28bb1   Kees Cook   pstore: Remove fi...
360
  	private->dentry = dentry;
4c6d80e11   Norbert Manthey   pstore: Fix doubl...
361
  	private->record = record;
83f70f076   Kees Cook   pstore: Do not du...
362
  	inode->i_size = private->total_size = size;
ca01d6dd2   Tony Luck   pstore: new files...
363
  	inode->i_private = private;
1edd1aa39   Kees Cook   pstore: Switch ps...
364
365
  	if (record->time.tv_sec)
  		inode->i_mtime = inode->i_ctime = record->time;
ca01d6dd2   Tony Luck   pstore: new files...
366

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

47af61ffb   Kees Cook   pstore: Rename "a...
369
  	list_add(&private->list, &records_list);
db23491c7   Kees Cook   pstore: Convert "...
370
  	mutex_unlock(&records_list_lock);
6dda92669   Tony Luck   pstore: defer ins...
371

fbe0aa1f3   Tony Luck   Some fixes for ps...
372
  	return 0;
ca01d6dd2   Tony Luck   pstore: new files...
373

3a7d2fd16   Kees Cook   pstore: Solve loc...
374
  fail_private:
1dfff7dd6   Kees Cook   pstore: Pass reco...
375
  	free_pstore_private(private);
4c6d80e11   Norbert Manthey   pstore: Fix doubl...
376
  fail_inode:
ca01d6dd2   Tony Luck   pstore: new files...
377
  	iput(inode);
ca01d6dd2   Tony Luck   pstore: new files...
378
  fail:
27e5041a8   Kees Cook   pstore: Add locki...
379
  	mutex_unlock(&records_list_lock);
ca01d6dd2   Tony Luck   pstore: new files...
380
381
  	return rc;
  }
3a7d2fd16   Kees Cook   pstore: Solve loc...
382
383
384
385
386
387
388
389
  /*
   * 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)
  {
3a7d2fd16   Kees Cook   pstore: Solve loc...
390
  	struct dentry *root;
27e5041a8   Kees Cook   pstore: Add locki...
391
392
  	root = psinfo_lock_root();
  	if (!root)
3a7d2fd16   Kees Cook   pstore: Solve loc...
393
  		return;
27e5041a8   Kees Cook   pstore: Add locki...
394
  	pstore_get_backend_records(psinfo, root, quiet);
3a7d2fd16   Kees Cook   pstore: Solve loc...
395
396
  	inode_unlock(d_inode(root));
  }
364ed2f46   Anton Vorontsov   pstore/inode: Mak...
397
  static int pstore_fill_super(struct super_block *sb, void *data, int silent)
ca01d6dd2   Tony Luck   pstore: new files...
398
  {
318ceed08   Al Viro   tidy up after d_m...
399
  	struct inode *inode;
ca01d6dd2   Tony Luck   pstore: new files...
400

ca01d6dd2   Tony Luck   pstore: new files...
401
  	sb->s_maxbytes		= MAX_LFS_FILESIZE;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
402
403
  	sb->s_blocksize		= PAGE_SIZE;
  	sb->s_blocksize_bits	= PAGE_SHIFT;
ca01d6dd2   Tony Luck   pstore: new files...
404
405
406
  	sb->s_magic		= PSTOREFS_MAGIC;
  	sb->s_op		= &pstore_ops;
  	sb->s_time_gran		= 1;
366f7e7a7   Tony Luck   pstore: use mount...
407
  	parse_options(data);
22a71c305   Al Viro   pstore: trim psto...
408
  	inode = pstore_get_inode(sb);
318ceed08   Al Viro   tidy up after d_m...
409
  	if (inode) {
d7caa3368   Kees Cook   pstore: Make defa...
410
  		inode->i_mode = S_IFDIR | 0750;
318ceed08   Al Viro   tidy up after d_m...
411
  		inode->i_op = &pstore_dir_inode_operations;
22a71c305   Al Viro   pstore: trim psto...
412
413
  		inode->i_fop = &simple_dir_operations;
  		inc_nlink(inode);
ca01d6dd2   Tony Luck   pstore: new files...
414
  	}
318ceed08   Al Viro   tidy up after d_m...
415
416
417
  	sb->s_root = d_make_root(inode);
  	if (!sb->s_root)
  		return -ENOMEM;
ca01d6dd2   Tony Luck   pstore: new files...
418

27e5041a8   Kees Cook   pstore: Add locki...
419
420
421
  	mutex_lock(&pstore_sb_lock);
  	pstore_sb = sb;
  	mutex_unlock(&pstore_sb_lock);
6dda92669   Tony Luck   pstore: defer ins...
422
  	pstore_get_records(0);
ca01d6dd2   Tony Luck   pstore: new files...
423
424
  
  	return 0;
ca01d6dd2   Tony Luck   pstore: new files...
425
  }
fbe0aa1f3   Tony Luck   Some fixes for ps...
426
427
  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...
428
  {
fbe0aa1f3   Tony Luck   Some fixes for ps...
429
  	return mount_single(fs_type, flags, data, pstore_fill_super);
ca01d6dd2   Tony Luck   pstore: new files...
430
431
432
433
  }
  
  static void pstore_kill_sb(struct super_block *sb)
  {
27e5041a8   Kees Cook   pstore: Add locki...
434
435
  	mutex_lock(&pstore_sb_lock);
  	WARN_ON(pstore_sb != sb);
ca01d6dd2   Tony Luck   pstore: new files...
436
437
  	kill_litter_super(sb);
  	pstore_sb = NULL;
27e5041a8   Kees Cook   pstore: Add locki...
438
439
  
  	mutex_lock(&records_list_lock);
7a0ad5468   Kees Cook   pstore: Refactor ...
440
  	INIT_LIST_HEAD(&records_list);
27e5041a8   Kees Cook   pstore: Add locki...
441
442
443
  	mutex_unlock(&records_list_lock);
  
  	mutex_unlock(&pstore_sb_lock);
ca01d6dd2   Tony Luck   pstore: new files...
444
445
446
  }
  
  static struct file_system_type pstore_fs_type = {
ee1d26742   Geliang Tang   pstore: add pstor...
447
  	.owner          = THIS_MODULE,
ca01d6dd2   Tony Luck   pstore: new files...
448
  	.name		= "pstore",
fbe0aa1f3   Tony Luck   Some fixes for ps...
449
  	.mount		= pstore_mount,
ca01d6dd2   Tony Luck   pstore: new files...
450
451
  	.kill_sb	= pstore_kill_sb,
  };
cb095afd4   Kees Cook   pstore: Centraliz...
452
  int __init pstore_init_fs(void)
ca01d6dd2   Tony Luck   pstore: new files...
453
  {
f9bb48825   Eric W. Biederman   sysfs: Create mou...
454
  	int err;
fb0af3f2b   Josh Boyer   pstore: Create a ...
455
456
  
  	/* Create a convenient mount point for people to access pstore */
f9bb48825   Eric W. Biederman   sysfs: Create mou...
457
458
  	err = sysfs_create_mount_point(fs_kobj, "pstore");
  	if (err)
fb0af3f2b   Josh Boyer   pstore: Create a ...
459
  		goto out;
fb0af3f2b   Josh Boyer   pstore: Create a ...
460
461
462
  
  	err = register_filesystem(&pstore_fs_type);
  	if (err < 0)
f9bb48825   Eric W. Biederman   sysfs: Create mou...
463
  		sysfs_remove_mount_point(fs_kobj, "pstore");
fb0af3f2b   Josh Boyer   pstore: Create a ...
464
465
466
  
  out:
  	return err;
ca01d6dd2   Tony Luck   pstore: new files...
467
  }
ca01d6dd2   Tony Luck   pstore: new files...
468

cb095afd4   Kees Cook   pstore: Centraliz...
469
  void __exit pstore_exit_fs(void)
ee1d26742   Geliang Tang   pstore: add pstor...
470
471
472
473
  {
  	unregister_filesystem(&pstore_fs_type);
  	sysfs_remove_mount_point(fs_kobj, "pstore");
  }