mirror of
				https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
				synced 2025-10-30 10:41:34 +10:00 
			
		
		
		
	If CONFIG_MODULES is n, we got this: kernel/printk/index.c:146:13: warning: ‘pi_remove_file’ defined but not used [-Wunused-function] Move it inside #ifdef block to fix this warning. Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: YueHaibing <yuehaibing@huawei.com> Signed-off-by: Petr Mladek <pmladek@suse.com> Link: https://lore.kernel.org/r/20210804130105.18732-1-yuehaibing@huawei.com
		
			
				
	
	
		
			196 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			196 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  * Userspace indexing of printk formats
 | |
|  */
 | |
| 
 | |
| #include <linux/debugfs.h>
 | |
| #include <linux/module.h>
 | |
| #include <linux/printk.h>
 | |
| #include <linux/slab.h>
 | |
| #include <linux/string_helpers.h>
 | |
| 
 | |
| #include "internal.h"
 | |
| 
 | |
| extern struct pi_entry *__start_printk_index[];
 | |
| extern struct pi_entry *__stop_printk_index[];
 | |
| 
 | |
| /* The base dir for module formats, typically debugfs/printk/index/ */
 | |
| static struct dentry *dfs_index;
 | |
| 
 | |
| static struct pi_entry *pi_get_entry(const struct module *mod, loff_t pos)
 | |
| {
 | |
| 	struct pi_entry **entries;
 | |
| 	unsigned int nr_entries;
 | |
| 
 | |
| #ifdef CONFIG_MODULES
 | |
| 	if (mod) {
 | |
| 		entries = mod->printk_index_start;
 | |
| 		nr_entries = mod->printk_index_size;
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	if (!mod) {
 | |
| 		/* vmlinux, comes from linker symbols */
 | |
| 		entries = __start_printk_index;
 | |
| 		nr_entries = __stop_printk_index - __start_printk_index;
 | |
| 	}
 | |
| 
 | |
| 	if (pos >= nr_entries)
 | |
| 		return NULL;
 | |
| 
 | |
| 	return entries[pos];
 | |
| }
 | |
| 
 | |
| static void *pi_next(struct seq_file *s, void *v, loff_t *pos)
 | |
| {
 | |
| 	const struct module *mod = s->file->f_inode->i_private;
 | |
| 	struct pi_entry *entry = pi_get_entry(mod, *pos);
 | |
| 
 | |
| 	(*pos)++;
 | |
| 
 | |
| 	return entry;
 | |
| }
 | |
| 
 | |
| static void *pi_start(struct seq_file *s, loff_t *pos)
 | |
| {
 | |
| 	/*
 | |
| 	 * Make show() print the header line. Do not update *pos because
 | |
| 	 * pi_next() still has to return the entry at index 0 later.
 | |
| 	 */
 | |
| 	if (*pos == 0)
 | |
| 		return SEQ_START_TOKEN;
 | |
| 
 | |
| 	return pi_next(s, NULL, pos);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * We need both ESCAPE_ANY and explicit characters from ESCAPE_SPECIAL in @only
 | |
|  * because otherwise ESCAPE_NAP will cause double quotes and backslashes to be
 | |
|  * ignored for quoting.
 | |
|  */
 | |
| #define seq_escape_printf_format(s, src) \
 | |
| 	seq_escape_str(s, src, ESCAPE_ANY | ESCAPE_NAP | ESCAPE_APPEND, "\"\\")
 | |
| 
 | |
| static int pi_show(struct seq_file *s, void *v)
 | |
| {
 | |
| 	const struct pi_entry *entry = v;
 | |
| 	int level = LOGLEVEL_DEFAULT;
 | |
| 	enum printk_info_flags flags = 0;
 | |
| 	u16 prefix_len = 0;
 | |
| 
 | |
| 	if (v == SEQ_START_TOKEN) {
 | |
| 		seq_puts(s, "# <level/flags> filename:line function \"format\"\n");
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	if (!entry->fmt)
 | |
| 		return 0;
 | |
| 
 | |
| 	if (entry->level)
 | |
| 		printk_parse_prefix(entry->level, &level, &flags);
 | |
| 	else
 | |
| 		prefix_len = printk_parse_prefix(entry->fmt, &level, &flags);
 | |
| 
 | |
| 
 | |
| 	if (flags & LOG_CONT) {
 | |
| 		/*
 | |
| 		 * LOGLEVEL_DEFAULT here means "use the same level as the
 | |
| 		 * message we're continuing from", not the default message
 | |
| 		 * loglevel, so don't display it as such.
 | |
| 		 */
 | |
| 		if (level == LOGLEVEL_DEFAULT)
 | |
| 			seq_puts(s, "<c>");
 | |
| 		else
 | |
| 			seq_printf(s, "<%d,c>", level);
 | |
| 	} else
 | |
| 		seq_printf(s, "<%d>", level);
 | |
| 
 | |
| 	seq_printf(s, " %s:%d %s \"", entry->file, entry->line, entry->func);
 | |
| 	if (entry->subsys_fmt_prefix)
 | |
| 		seq_escape_printf_format(s, entry->subsys_fmt_prefix);
 | |
| 	seq_escape_printf_format(s, entry->fmt + prefix_len);
 | |
| 	seq_puts(s, "\"\n");
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static void pi_stop(struct seq_file *p, void *v) { }
 | |
| 
 | |
| static const struct seq_operations dfs_index_sops = {
 | |
| 	.start = pi_start,
 | |
| 	.next  = pi_next,
 | |
| 	.show  = pi_show,
 | |
| 	.stop  = pi_stop,
 | |
| };
 | |
| 
 | |
| DEFINE_SEQ_ATTRIBUTE(dfs_index);
 | |
| 
 | |
| #ifdef CONFIG_MODULES
 | |
| static const char *pi_get_module_name(struct module *mod)
 | |
| {
 | |
| 	return mod ? mod->name : "vmlinux";
 | |
| }
 | |
| #else
 | |
| static const char *pi_get_module_name(struct module *mod)
 | |
| {
 | |
| 	return "vmlinux";
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static void pi_create_file(struct module *mod)
 | |
| {
 | |
| 	debugfs_create_file(pi_get_module_name(mod), 0444, dfs_index,
 | |
| 				       mod, &dfs_index_fops);
 | |
| }
 | |
| 
 | |
| #ifdef CONFIG_MODULES
 | |
| static void pi_remove_file(struct module *mod)
 | |
| {
 | |
| 	debugfs_remove(debugfs_lookup(pi_get_module_name(mod), dfs_index));
 | |
| }
 | |
| 
 | |
| static int pi_module_notify(struct notifier_block *nb, unsigned long op,
 | |
| 			    void *data)
 | |
| {
 | |
| 	struct module *mod = data;
 | |
| 
 | |
| 	switch (op) {
 | |
| 	case MODULE_STATE_COMING:
 | |
| 		pi_create_file(mod);
 | |
| 		break;
 | |
| 	case MODULE_STATE_GOING:
 | |
| 		pi_remove_file(mod);
 | |
| 		break;
 | |
| 	default: /* we don't care about other module states */
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	return NOTIFY_OK;
 | |
| }
 | |
| 
 | |
| static struct notifier_block module_printk_fmts_nb = {
 | |
| 	.notifier_call = pi_module_notify,
 | |
| };
 | |
| 
 | |
| static void __init pi_setup_module_notifier(void)
 | |
| {
 | |
| 	register_module_notifier(&module_printk_fmts_nb);
 | |
| }
 | |
| #else
 | |
| static inline void __init pi_setup_module_notifier(void) { }
 | |
| #endif
 | |
| 
 | |
| static int __init pi_init(void)
 | |
| {
 | |
| 	struct dentry *dfs_root = debugfs_create_dir("printk", NULL);
 | |
| 
 | |
| 	dfs_index = debugfs_create_dir("index", dfs_root);
 | |
| 	pi_setup_module_notifier();
 | |
| 	pi_create_file(NULL);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* debugfs comes up on core and must be initialised first */
 | |
| postcore_initcall(pi_init);
 |