Blame view
fs/pstore/inode.c
11.7 KB
ca01d6dd2 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 pstore: defer ins... |
27 |
#include <linux/list.h> |
ca01d6dd2 pstore: new files... |
28 29 |
#include <linux/string.h> #include <linux/mount.h> |
060287b8c pstore: Add persi... |
30 |
#include <linux/seq_file.h> |
ca01d6dd2 pstore: new files... |
31 |
#include <linux/ramfs.h> |
366f7e7a7 pstore: use mount... |
32 |
#include <linux/parser.h> |
ca01d6dd2 pstore: new files... |
33 34 35 36 |
#include <linux/sched.h> #include <linux/magic.h> #include <linux/pstore.h> #include <linux/slab.h> |
6dda92669 pstore: defer ins... |
37 |
#include <linux/spinlock.h> |
ca01d6dd2 pstore: new files... |
38 39 40 41 42 |
#include <linux/uaccess.h> #include "internal.h" #define PSTORE_NAMELEN 64 |
6dda92669 pstore: defer ins... |
43 44 |
static DEFINE_SPINLOCK(allpstore_lock); static LIST_HEAD(allpstore); |
ca01d6dd2 pstore: new files... |
45 |
struct pstore_private { |
6dda92669 pstore: defer ins... |
46 |
struct list_head list; |
83f70f076 pstore: Do not du... |
47 48 |
struct pstore_record *record; size_t total_size; |
ca01d6dd2 pstore: new files... |
49 |
}; |
060287b8c 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 pstore: Pass reco... |
57 58 59 60 |
static void free_pstore_private(struct pstore_private *private) { if (!private) return; |
83f70f076 pstore: Do not du... |
61 62 63 64 |
if (private->record) { kfree(private->record->buf); kfree(private->record); } |
1dfff7dd6 pstore: Pass reco... |
65 66 |
kfree(private); } |
060287b8c 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 pstore: Do not du... |
75 |
data->off = ps->total_size % REC_SIZE; |
060287b8c pstore: Add persi... |
76 |
data->off += *pos * REC_SIZE; |
83f70f076 pstore: Do not du... |
77 |
if (data->off + REC_SIZE > ps->total_size) { |
060287b8c 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 pstore: Do not du... |
97 |
if (data->off + REC_SIZE > ps->total_size) |
060287b8c 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 pstore: Do not du... |
108 109 110 |
struct pstore_ftrace_record *rec; rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off); |
060287b8c pstore: Add persi... |
111 |
|
fbccdeb8d 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 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 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 pstore: Add persi... |
131 132 |
struct seq_file *sf = file->private_data; struct pstore_private *ps = sf->private; |
fbe0aa1f3 Some fixes for ps... |
133 |
|
83f70f076 pstore: Do not du... |
134 |
if (ps->record->type == PSTORE_TYPE_FTRACE) |
060287b8c pstore: Add persi... |
135 |
return seq_read(file, userbuf, count, ppos); |
83f70f076 pstore: Do not du... |
136 137 |
return simple_read_from_buffer(userbuf, count, ppos, ps->record->buf, ps->total_size); |
fbe0aa1f3 Some fixes for ps... |
138 |
} |
060287b8c 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 pstore: Do not du... |
145 |
if (ps->record->type == PSTORE_TYPE_FTRACE) |
060287b8c 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 lseek: the "whenc... |
157 |
static loff_t pstore_file_llseek(struct file *file, loff_t off, int whence) |
060287b8c pstore: Add persi... |
158 159 160 161 |
{ struct seq_file *sf = file->private_data; if (sf->op) |
965c8e59c lseek: the "whenc... |
162 163 |
return seq_lseek(file, off, whence); return default_llseek(file, off, whence); |
060287b8c pstore: Add persi... |
164 |
} |
fbe0aa1f3 Some fixes for ps... |
165 |
static const struct file_operations pstore_file_operations = { |
060287b8c pstore: Add persi... |
166 167 168 169 |
.open = pstore_file_open, .read = pstore_file_read, .llseek = pstore_file_llseek, .release = seq_release, |
fbe0aa1f3 Some fixes for ps... |
170 |
}; |
ca01d6dd2 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 VFS: normal files... |
178 |
struct pstore_private *p = d_inode(dentry)->i_private; |
83f70f076 pstore: Do not du... |
179 |
struct pstore_record *record = p->record; |
ca01d6dd2 pstore: new files... |
180 |
|
a61072aae pstore: Replace a... |
181 |
if (!record->psi->erase) |
bf2883339 pstore: Fail to u... |
182 |
return -EPERM; |
a61072aae pstore: Replace a... |
183 184 185 186 |
mutex_lock(&record->psi->read_mutex); record->psi->erase(record); mutex_unlock(&record->psi->read_mutex); |
ca01d6dd2 pstore: new files... |
187 188 189 |
return simple_unlink(dir, dentry); } |
a872d5101 pstore: fix leaki... |
190 191 |
static void pstore_evict_inode(struct inode *inode) { |
6dda92669 pstore: defer ins... |
192 193 |
struct pstore_private *p = inode->i_private; unsigned long flags; |
dbd5768f8 vfs: Rename end_w... |
194 |
clear_inode(inode); |
6dda92669 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 pstore: Pass reco... |
199 |
free_pstore_private(p); |
6dda92669 pstore: defer ins... |
200 |
} |
a872d5101 pstore: fix leaki... |
201 |
} |
ca01d6dd2 pstore: new files... |
202 203 204 205 |
static const struct inode_operations pstore_dir_inode_operations = { .lookup = simple_lookup, .unlink = pstore_unlink, }; |
22a71c305 pstore: trim psto... |
206 |
static struct inode *pstore_get_inode(struct super_block *sb) |
fbe0aa1f3 Some fixes for ps... |
207 208 |
{ struct inode *inode = new_inode(sb); |
fbe0aa1f3 Some fixes for ps... |
209 210 |
if (inode) { inode->i_ino = get_next_ino(); |
078cd8279 fs: Replace CURRE... |
211 |
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); |
fbe0aa1f3 Some fixes for ps... |
212 213 214 |
} return inode; } |
366f7e7a7 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 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 pstore: use mount... |
257 258 |
static int pstore_remount(struct super_block *sb, int *flags, char *data) { |
02b9984d6 fs: push sync_fil... |
259 |
sync_filesystem(sb); |
366f7e7a7 pstore: use mount... |
260 261 262 263 |
parse_options(data); return 0; } |
ca01d6dd2 pstore: new files... |
264 265 266 |
static const struct super_operations pstore_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, |
a872d5101 pstore: fix leaki... |
267 |
.evict_inode = pstore_evict_inode, |
366f7e7a7 pstore: use mount... |
268 |
.remount_fs = pstore_remount, |
349d74389 pstore: Implement... |
269 |
.show_options = pstore_show_options, |
ca01d6dd2 pstore: new files... |
270 271 272 |
}; static struct super_block *pstore_sb; |
ca01d6dd2 pstore: new files... |
273 |
|
7e26e9ff0 pstore: Fix retur... |
274 |
bool pstore_is_mounted(void) |
ca01d6dd2 pstore: new files... |
275 |
{ |
fbe0aa1f3 Some fixes for ps... |
276 |
return pstore_sb != NULL; |
ca01d6dd2 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 pstore: Solve loc... |
284 |
int pstore_mkfile(struct dentry *root, struct pstore_record *record) |
ca01d6dd2 pstore: new files... |
285 |
{ |
ca01d6dd2 pstore: new files... |
286 287 |
struct dentry *dentry; struct inode *inode; |
6dda92669 pstore: defer ins... |
288 |
int rc = 0; |
ca01d6dd2 pstore: new files... |
289 |
char name[PSTORE_NAMELEN]; |
6dda92669 pstore: defer ins... |
290 291 |
struct pstore_private *private, *pos; unsigned long flags; |
1edd1aa39 pstore: Switch ps... |
292 |
size_t size = record->size + record->ecc_notice_size; |
6dda92669 pstore: defer ins... |
293 |
|
3a7d2fd16 pstore: Solve loc... |
294 |
WARN_ON(!inode_is_locked(d_inode(root))); |
6dda92669 pstore: defer ins... |
295 296 |
spin_lock_irqsave(&allpstore_lock, flags); list_for_each_entry(pos, &allpstore, list) { |
83f70f076 pstore: Do not du... |
297 298 299 |
if (pos->record->type == record->type && pos->record->id == record->id && pos->record->psi == record->psi) { |
6dda92669 pstore: defer ins... |
300 301 302 303 304 305 306 |
rc = -EEXIST; break; } } spin_unlock_irqrestore(&allpstore_lock, flags); if (rc) return rc; |
ca01d6dd2 pstore: new files... |
307 308 |
rc = -ENOMEM; |
3a7d2fd16 pstore: Solve loc... |
309 |
inode = pstore_get_inode(root->d_sb); |
ca01d6dd2 pstore: new files... |
310 311 |
if (!inode) goto fail; |
22a71c305 pstore: trim psto... |
312 313 |
inode->i_mode = S_IFREG | 0444; inode->i_fop = &pstore_file_operations; |
1dfff7dd6 pstore: Pass reco... |
314 |
private = kzalloc(sizeof(*private), GFP_KERNEL); |
ca01d6dd2 pstore: new files... |
315 316 |
if (!private) goto fail_alloc; |
83f70f076 pstore: Do not du... |
317 |
private->record = record; |
ca01d6dd2 pstore: new files... |
318 |
|
1edd1aa39 pstore: Switch ps... |
319 |
switch (record->type) { |
ca01d6dd2 pstore: new files... |
320 |
case PSTORE_TYPE_DMESG: |
d3762358a pstore: Fix forma... |
321 |
scnprintf(name, sizeof(name), "dmesg-%s-%llu%s", |
1edd1aa39 pstore: Switch ps... |
322 323 |
record->psi->name, record->id, record->compressed ? ".enc.z" : ""); |
ca01d6dd2 pstore: new files... |
324 |
break; |
f29e5956a pstore: Add conso... |
325 |
case PSTORE_TYPE_CONSOLE: |
d3762358a pstore: Fix forma... |
326 |
scnprintf(name, sizeof(name), "console-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
327 |
record->psi->name, record->id); |
f29e5956a pstore: Add conso... |
328 |
break; |
060287b8c pstore: Add persi... |
329 |
case PSTORE_TYPE_FTRACE: |
d3762358a pstore: Fix forma... |
330 |
scnprintf(name, sizeof(name), "ftrace-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
331 |
record->psi->name, record->id); |
060287b8c pstore: Add persi... |
332 |
break; |
ca01d6dd2 pstore: new files... |
333 |
case PSTORE_TYPE_MCE: |
d3762358a pstore: Fix forma... |
334 |
scnprintf(name, sizeof(name), "mce-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
335 |
record->psi->name, record->id); |
ca01d6dd2 pstore: new files... |
336 |
break; |
69020eea9 powerpc/pseries: ... |
337 |
case PSTORE_TYPE_PPC_RTAS: |
d3762358a pstore: Fix forma... |
338 |
scnprintf(name, sizeof(name), "rtas-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
339 |
record->psi->name, record->id); |
69020eea9 powerpc/pseries: ... |
340 |
break; |
f33f748c9 powerpc/pseries: ... |
341 |
case PSTORE_TYPE_PPC_OF: |
d3762358a pstore: Fix forma... |
342 |
scnprintf(name, sizeof(name), "powerpc-ofw-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
343 |
record->psi->name, record->id); |
f33f748c9 powerpc/pseries: ... |
344 |
break; |
a5e4797b0 powerpc/pseries: ... |
345 |
case PSTORE_TYPE_PPC_COMMON: |
d3762358a pstore: Fix forma... |
346 |
scnprintf(name, sizeof(name), "powerpc-common-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
347 |
record->psi->name, record->id); |
a5e4797b0 powerpc/pseries: ... |
348 |
break; |
9d5438f46 pstore: Add pmsg ... |
349 |
case PSTORE_TYPE_PMSG: |
d3762358a pstore: Fix forma... |
350 |
scnprintf(name, sizeof(name), "pmsg-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
351 |
record->psi->name, record->id); |
9d5438f46 pstore: Add pmsg ... |
352 |
break; |
ae011d2e4 pstore: Add pstor... |
353 |
case PSTORE_TYPE_PPC_OPAL: |
d3762358a pstore: Fix forma... |
354 |
scnprintf(name, sizeof(name), "powerpc-opal-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
355 |
record->psi->name, record->id); |
ae011d2e4 pstore: Add pstor... |
356 |
break; |
ca01d6dd2 pstore: new files... |
357 |
case PSTORE_TYPE_UNKNOWN: |
d3762358a pstore: Fix forma... |
358 |
scnprintf(name, sizeof(name), "unknown-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
359 |
record->psi->name, record->id); |
ca01d6dd2 pstore: new files... |
360 361 |
break; default: |
d3762358a pstore: Fix forma... |
362 |
scnprintf(name, sizeof(name), "type%d-%s-%llu", |
1edd1aa39 pstore: Switch ps... |
363 |
record->type, record->psi->name, record->id); |
ca01d6dd2 pstore: new files... |
364 365 |
break; } |
ca01d6dd2 pstore: new files... |
366 |
dentry = d_alloc_name(root, name); |
c39524e67 pstore: d_alloc_n... |
367 |
if (!dentry) |
3a7d2fd16 pstore: Solve loc... |
368 |
goto fail_private; |
ca01d6dd2 pstore: new files... |
369 |
|
83f70f076 pstore: Do not du... |
370 |
inode->i_size = private->total_size = size; |
ca01d6dd2 pstore: new files... |
371 372 |
inode->i_private = private; |
1edd1aa39 pstore: Switch ps... |
373 374 |
if (record->time.tv_sec) inode->i_mtime = inode->i_ctime = record->time; |
ca01d6dd2 pstore: new files... |
375 |
|
fbe0aa1f3 Some fixes for ps... |
376 |
d_add(dentry, inode); |
ca01d6dd2 pstore: new files... |
377 |
|
6dda92669 pstore: defer ins... |
378 379 380 |
spin_lock_irqsave(&allpstore_lock, flags); list_add(&private->list, &allpstore); spin_unlock_irqrestore(&allpstore_lock, flags); |
fbe0aa1f3 Some fixes for ps... |
381 |
return 0; |
ca01d6dd2 pstore: new files... |
382 |
|
3a7d2fd16 pstore: Solve loc... |
383 |
fail_private: |
1dfff7dd6 pstore: Pass reco... |
384 |
free_pstore_private(private); |
ca01d6dd2 pstore: new files... |
385 386 387 388 389 390 |
fail_alloc: iput(inode); fail: return rc; } |
3a7d2fd16 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 pstore/inode: Mak... |
411 |
static int pstore_fill_super(struct super_block *sb, void *data, int silent) |
ca01d6dd2 pstore: new files... |
412 |
{ |
318ceed08 tidy up after d_m... |
413 |
struct inode *inode; |
ca01d6dd2 pstore: new files... |
414 |
|
ca01d6dd2 pstore: new files... |
415 416 417 |
pstore_sb = sb; sb->s_maxbytes = MAX_LFS_FILESIZE; |
09cbfeaf1 mm, fs: get rid o... |
418 419 |
sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; |
ca01d6dd2 pstore: new files... |
420 421 422 |
sb->s_magic = PSTOREFS_MAGIC; sb->s_op = &pstore_ops; sb->s_time_gran = 1; |
366f7e7a7 pstore: use mount... |
423 |
parse_options(data); |
22a71c305 pstore: trim psto... |
424 |
inode = pstore_get_inode(sb); |
318ceed08 tidy up after d_m... |
425 |
if (inode) { |
d7caa3368 pstore: Make defa... |
426 |
inode->i_mode = S_IFDIR | 0750; |
318ceed08 tidy up after d_m... |
427 |
inode->i_op = &pstore_dir_inode_operations; |
22a71c305 pstore: trim psto... |
428 429 |
inode->i_fop = &simple_dir_operations; inc_nlink(inode); |
ca01d6dd2 pstore: new files... |
430 |
} |
318ceed08 tidy up after d_m... |
431 432 433 |
sb->s_root = d_make_root(inode); if (!sb->s_root) return -ENOMEM; |
ca01d6dd2 pstore: new files... |
434 |
|
6dda92669 pstore: defer ins... |
435 |
pstore_get_records(0); |
ca01d6dd2 pstore: new files... |
436 437 |
return 0; |
ca01d6dd2 pstore: new files... |
438 |
} |
fbe0aa1f3 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 pstore: new files... |
441 |
{ |
fbe0aa1f3 Some fixes for ps... |
442 |
return mount_single(fs_type, flags, data, pstore_fill_super); |
ca01d6dd2 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 pstore: new files... |
449 450 451 |
} static struct file_system_type pstore_fs_type = { |
ee1d26742 pstore: add pstor... |
452 |
.owner = THIS_MODULE, |
ca01d6dd2 pstore: new files... |
453 |
.name = "pstore", |
fbe0aa1f3 Some fixes for ps... |
454 |
.mount = pstore_mount, |
ca01d6dd2 pstore: new files... |
455 456 457 458 459 |
.kill_sb = pstore_kill_sb, }; static int __init init_pstore_fs(void) { |
f9bb48825 sysfs: Create mou... |
460 |
int err; |
fb0af3f2b pstore: Create a ... |
461 462 |
/* Create a convenient mount point for people to access pstore */ |
f9bb48825 sysfs: Create mou... |
463 464 |
err = sysfs_create_mount_point(fs_kobj, "pstore"); if (err) |
fb0af3f2b pstore: Create a ... |
465 |
goto out; |
fb0af3f2b pstore: Create a ... |
466 467 468 |
err = register_filesystem(&pstore_fs_type); if (err < 0) |
f9bb48825 sysfs: Create mou... |
469 |
sysfs_remove_mount_point(fs_kobj, "pstore"); |
fb0af3f2b pstore: Create a ... |
470 471 472 |
out: return err; |
ca01d6dd2 pstore: new files... |
473 474 |
} module_init(init_pstore_fs) |
ee1d26742 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 pstore: new files... |
481 482 |
MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>"); MODULE_LICENSE("GPL"); |