mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									1873041152
								
							
						
					
					
						commit
						ee1d267423
					
				
					 10 changed files with 88 additions and 34 deletions
				
			
		| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
config PSTORE
 | 
					config PSTORE
 | 
				
			||||||
	bool "Persistent store support"
 | 
						tristate "Persistent store support"
 | 
				
			||||||
	default n
 | 
						default n
 | 
				
			||||||
	select ZLIB_DEFLATE
 | 
						select ZLIB_DEFLATE
 | 
				
			||||||
	select ZLIB_INFLATE
 | 
						select ZLIB_INFLATE
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,12 +2,12 @@
 | 
				
			||||||
# Makefile for the linux pstorefs routines.
 | 
					# Makefile for the linux pstorefs routines.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-y += pstore.o
 | 
					obj-$(CONFIG_PSTORE) += pstore.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pstore-objs += inode.o platform.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
 | 
					ramoops-objs += ram.o ram_core.o
 | 
				
			||||||
obj-$(CONFIG_PSTORE_RAM)	+= ramoops.o
 | 
					obj-$(CONFIG_PSTORE_RAM)	+= ramoops.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,22 +104,23 @@ static const struct file_operations pstore_knob_fops = {
 | 
				
			||||||
	.write	= pstore_ftrace_knob_write,
 | 
						.write	= pstore_ftrace_knob_write,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct dentry *pstore_ftrace_dir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pstore_register_ftrace(void)
 | 
					void pstore_register_ftrace(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dentry *dir;
 | 
					 | 
				
			||||||
	struct dentry *file;
 | 
						struct dentry *file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!psinfo->write_buf)
 | 
						if (!psinfo->write_buf)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dir = debugfs_create_dir("pstore", NULL);
 | 
						pstore_ftrace_dir = debugfs_create_dir("pstore", NULL);
 | 
				
			||||||
	if (!dir) {
 | 
						if (!pstore_ftrace_dir) {
 | 
				
			||||||
		pr_err("%s: unable to create pstore directory\n", __func__);
 | 
							pr_err("%s: unable to create pstore directory\n", __func__);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file = debugfs_create_file("record_ftrace", 0600, dir, NULL,
 | 
						file = debugfs_create_file("record_ftrace", 0600, pstore_ftrace_dir,
 | 
				
			||||||
				   &pstore_knob_fops);
 | 
									   NULL, &pstore_knob_fops);
 | 
				
			||||||
	if (!file) {
 | 
						if (!file) {
 | 
				
			||||||
		pr_err("%s: unable to create record_ftrace file\n", __func__);
 | 
							pr_err("%s: unable to create record_ftrace file\n", __func__);
 | 
				
			||||||
		goto err_file;
 | 
							goto err_file;
 | 
				
			||||||
| 
						 | 
					@ -127,5 +128,17 @@ void pstore_register_ftrace(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
err_file:
 | 
					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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 = {
 | 
					static const struct file_operations pstore_file_operations = {
 | 
				
			||||||
 | 
						.owner		= THIS_MODULE,
 | 
				
			||||||
	.open		= pstore_file_open,
 | 
						.open		= pstore_file_open,
 | 
				
			||||||
	.read		= pstore_file_read,
 | 
						.read		= pstore_file_read,
 | 
				
			||||||
	.llseek		= pstore_file_llseek,
 | 
						.llseek		= pstore_file_llseek,
 | 
				
			||||||
| 
						 | 
					@ -456,6 +457,7 @@ static void pstore_kill_sb(struct super_block *sb)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct file_system_type pstore_fs_type = {
 | 
					static struct file_system_type pstore_fs_type = {
 | 
				
			||||||
 | 
						.owner          = THIS_MODULE,
 | 
				
			||||||
	.name		= "pstore",
 | 
						.name		= "pstore",
 | 
				
			||||||
	.mount		= pstore_mount,
 | 
						.mount		= pstore_mount,
 | 
				
			||||||
	.kill_sb	= pstore_kill_sb,
 | 
						.kill_sb	= pstore_kill_sb,
 | 
				
			||||||
| 
						 | 
					@ -479,5 +481,12 @@ static int __init init_pstore_fs(void)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
module_init(init_pstore_fs)
 | 
					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_AUTHOR("Tony Luck <tony.luck@intel.com>");
 | 
				
			||||||
MODULE_LICENSE("GPL");
 | 
					MODULE_LICENSE("GPL");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,14 +41,18 @@ pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_PSTORE_FTRACE
 | 
					#ifdef CONFIG_PSTORE_FTRACE
 | 
				
			||||||
extern void pstore_register_ftrace(void);
 | 
					extern void pstore_register_ftrace(void);
 | 
				
			||||||
 | 
					extern void pstore_unregister_ftrace(void);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static inline void pstore_register_ftrace(void) {}
 | 
					static inline void pstore_register_ftrace(void) {}
 | 
				
			||||||
 | 
					static inline void pstore_unregister_ftrace(void) {}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_PSTORE_PMSG
 | 
					#ifdef CONFIG_PSTORE_PMSG
 | 
				
			||||||
extern void pstore_register_pmsg(void);
 | 
					extern void pstore_register_pmsg(void);
 | 
				
			||||||
 | 
					extern void pstore_unregister_pmsg(void);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static inline void pstore_register_pmsg(void) {}
 | 
					static inline void pstore_register_pmsg(void) {}
 | 
				
			||||||
 | 
					static inline void pstore_unregister_pmsg(void) {}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct pstore_info *psinfo;
 | 
					extern struct pstore_info *psinfo;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					 * Called when compression fails, since the printk buffer
 | 
				
			||||||
 * would be fetched for compression calling it again when
 | 
					 * would be fetched for compression calling it again when
 | 
				
			||||||
| 
						 | 
					@ -358,6 +366,11 @@ static void pstore_register_kmsg(void)
 | 
				
			||||||
	kmsg_dump_register(&pstore_dumper);
 | 
						kmsg_dump_register(&pstore_dumper);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pstore_unregister_kmsg(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						kmsg_dump_unregister(&pstore_dumper);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_PSTORE_CONSOLE
 | 
					#ifdef CONFIG_PSTORE_CONSOLE
 | 
				
			||||||
static void pstore_console_write(struct console *con, const char *s, unsigned c)
 | 
					static void pstore_console_write(struct console *con, const char *s, unsigned c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -395,8 +408,14 @@ static void pstore_register_console(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	register_console(&pstore_console);
 | 
						register_console(&pstore_console);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pstore_unregister_console(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unregister_console(&pstore_console);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static void pstore_register_console(void) {}
 | 
					static void pstore_register_console(void) {}
 | 
				
			||||||
 | 
					static void pstore_unregister_console(void) {}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int pstore_write_compat(enum pstore_type_id type,
 | 
					static int pstore_write_compat(enum pstore_type_id type,
 | 
				
			||||||
| 
						 | 
					@ -467,12 +486,28 @@ int pstore_register(struct pstore_info *psi)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	backend = psi->name;
 | 
						backend = psi->name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						module_put(owner);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr_info("Registered %s as persistent store backend\n", psi->name);
 | 
						pr_info("Registered %s as persistent store backend\n", psi->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(pstore_register);
 | 
					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
 | 
					 * Read all the records from the persistent store. Create
 | 
				
			||||||
 * files in our filesystem.  Don't warn about -EEXIST errors
 | 
					 * files in our filesystem.  Don't warn about -EEXIST errors
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,3 +114,10 @@ void pstore_register_pmsg(void)
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pstore_unregister_pmsg(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						device_destroy(pmsg_class, MKDEV(pmsg_major, 0));
 | 
				
			||||||
 | 
						class_destroy(pmsg_class);
 | 
				
			||||||
 | 
						unregister_chrdev(pmsg_major, PMSG_NAME);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -578,30 +578,27 @@ static int ramoops_probe(struct platform_device *pdev)
 | 
				
			||||||
	return err;
 | 
						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;
 | 
						struct ramoops_context *cxt = &oops_cxt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	iounmap(cxt->virt_addr);
 | 
						pstore_unregister(&cxt->pstore);
 | 
				
			||||||
	release_mem_region(cxt->phys_addr, cxt->size);
 | 
					 | 
				
			||||||
	cxt->max_dump_cnt = 0;
 | 
						cxt->max_dump_cnt = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* TODO(kees): When pstore supports unregistering, call it here. */
 | 
					 | 
				
			||||||
	kfree(cxt->pstore.buf);
 | 
						kfree(cxt->pstore.buf);
 | 
				
			||||||
	cxt->pstore.bufsize = 0;
 | 
						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;
 | 
						return 0;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	return -EBUSY;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct platform_driver ramoops_driver = {
 | 
					static struct platform_driver ramoops_driver = {
 | 
				
			||||||
	.probe		= ramoops_probe,
 | 
						.probe		= ramoops_probe,
 | 
				
			||||||
	.remove		= __exit_p(ramoops_remove),
 | 
						.remove		= ramoops_remove,
 | 
				
			||||||
	.driver		= {
 | 
						.driver		= {
 | 
				
			||||||
		.name	= "ramoops",
 | 
							.name	= "ramoops",
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,20 +75,8 @@ struct pstore_info {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define	PSTORE_FLAGS_FRAGILE	1
 | 
					#define	PSTORE_FLAGS_FRAGILE	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_PSTORE
 | 
					 | 
				
			||||||
extern int pstore_register(struct pstore_info *);
 | 
					extern int pstore_register(struct pstore_info *);
 | 
				
			||||||
 | 
					extern void pstore_unregister(struct pstore_info *);
 | 
				
			||||||
extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
 | 
					extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
static inline int
 | 
					 | 
				
			||||||
pstore_register(struct pstore_info *psi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return -ENODEV;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static inline bool
 | 
					 | 
				
			||||||
pstore_cannot_block_path(enum kmsg_dump_reason reason)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /*_LINUX_PSTORE_H*/
 | 
					#endif /*_LINUX_PSTORE_H*/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -517,6 +517,7 @@ int check_syslog_permissions(int type, int source)
 | 
				
			||||||
ok:
 | 
					ok:
 | 
				
			||||||
	return security_syslog(type);
 | 
						return security_syslog(type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(check_syslog_permissions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void append_char(char **pp, char *e, char c)
 | 
					static void append_char(char **pp, char *e, char c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue