Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

proc: bootconfig: Add /proc/bootconfig to show boot config list

Add /proc/bootconfig which shows the list of key-value pairs
in boot config. Since after boot, all boot configs and tree
are removed, this interface just keep a copy of key-value
pairs in text.

Link: http://lkml.kernel.org/r/157867225967.17873.12155805787236073787.stgit@devnote2

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

authored by

Masami Hiramatsu and committed by
Steven Rostedt (VMware)
c1a3c360 081c6536

+91
+1
MAINTAINERS
··· 15774 15774 M: Masami Hiramatsu <mhiramat@kernel.org> 15775 15775 S: Maintained 15776 15776 F: lib/bootconfig.c 15777 + F: fs/proc/bootconfig.c 15777 15778 F: include/linux/bootconfig.h 15778 15779 F: tools/bootconfig/* 15779 15780
+1
fs/proc/Makefile
··· 33 33 proc-$(CONFIG_PROC_VMCORE) += vmcore.o 34 34 proc-$(CONFIG_PRINTK) += kmsg.o 35 35 proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o 36 + proc-$(CONFIG_BOOT_CONFIG) += bootconfig.o
+89
fs/proc/bootconfig.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * /proc/bootconfig - Extra boot configuration 4 + */ 5 + #include <linux/fs.h> 6 + #include <linux/init.h> 7 + #include <linux/printk.h> 8 + #include <linux/proc_fs.h> 9 + #include <linux/seq_file.h> 10 + #include <linux/bootconfig.h> 11 + #include <linux/slab.h> 12 + 13 + static char *saved_boot_config; 14 + 15 + static int boot_config_proc_show(struct seq_file *m, void *v) 16 + { 17 + if (saved_boot_config) 18 + seq_puts(m, saved_boot_config); 19 + return 0; 20 + } 21 + 22 + /* Rest size of buffer */ 23 + #define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0) 24 + 25 + /* Return the needed total length if @size is 0 */ 26 + static int __init copy_xbc_key_value_list(char *dst, size_t size) 27 + { 28 + struct xbc_node *leaf, *vnode; 29 + const char *val; 30 + char *key, *end = dst + size; 31 + int ret = 0; 32 + 33 + key = kzalloc(XBC_KEYLEN_MAX, GFP_KERNEL); 34 + 35 + xbc_for_each_key_value(leaf, val) { 36 + ret = xbc_node_compose_key(leaf, key, XBC_KEYLEN_MAX); 37 + if (ret < 0) 38 + break; 39 + ret = snprintf(dst, rest(dst, end), "%s = ", key); 40 + if (ret < 0) 41 + break; 42 + dst += ret; 43 + vnode = xbc_node_get_child(leaf); 44 + if (vnode && xbc_node_is_array(vnode)) { 45 + xbc_array_for_each_value(vnode, val) { 46 + ret = snprintf(dst, rest(dst, end), "\"%s\"%s", 47 + val, vnode->next ? ", " : "\n"); 48 + if (ret < 0) 49 + goto out; 50 + dst += ret; 51 + } 52 + } else { 53 + ret = snprintf(dst, rest(dst, end), "\"%s\"\n", val); 54 + if (ret < 0) 55 + break; 56 + dst += ret; 57 + } 58 + } 59 + out: 60 + kfree(key); 61 + 62 + return ret < 0 ? ret : dst - (end - size); 63 + } 64 + 65 + static int __init proc_boot_config_init(void) 66 + { 67 + int len; 68 + 69 + len = copy_xbc_key_value_list(NULL, 0); 70 + if (len < 0) 71 + return len; 72 + 73 + if (len > 0) { 74 + saved_boot_config = kzalloc(len + 1, GFP_KERNEL); 75 + if (!saved_boot_config) 76 + return -ENOMEM; 77 + 78 + len = copy_xbc_key_value_list(saved_boot_config, len + 1); 79 + if (len < 0) { 80 + kfree(saved_boot_config); 81 + return len; 82 + } 83 + } 84 + 85 + proc_create_single("bootconfig", 0, NULL, boot_config_proc_show); 86 + 87 + return 0; 88 + } 89 + fs_initcall(proc_boot_config_init);