diff options
-rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 2 | ||||
-rw-r--r-- | fs/pstore/Kconfig | 2 | ||||
-rw-r--r-- | fs/pstore/Makefile | 6 | ||||
-rw-r--r-- | fs/pstore/ftrace.c | 25 | ||||
-rw-r--r-- | fs/pstore/inode.c | 11 | ||||
-rw-r--r-- | fs/pstore/internal.h | 6 | ||||
-rw-r--r-- | fs/pstore/platform.c | 47 | ||||
-rw-r--r-- | fs/pstore/pmsg.c | 9 | ||||
-rw-r--r-- | fs/pstore/ram.c | 19 | ||||
-rw-r--r-- | include/linux/pstore.h | 14 | ||||
-rw-r--r-- | kernel/printk/printk.c | 1 |
11 files changed, 102 insertions, 40 deletions
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index c8d794c58479..eac76a79a880 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c | |||
@@ -103,7 +103,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) | |||
103 | 103 | ||
104 | /** | 104 | /** |
105 | * efi_pstore_scan_sysfs_enter | 105 | * efi_pstore_scan_sysfs_enter |
106 | * @entry: scanning entry | 106 | * @pos: scanning entry |
107 | * @next: next entry | 107 | * @next: next entry |
108 | * @head: list head | 108 | * @head: list head |
109 | */ | 109 | */ |
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 916b8e23d968..360ae43f590c 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | config PSTORE | 1 | config PSTORE |
2 | bool "Persistent store support" | 2 | tristate "Persistent store support" |
3 | default n | 3 | default n |
4 | select ZLIB_DEFLATE | 4 | select ZLIB_DEFLATE |
5 | select ZLIB_INFLATE | 5 | select ZLIB_INFLATE |
diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile index e647d8e81712..b8803cc07fce 100644 --- a/fs/pstore/Makefile +++ b/fs/pstore/Makefile | |||
@@ -2,12 +2,12 @@ | |||
2 | # Makefile for the linux pstorefs routines. | 2 | # Makefile for the linux pstorefs routines. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += pstore.o | 5 | obj-$(CONFIG_PSTORE) += pstore.o |
6 | 6 | ||
7 | pstore-objs += inode.o platform.o | 7 | pstore-objs += inode.o platform.o |
8 | obj-$(CONFIG_PSTORE_FTRACE) += ftrace.o | 8 | pstore-$(CONFIG_PSTORE_FTRACE) += ftrace.o |
9 | 9 | ||
10 | obj-$(CONFIG_PSTORE_PMSG) += pmsg.o | 10 | pstore-$(CONFIG_PSTORE_PMSG) += pmsg.o |
11 | 11 | ||
12 | ramoops-objs += ram.o ram_core.o | 12 | ramoops-objs += ram.o ram_core.o |
13 | obj-$(CONFIG_PSTORE_RAM) += ramoops.o | 13 | obj-$(CONFIG_PSTORE_RAM) += ramoops.o |
diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c index 76a4eeb92982..d4887705bb61 100644 --- a/fs/pstore/ftrace.c +++ b/fs/pstore/ftrace.c | |||
@@ -104,22 +104,23 @@ static const struct file_operations pstore_knob_fops = { | |||
104 | .write = pstore_ftrace_knob_write, | 104 | .write = pstore_ftrace_knob_write, |
105 | }; | 105 | }; |
106 | 106 | ||
107 | static struct dentry *pstore_ftrace_dir; | ||
108 | |||
107 | void pstore_register_ftrace(void) | 109 | void pstore_register_ftrace(void) |
108 | { | 110 | { |
109 | struct dentry *dir; | ||
110 | struct dentry *file; | 111 | struct dentry *file; |
111 | 112 | ||
112 | if (!psinfo->write_buf) | 113 | if (!psinfo->write_buf) |
113 | return; | 114 | return; |
114 | 115 | ||
115 | dir = debugfs_create_dir("pstore", NULL); | 116 | pstore_ftrace_dir = debugfs_create_dir("pstore", NULL); |
116 | if (!dir) { | 117 | if (!pstore_ftrace_dir) { |
117 | pr_err("%s: unable to create pstore directory\n", __func__); | 118 | pr_err("%s: unable to create pstore directory\n", __func__); |
118 | return; | 119 | return; |
119 | } | 120 | } |
120 | 121 | ||
121 | file = debugfs_create_file("record_ftrace", 0600, dir, NULL, | 122 | file = debugfs_create_file("record_ftrace", 0600, pstore_ftrace_dir, |
122 | &pstore_knob_fops); | 123 | NULL, &pstore_knob_fops); |
123 | if (!file) { | 124 | if (!file) { |
124 | pr_err("%s: unable to create record_ftrace file\n", __func__); | 125 | pr_err("%s: unable to create record_ftrace file\n", __func__); |
125 | goto err_file; | 126 | goto err_file; |
@@ -127,5 +128,17 @@ void pstore_register_ftrace(void) | |||
127 | 128 | ||
128 | return; | 129 | return; |
129 | err_file: | 130 | err_file: |
130 | debugfs_remove(dir); | 131 | debugfs_remove(pstore_ftrace_dir); |
132 | } | ||
133 | |||
134 | void pstore_unregister_ftrace(void) | ||
135 | { | ||
136 | mutex_lock(&pstore_ftrace_lock); | ||
137 | if (pstore_ftrace_enabled) { | ||
138 | unregister_ftrace_function(&pstore_ftrace_ops); | ||
139 | pstore_ftrace_enabled = 0; | ||
140 | } | ||
141 | mutex_unlock(&pstore_ftrace_lock); | ||
142 | |||
143 | debugfs_remove_recursive(pstore_ftrace_dir); | ||
131 | } | 144 | } |
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 3adcc4669fac..d8c439d813ce 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c | |||
@@ -178,6 +178,7 @@ static loff_t pstore_file_llseek(struct file *file, loff_t off, int whence) | |||
178 | } | 178 | } |
179 | 179 | ||
180 | static const struct file_operations pstore_file_operations = { | 180 | static const struct file_operations pstore_file_operations = { |
181 | .owner = THIS_MODULE, | ||
181 | .open = pstore_file_open, | 182 | .open = pstore_file_open, |
182 | .read = pstore_file_read, | 183 | .read = pstore_file_read, |
183 | .llseek = pstore_file_llseek, | 184 | .llseek = pstore_file_llseek, |
@@ -287,7 +288,7 @@ static const struct super_operations pstore_ops = { | |||
287 | 288 | ||
288 | static struct super_block *pstore_sb; | 289 | static struct super_block *pstore_sb; |
289 | 290 | ||
290 | int pstore_is_mounted(void) | 291 | bool pstore_is_mounted(void) |
291 | { | 292 | { |
292 | return pstore_sb != NULL; | 293 | return pstore_sb != NULL; |
293 | } | 294 | } |
@@ -456,6 +457,7 @@ static void pstore_kill_sb(struct super_block *sb) | |||
456 | } | 457 | } |
457 | 458 | ||
458 | static struct file_system_type pstore_fs_type = { | 459 | static struct file_system_type pstore_fs_type = { |
460 | .owner = THIS_MODULE, | ||
459 | .name = "pstore", | 461 | .name = "pstore", |
460 | .mount = pstore_mount, | 462 | .mount = pstore_mount, |
461 | .kill_sb = pstore_kill_sb, | 463 | .kill_sb = pstore_kill_sb, |
@@ -479,5 +481,12 @@ out: | |||
479 | } | 481 | } |
480 | module_init(init_pstore_fs) | 482 | module_init(init_pstore_fs) |
481 | 483 | ||
484 | static void __exit exit_pstore_fs(void) | ||
485 | { | ||
486 | unregister_filesystem(&pstore_fs_type); | ||
487 | sysfs_remove_mount_point(fs_kobj, "pstore"); | ||
488 | } | ||
489 | module_exit(exit_pstore_fs) | ||
490 | |||
482 | MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>"); | 491 | MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>"); |
483 | MODULE_LICENSE("GPL"); | 492 | MODULE_LICENSE("GPL"); |
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index c36ba2cd0b5d..e38a22b31282 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h | |||
@@ -41,14 +41,18 @@ pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) | |||
41 | 41 | ||
42 | #ifdef CONFIG_PSTORE_FTRACE | 42 | #ifdef CONFIG_PSTORE_FTRACE |
43 | extern void pstore_register_ftrace(void); | 43 | extern void pstore_register_ftrace(void); |
44 | extern void pstore_unregister_ftrace(void); | ||
44 | #else | 45 | #else |
45 | static inline void pstore_register_ftrace(void) {} | 46 | static inline void pstore_register_ftrace(void) {} |
47 | static inline void pstore_unregister_ftrace(void) {} | ||
46 | #endif | 48 | #endif |
47 | 49 | ||
48 | #ifdef CONFIG_PSTORE_PMSG | 50 | #ifdef CONFIG_PSTORE_PMSG |
49 | extern void pstore_register_pmsg(void); | 51 | extern void pstore_register_pmsg(void); |
52 | extern void pstore_unregister_pmsg(void); | ||
50 | #else | 53 | #else |
51 | static inline void pstore_register_pmsg(void) {} | 54 | static inline void pstore_register_pmsg(void) {} |
55 | static inline void pstore_unregister_pmsg(void) {} | ||
52 | #endif | 56 | #endif |
53 | 57 | ||
54 | extern struct pstore_info *psinfo; | 58 | extern struct pstore_info *psinfo; |
@@ -59,6 +63,6 @@ extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, | |||
59 | int count, char *data, bool compressed, | 63 | int count, char *data, bool compressed, |
60 | size_t size, struct timespec time, | 64 | size_t size, struct timespec time, |
61 | struct pstore_info *psi); | 65 | struct pstore_info *psi); |
62 | extern int pstore_is_mounted(void); | 66 | extern bool pstore_is_mounted(void); |
63 | 67 | ||
64 | #endif | 68 | #endif |
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 791743deedf1..588461bb2dd4 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c | |||
@@ -237,6 +237,14 @@ static void allocate_buf_for_compression(void) | |||
237 | 237 | ||
238 | } | 238 | } |
239 | 239 | ||
240 | static void free_buf_for_compression(void) | ||
241 | { | ||
242 | kfree(stream.workspace); | ||
243 | stream.workspace = NULL; | ||
244 | kfree(big_oops_buf); | ||
245 | big_oops_buf = NULL; | ||
246 | } | ||
247 | |||
240 | /* | 248 | /* |
241 | * Called when compression fails, since the printk buffer | 249 | * Called when compression fails, since the printk buffer |
242 | * would be fetched for compression calling it again when | 250 | * would be fetched for compression calling it again when |
@@ -353,6 +361,19 @@ static struct kmsg_dumper pstore_dumper = { | |||
353 | .dump = pstore_dump, | 361 | .dump = pstore_dump, |
354 | }; | 362 | }; |
355 | 363 | ||
364 | /* | ||
365 | * Register with kmsg_dump to save last part of console log on panic. | ||
366 | */ | ||
367 | static void pstore_register_kmsg(void) | ||
368 | { | ||
369 | kmsg_dump_register(&pstore_dumper); | ||
370 | } | ||
371 | |||
372 | static void pstore_unregister_kmsg(void) | ||
373 | { | ||
374 | kmsg_dump_unregister(&pstore_dumper); | ||
375 | } | ||
376 | |||
356 | #ifdef CONFIG_PSTORE_CONSOLE | 377 | #ifdef CONFIG_PSTORE_CONSOLE |
357 | static void pstore_console_write(struct console *con, const char *s, unsigned c) | 378 | static void pstore_console_write(struct console *con, const char *s, unsigned c) |
358 | { | 379 | { |
@@ -390,8 +411,14 @@ static void pstore_register_console(void) | |||
390 | { | 411 | { |
391 | register_console(&pstore_console); | 412 | register_console(&pstore_console); |
392 | } | 413 | } |
414 | |||
415 | static void pstore_unregister_console(void) | ||
416 | { | ||
417 | unregister_console(&pstore_console); | ||
418 | } | ||
393 | #else | 419 | #else |
394 | static void pstore_register_console(void) {} | 420 | static void pstore_register_console(void) {} |
421 | static void pstore_unregister_console(void) {} | ||
395 | #endif | 422 | #endif |
396 | 423 | ||
397 | static int pstore_write_compat(enum pstore_type_id type, | 424 | static int pstore_write_compat(enum pstore_type_id type, |
@@ -410,8 +437,6 @@ static int pstore_write_compat(enum pstore_type_id type, | |||
410 | * read function right away to populate the file system. If not | 437 | * read function right away to populate the file system. If not |
411 | * then the pstore mount code will call us later to fill out | 438 | * then the pstore mount code will call us later to fill out |
412 | * the file system. | 439 | * the file system. |
413 | * | ||
414 | * Register with kmsg_dump to save last part of console log on panic. | ||
415 | */ | 440 | */ |
416 | int pstore_register(struct pstore_info *psi) | 441 | int pstore_register(struct pstore_info *psi) |
417 | { | 442 | { |
@@ -442,7 +467,7 @@ int pstore_register(struct pstore_info *psi) | |||
442 | if (pstore_is_mounted()) | 467 | if (pstore_is_mounted()) |
443 | pstore_get_records(0); | 468 | pstore_get_records(0); |
444 | 469 | ||
445 | kmsg_dump_register(&pstore_dumper); | 470 | pstore_register_kmsg(); |
446 | 471 | ||
447 | if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { | 472 | if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { |
448 | pstore_register_console(); | 473 | pstore_register_console(); |
@@ -462,12 +487,28 @@ int pstore_register(struct pstore_info *psi) | |||
462 | */ | 487 | */ |
463 | backend = psi->name; | 488 | backend = psi->name; |
464 | 489 | ||
490 | module_put(owner); | ||
491 | |||
465 | pr_info("Registered %s as persistent store backend\n", psi->name); | 492 | pr_info("Registered %s as persistent store backend\n", psi->name); |
466 | 493 | ||
467 | return 0; | 494 | return 0; |
468 | } | 495 | } |
469 | EXPORT_SYMBOL_GPL(pstore_register); | 496 | EXPORT_SYMBOL_GPL(pstore_register); |
470 | 497 | ||
498 | void pstore_unregister(struct pstore_info *psi) | ||
499 | { | ||
500 | pstore_unregister_pmsg(); | ||
501 | pstore_unregister_ftrace(); | ||
502 | pstore_unregister_console(); | ||
503 | pstore_unregister_kmsg(); | ||
504 | |||
505 | free_buf_for_compression(); | ||
506 | |||
507 | psinfo = NULL; | ||
508 | backend = NULL; | ||
509 | } | ||
510 | EXPORT_SYMBOL_GPL(pstore_unregister); | ||
511 | |||
471 | /* | 512 | /* |
472 | * Read all the records from the persistent store. Create | 513 | * Read all the records from the persistent store. Create |
473 | * files in our filesystem. Don't warn about -EEXIST errors | 514 | * files in our filesystem. Don't warn about -EEXIST errors |
diff --git a/fs/pstore/pmsg.c b/fs/pstore/pmsg.c index feb5dd2948b4..7de20cd3797f 100644 --- a/fs/pstore/pmsg.c +++ b/fs/pstore/pmsg.c | |||
@@ -37,6 +37,8 @@ static ssize_t write_pmsg(struct file *file, const char __user *buf, | |||
37 | if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE) | 37 | if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE) |
38 | buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE; | 38 | buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE; |
39 | buffer = vmalloc(buffer_size); | 39 | buffer = vmalloc(buffer_size); |
40 | if (!buffer) | ||
41 | return -ENOMEM; | ||
40 | 42 | ||
41 | mutex_lock(&pmsg_lock); | 43 | mutex_lock(&pmsg_lock); |
42 | for (i = 0; i < count; ) { | 44 | for (i = 0; i < count; ) { |
@@ -112,3 +114,10 @@ err_class: | |||
112 | err: | 114 | err: |
113 | return; | 115 | return; |
114 | } | 116 | } |
117 | |||
118 | void pstore_unregister_pmsg(void) | ||
119 | { | ||
120 | device_destroy(pmsg_class, MKDEV(pmsg_major, 0)); | ||
121 | class_destroy(pmsg_class); | ||
122 | unregister_chrdev(pmsg_major, PMSG_NAME); | ||
123 | } | ||
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 6c26c4daaec9..319c3a60cfa5 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c | |||
@@ -578,30 +578,27 @@ fail_out: | |||
578 | return err; | 578 | return err; |
579 | } | 579 | } |
580 | 580 | ||
581 | static int __exit ramoops_remove(struct platform_device *pdev) | 581 | static int ramoops_remove(struct platform_device *pdev) |
582 | { | 582 | { |
583 | #if 0 | ||
584 | /* TODO(kees): We cannot unload ramoops since pstore doesn't support | ||
585 | * unregistering yet. | ||
586 | */ | ||
587 | struct ramoops_context *cxt = &oops_cxt; | 583 | struct ramoops_context *cxt = &oops_cxt; |
588 | 584 | ||
589 | iounmap(cxt->virt_addr); | 585 | pstore_unregister(&cxt->pstore); |
590 | release_mem_region(cxt->phys_addr, cxt->size); | ||
591 | cxt->max_dump_cnt = 0; | 586 | cxt->max_dump_cnt = 0; |
592 | 587 | ||
593 | /* TODO(kees): When pstore supports unregistering, call it here. */ | ||
594 | kfree(cxt->pstore.buf); | 588 | kfree(cxt->pstore.buf); |
595 | cxt->pstore.bufsize = 0; | 589 | cxt->pstore.bufsize = 0; |
596 | 590 | ||
591 | persistent_ram_free(cxt->mprz); | ||
592 | persistent_ram_free(cxt->fprz); | ||
593 | persistent_ram_free(cxt->cprz); | ||
594 | ramoops_free_przs(cxt); | ||
595 | |||
597 | return 0; | 596 | return 0; |
598 | #endif | ||
599 | return -EBUSY; | ||
600 | } | 597 | } |
601 | 598 | ||
602 | static struct platform_driver ramoops_driver = { | 599 | static struct platform_driver ramoops_driver = { |
603 | .probe = ramoops_probe, | 600 | .probe = ramoops_probe, |
604 | .remove = __exit_p(ramoops_remove), | 601 | .remove = ramoops_remove, |
605 | .driver = { | 602 | .driver = { |
606 | .name = "ramoops", | 603 | .name = "ramoops", |
607 | }, | 604 | }, |
diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 8e7a25b068b0..831479f8df8f 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h | |||
@@ -75,20 +75,8 @@ struct pstore_info { | |||
75 | 75 | ||
76 | #define PSTORE_FLAGS_FRAGILE 1 | 76 | #define PSTORE_FLAGS_FRAGILE 1 |
77 | 77 | ||
78 | #ifdef CONFIG_PSTORE | ||
79 | extern int pstore_register(struct pstore_info *); | 78 | extern int pstore_register(struct pstore_info *); |
79 | extern void pstore_unregister(struct pstore_info *); | ||
80 | extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); | 80 | extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); |
81 | #else | ||
82 | static inline int | ||
83 | pstore_register(struct pstore_info *psi) | ||
84 | { | ||
85 | return -ENODEV; | ||
86 | } | ||
87 | static inline bool | ||
88 | pstore_cannot_block_path(enum kmsg_dump_reason reason) | ||
89 | { | ||
90 | return false; | ||
91 | } | ||
92 | #endif | ||
93 | 81 | ||
94 | #endif /*_LINUX_PSTORE_H*/ | 82 | #endif /*_LINUX_PSTORE_H*/ |
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 8f0324ef72ab..b16f35487b67 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
@@ -517,6 +517,7 @@ int check_syslog_permissions(int type, int source) | |||
517 | ok: | 517 | ok: |
518 | return security_syslog(type); | 518 | return security_syslog(type); |
519 | } | 519 | } |
520 | EXPORT_SYMBOL_GPL(check_syslog_permissions); | ||
520 | 521 | ||
521 | static void append_char(char **pp, char *e, char c) | 522 | static void append_char(char **pp, char *e, char c) |
522 | { | 523 | { |