diff options
author | Geliang Tang <geliangtang@163.com> | 2015-10-20 03:39:03 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2015-10-22 11:59:18 -0400 |
commit | ee1d267423a1f8041e2b1a33fc23e4393c67677e (patch) | |
tree | b53cdedcdc8f6a7b36f0342814b91005ce4955ea | |
parent | 1873041152d2e324e25ddeec5541b90c22c2dc0f (diff) |
pstore: add pstore unregister
pstore doesn't support unregistering yet. It was marked as TODO.
This patch adds some code to fix it:
1) Add functions to unregister kmsg/console/ftrace/pmsg.
2) Add a function to free compression buffer.
3) Unmap the memory and free it.
4) Add a function to unregister pstore filesystem.
Signed-off-by: Geliang Tang <geliangtang@163.com>
Acked-by: Kees Cook <keescook@chromium.org>
[Removed __exit annotation from ramoops_remove(). Reported by Arnd Bergmann]
Signed-off-by: Tony Luck <tony.luck@intel.com>
-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 | 9 | ||||
-rw-r--r-- | fs/pstore/internal.h | 4 | ||||
-rw-r--r-- | fs/pstore/platform.c | 35 | ||||
-rw-r--r-- | fs/pstore/pmsg.c | 7 | ||||
-rw-r--r-- | fs/pstore/ram.c | 19 | ||||
-rw-r--r-- | include/linux/pstore.h | 14 | ||||
-rw-r--r-- | kernel/printk/printk.c | 1 |
10 files changed, 88 insertions, 34 deletions
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..3586491f26ba 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, |
@@ -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..96253c474ea5 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; |
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 1b1124942b4e..0aab920efff7 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 |
@@ -358,6 +366,11 @@ static void pstore_register_kmsg(void) | |||
358 | kmsg_dump_register(&pstore_dumper); | 366 | kmsg_dump_register(&pstore_dumper); |
359 | } | 367 | } |
360 | 368 | ||
369 | static void pstore_unregister_kmsg(void) | ||
370 | { | ||
371 | kmsg_dump_unregister(&pstore_dumper); | ||
372 | } | ||
373 | |||
361 | #ifdef CONFIG_PSTORE_CONSOLE | 374 | #ifdef CONFIG_PSTORE_CONSOLE |
362 | static void pstore_console_write(struct console *con, const char *s, unsigned c) | 375 | static void pstore_console_write(struct console *con, const char *s, unsigned c) |
363 | { | 376 | { |
@@ -395,8 +408,14 @@ static void pstore_register_console(void) | |||
395 | { | 408 | { |
396 | register_console(&pstore_console); | 409 | register_console(&pstore_console); |
397 | } | 410 | } |
411 | |||
412 | static void pstore_unregister_console(void) | ||
413 | { | ||
414 | unregister_console(&pstore_console); | ||
415 | } | ||
398 | #else | 416 | #else |
399 | static void pstore_register_console(void) {} | 417 | static void pstore_register_console(void) {} |
418 | static void pstore_unregister_console(void) {} | ||
400 | #endif | 419 | #endif |
401 | 420 | ||
402 | static int pstore_write_compat(enum pstore_type_id type, | 421 | static int pstore_write_compat(enum pstore_type_id type, |
@@ -467,12 +486,28 @@ int pstore_register(struct pstore_info *psi) | |||
467 | */ | 486 | */ |
468 | backend = psi->name; | 487 | backend = psi->name; |
469 | 488 | ||
489 | module_put(owner); | ||
490 | |||
470 | pr_info("Registered %s as persistent store backend\n", psi->name); | 491 | pr_info("Registered %s as persistent store backend\n", psi->name); |
471 | 492 | ||
472 | return 0; | 493 | return 0; |
473 | } | 494 | } |
474 | EXPORT_SYMBOL_GPL(pstore_register); | 495 | EXPORT_SYMBOL_GPL(pstore_register); |
475 | 496 | ||
497 | void pstore_unregister(struct pstore_info *psi) | ||
498 | { | ||
499 | pstore_unregister_pmsg(); | ||
500 | pstore_unregister_ftrace(); | ||
501 | pstore_unregister_console(); | ||
502 | pstore_unregister_kmsg(); | ||
503 | |||
504 | free_buf_for_compression(); | ||
505 | |||
506 | psinfo = NULL; | ||
507 | backend = NULL; | ||
508 | } | ||
509 | EXPORT_SYMBOL_GPL(pstore_unregister); | ||
510 | |||
476 | /* | 511 | /* |
477 | * Read all the records from the persistent store. Create | 512 | * Read all the records from the persistent store. Create |
478 | * files in our filesystem. Don't warn about -EEXIST errors | 513 | * files in our filesystem. Don't warn about -EEXIST errors |
diff --git a/fs/pstore/pmsg.c b/fs/pstore/pmsg.c index 5a2f05a16c1e..7de20cd3797f 100644 --- a/fs/pstore/pmsg.c +++ b/fs/pstore/pmsg.c | |||
@@ -114,3 +114,10 @@ err_class: | |||
114 | err: | 114 | err: |
115 | return; | 115 | return; |
116 | } | 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 | { |