diff options
Diffstat (limited to 'fs/pstore')
-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 |
8 files changed, 99 insertions, 26 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 @@ config PSTORE - bool "Persistent store support" + tristate "Persistent store support" default n select ZLIB_DEFLATE 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 @@ # Makefile for the linux pstorefs routines. # -obj-y += pstore.o +obj-$(CONFIG_PSTORE) += pstore.o pstore-objs += inode.o platform.o -obj-$(CONFIG_PSTORE_FTRACE) += ftrace.o +pstore-$(CONFIG_PSTORE_FTRACE) += ftrace.o -obj-$(CONFIG_PSTORE_PMSG) += pmsg.o +pstore-$(CONFIG_PSTORE_PMSG) += pmsg.o ramoops-objs += ram.o ram_core.o 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 = { .write = pstore_ftrace_knob_write, }; +static struct dentry *pstore_ftrace_dir; + void pstore_register_ftrace(void) { - struct dentry *dir; struct dentry *file; if (!psinfo->write_buf) return; - dir = debugfs_create_dir("pstore", NULL); - if (!dir) { + pstore_ftrace_dir = debugfs_create_dir("pstore", NULL); + if (!pstore_ftrace_dir) { pr_err("%s: unable to create pstore directory\n", __func__); return; } - file = debugfs_create_file("record_ftrace", 0600, dir, NULL, - &pstore_knob_fops); + file = debugfs_create_file("record_ftrace", 0600, pstore_ftrace_dir, + NULL, &pstore_knob_fops); if (!file) { pr_err("%s: unable to create record_ftrace file\n", __func__); goto err_file; @@ -127,5 +128,17 @@ void pstore_register_ftrace(void) return; err_file: - debugfs_remove(dir); + debugfs_remove(pstore_ftrace_dir); +} + +void pstore_unregister_ftrace(void) +{ + mutex_lock(&pstore_ftrace_lock); + if (pstore_ftrace_enabled) { + unregister_ftrace_function(&pstore_ftrace_ops); + pstore_ftrace_enabled = 0; + } + mutex_unlock(&pstore_ftrace_lock); + + debugfs_remove_recursive(pstore_ftrace_dir); } 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) } static const struct file_operations pstore_file_operations = { + .owner = THIS_MODULE, .open = pstore_file_open, .read = pstore_file_read, .llseek = pstore_file_llseek, @@ -287,7 +288,7 @@ static const struct super_operations pstore_ops = { static struct super_block *pstore_sb; -int pstore_is_mounted(void) +bool pstore_is_mounted(void) { return pstore_sb != NULL; } @@ -456,6 +457,7 @@ static void pstore_kill_sb(struct super_block *sb) } static struct file_system_type pstore_fs_type = { + .owner = THIS_MODULE, .name = "pstore", .mount = pstore_mount, .kill_sb = pstore_kill_sb, @@ -479,5 +481,12 @@ out: } module_init(init_pstore_fs) +static void __exit exit_pstore_fs(void) +{ + unregister_filesystem(&pstore_fs_type); + sysfs_remove_mount_point(fs_kobj, "pstore"); +} +module_exit(exit_pstore_fs) + MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>"); 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) #ifdef CONFIG_PSTORE_FTRACE extern void pstore_register_ftrace(void); +extern void pstore_unregister_ftrace(void); #else static inline void pstore_register_ftrace(void) {} +static inline void pstore_unregister_ftrace(void) {} #endif #ifdef CONFIG_PSTORE_PMSG extern void pstore_register_pmsg(void); +extern void pstore_unregister_pmsg(void); #else static inline void pstore_register_pmsg(void) {} +static inline void pstore_unregister_pmsg(void) {} #endif extern struct pstore_info *psinfo; @@ -59,6 +63,6 @@ extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, int count, char *data, bool compressed, size_t size, struct timespec time, struct pstore_info *psi); -extern int pstore_is_mounted(void); +extern bool pstore_is_mounted(void); #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) } +static void free_buf_for_compression(void) +{ + kfree(stream.workspace); + stream.workspace = NULL; + kfree(big_oops_buf); + big_oops_buf = NULL; +} + /* * Called when compression fails, since the printk buffer * would be fetched for compression calling it again when @@ -353,6 +361,19 @@ static struct kmsg_dumper pstore_dumper = { .dump = pstore_dump, }; +/* + * Register with kmsg_dump to save last part of console log on panic. + */ +static void pstore_register_kmsg(void) +{ + kmsg_dump_register(&pstore_dumper); +} + +static void pstore_unregister_kmsg(void) +{ + kmsg_dump_unregister(&pstore_dumper); +} + #ifdef CONFIG_PSTORE_CONSOLE static void pstore_console_write(struct console *con, const char *s, unsigned c) { @@ -390,8 +411,14 @@ static void pstore_register_console(void) { register_console(&pstore_console); } + +static void pstore_unregister_console(void) +{ + unregister_console(&pstore_console); +} #else static void pstore_register_console(void) {} +static void pstore_unregister_console(void) {} #endif static int pstore_write_compat(enum pstore_type_id type, @@ -410,8 +437,6 @@ static int pstore_write_compat(enum pstore_type_id type, * read function right away to populate the file system. If not * then the pstore mount code will call us later to fill out * the file system. - * - * Register with kmsg_dump to save last part of console log on panic. */ int pstore_register(struct pstore_info *psi) { @@ -442,7 +467,7 @@ int pstore_register(struct pstore_info *psi) if (pstore_is_mounted()) pstore_get_records(0); - kmsg_dump_register(&pstore_dumper); + pstore_register_kmsg(); if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { pstore_register_console(); @@ -462,12 +487,28 @@ int pstore_register(struct pstore_info *psi) */ backend = psi->name; + module_put(owner); + pr_info("Registered %s as persistent store backend\n", psi->name); return 0; } EXPORT_SYMBOL_GPL(pstore_register); +void pstore_unregister(struct pstore_info *psi) +{ + pstore_unregister_pmsg(); + pstore_unregister_ftrace(); + pstore_unregister_console(); + pstore_unregister_kmsg(); + + free_buf_for_compression(); + + psinfo = NULL; + backend = NULL; +} +EXPORT_SYMBOL_GPL(pstore_unregister); + /* * Read all the records from the persistent store. Create * 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, if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE) buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE; buffer = vmalloc(buffer_size); + if (!buffer) + return -ENOMEM; mutex_lock(&pmsg_lock); for (i = 0; i < count; ) { @@ -112,3 +114,10 @@ err_class: err: return; } + +void pstore_unregister_pmsg(void) +{ + device_destroy(pmsg_class, MKDEV(pmsg_major, 0)); + class_destroy(pmsg_class); + unregister_chrdev(pmsg_major, PMSG_NAME); +} 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: return err; } -static int __exit ramoops_remove(struct platform_device *pdev) +static int ramoops_remove(struct platform_device *pdev) { -#if 0 - /* TODO(kees): We cannot unload ramoops since pstore doesn't support - * unregistering yet. - */ struct ramoops_context *cxt = &oops_cxt; - iounmap(cxt->virt_addr); - release_mem_region(cxt->phys_addr, cxt->size); + pstore_unregister(&cxt->pstore); cxt->max_dump_cnt = 0; - /* TODO(kees): When pstore supports unregistering, call it here. */ kfree(cxt->pstore.buf); cxt->pstore.bufsize = 0; + persistent_ram_free(cxt->mprz); + persistent_ram_free(cxt->fprz); + persistent_ram_free(cxt->cprz); + ramoops_free_przs(cxt); + return 0; -#endif - return -EBUSY; } static struct platform_driver ramoops_driver = { .probe = ramoops_probe, - .remove = __exit_p(ramoops_remove), + .remove = ramoops_remove, .driver = { .name = "ramoops", }, |