From: "Randy.Dunlap" <randy.dunlap@verizon.net>


The SuSE kernels place their ikconfig info at /proc/config.gz: in a
different place, and compressed.  We thought it was a good idea to do it
that way in 2.6 as well.



- gzip the /proc config file, put it in /proc/config.gz;

- Based on a SuSE patch by Oliver Xymoron <oxymoron@waste.org>, which was
  derived from a patch by Nicholas Leon <nicholas@binary9.net>

- change /proc/ikconfig/built_with to /proc/config_build_info;

- cleanup ikconfig init/exit entry points (static, __init, __exit);

- Makefile help from Sam Ravnborg;

DESC
ikconfig cleanup
EDESC
From: Stephen Hemminger <shemminger@osdl.org>

Simplify and cleanup the code:
	- use single interface to seq_file where possible
	- don't need to do as much of the /proc interface, only read
	- use copy_to_user to avoid char at a time copy
	- remove unneccesary globals
	- use const char[] rather than const char * where possible.

Didn't change the version since interface doesn't change.



 25-akpm/init/Kconfig      |   12 ++---
 25-akpm/kernel/Makefile   |   25 ++++++++++-
 25-akpm/kernel/configs.c  |   98 ++++++++++++++++++++--------------------------
 25-akpm/scripts/Makefile  |    2 
 25-akpm/scripts/bin2c.c   |   27 ++++++++++++
 25-akpm/scripts/mkconfigs |   10 +---
 6 files changed, 104 insertions(+), 70 deletions(-)

diff -puN init/Kconfig~ikconfig-gzipped-2 init/Kconfig
--- 25/init/Kconfig~ikconfig-gzipped-2	Thu Sep  4 15:41:28 2003
+++ 25-akpm/init/Kconfig	Thu Sep  4 15:42:12 2003
@@ -134,24 +134,24 @@ config IKCONFIG
 	  This option enables the complete Linux kernel ".config" file
 	  contents, information on compiler used to build the kernel,
 	  kernel running when this kernel was built and kernel version
-	  from Makefile to be saved in kernel. It provides documentation
+	  from Makefile to be saved in the kernel. It provides documentation
 	  of which kernel options are used in a running kernel or in an
 	  on-disk kernel.  This information can be extracted from the kernel
 	  image file with the script scripts/extract-ikconfig and used as
 	  input to rebuild the current kernel or to build another kernel.
 	  It can also be extracted from a running kernel by reading
-	  /proc/ikconfig/config and /proc/ikconfig/built_with, if enabled.
-	  /proc/ikconfig/config will list the configuration that was used
-	  to build the kernel and /proc/ikconfig/built_with will list
+	  /proc/config.gz and /proc/config_built_with, if enabled (below).
+	  /proc/config.gz will list the configuration that was used
+	  to build the kernel and /proc/config_built_with will list
 	  information on the compiler and host machine that was used to
 	  build the kernel.
 
 config IKCONFIG_PROC
-	bool "Enable access to .config through /proc/ikconfig"
+	bool "Enable access to .config through /proc/config.gz"
 	depends on IKCONFIG && PROC_FS
 	---help---
 	  This option enables access to kernel configuration file and build
-	  information through /proc/ikconfig.
+	  information through /proc/config.gz.
 
 
 menuconfig EMBEDDED
diff -puN kernel/configs.c~ikconfig-gzipped-2 kernel/configs.c
--- 25/kernel/configs.c~ikconfig-gzipped-2	Thu Sep  4 15:41:28 2003
+++ 25-akpm/kernel/configs.c	Thu Sep  4 15:42:28 2003
@@ -23,6 +23,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
@@ -35,129 +36,116 @@
 /**************************************************/
 /* the actual current config file                 */
 
+/* This one is for extraction from the kernel binary file image. */
 #include "ikconfig.h"
 
 #ifdef CONFIG_IKCONFIG_PROC
 
+/* This is the data that can be read from /proc/config.gz. */
+#include "config_data.h"
+
 /**************************************************/
 /* globals and useful constants                   */
 
-static const char IKCONFIG_NAME[] = "ikconfig";
 static const char IKCONFIG_VERSION[] = "0.6";
 
-static int ikconfig_size;
-static struct proc_dir_entry *ikconfig_dir;
-
 static ssize_t
-ikconfig_read(struct file *file, char __user *buf, 
-		   size_t len, loff_t *offset)
+ikconfig_read_current(struct file *file, char __user *buf,
+		      size_t len, loff_t * offset)
 {
 	loff_t pos = *offset;
 	ssize_t count;
-	
-	if (pos >= ikconfig_size)
+
+	if (pos >= kernel_config_data_size)
 		return 0;
 
-	count = min(len, (size_t)(ikconfig_size - pos));
-	if(copy_to_user(buf, ikconfig_config + pos, count))
+	count = min(len, (size_t)(kernel_config_data_size - pos));
+	if(copy_to_user(buf, kernel_config_data + pos, count))
 		return -EFAULT;
 
 	*offset += count;
 	return count;
 }
 
-static struct file_operations config_fops = {
+static struct file_operations ikconfig_file_ops = {
 	.owner = THIS_MODULE,
-	.read  = ikconfig_read,
+	.read = ikconfig_read_current,
 };
 
+
 /***************************************************/
-/* built_with_show: let people read the info  */
+/* build_info_show: let people read the info       */
 /* we have on the tools used to build this kernel  */
 
-static int builtwith_show(struct seq_file *seq, void *v)
+static int build_info_show(struct seq_file *seq, void *v)
 {
-	seq_printf(seq, 
+	seq_printf(seq,
 		   "Kernel:    %s\nCompiler:  %s\nVersion_in_Makefile: %s\n",
-		   ikconfig_built_with, LINUX_COMPILER, UTS_RELEASE);
+		   ikconfig_build_info, LINUX_COMPILER, UTS_RELEASE);
 	return 0;
 }
 
-static int built_with_open(struct inode *inode, struct file *file)
+static int build_info_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, builtwith_show, PDE(inode)->data);
+	return single_open(file, build_info_show, PDE(inode)->data);
 }
-	
-static struct file_operations builtwith_fops = {
+
+static struct file_operations build_info_file_ops = {
 	.owner = THIS_MODULE,
-	.open  = built_with_open,
+	.open  = build_info_open,
 	.read  = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
-};	
+};
 
 /***************************************************/
 /* ikconfig_init: start up everything we need to */
 
-int __init
-ikconfig_init(void)
+static int __init ikconfig_init(void)
 {
 	struct proc_dir_entry *entry;
 
-	printk(KERN_INFO "ikconfig %s with /proc/ikconfig\n",
+	printk(KERN_INFO "ikconfig %s with /proc/config*\n",
 	       IKCONFIG_VERSION);
 
-	/* create the ikconfig directory */
-	ikconfig_dir = proc_mkdir(IKCONFIG_NAME, NULL);
-	if (ikconfig_dir == NULL) 
-		goto leave;
-	ikconfig_dir->owner = THIS_MODULE;
-
 	/* create the current config file */
-	entry = create_proc_entry("config", S_IFREG | S_IRUGO, ikconfig_dir);
+	entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
+				  &proc_root);
 	if (!entry)
-		goto leave2;
+		goto leave;
 
-	entry->proc_fops = &config_fops;
-	entry->size = ikconfig_size = strlen(ikconfig_config);
+	entry->proc_fops = &ikconfig_file_ops;
+	entry->size = kernel_config_data_size;
 
-	/* create the "built with" file */
-	entry = create_proc_entry("built_with", S_IFREG | S_IRUGO,
-				  ikconfig_dir);
+	/* create the "build_info" file */
+	entry = create_proc_entry("config_build_info",
+				  S_IFREG | S_IRUGO, &proc_root);
 	if (!entry)
-		goto leave3;
-	entry->proc_fops = &builtwith_fops;
+		goto leave_gz;
+	entry->proc_fops = &build_info_file_ops;
 
 	return 0;
 
-leave3:
+leave_gz:
 	/* remove the file from proc */
-	remove_proc_entry("config", ikconfig_dir);
-
-leave2:
-	/* remove the ikconfig directory */
-	remove_proc_entry(IKCONFIG_NAME, NULL);
+	remove_proc_entry("config.gz", &proc_root);
 
 leave:
 	return -ENOMEM;
 }
 
 /***************************************************/
-/* cleanup_ikconfig: clean up our mess           */
+/* ikconfig_cleanup: clean up our mess           */
 
-static void
-cleanup_ikconfig(void)
+static void __exit ikconfig_cleanup(void)
 {
 	/* remove the files */
-	remove_proc_entry("config", ikconfig_dir);
-	remove_proc_entry("built_with", ikconfig_dir);
-
-	/* remove the ikconfig directory */
-	remove_proc_entry(IKCONFIG_NAME, NULL);
+	remove_proc_entry("config.gz", &proc_root);
+	remove_proc_entry("config_build_info", &proc_root);
 }
 
 module_init(ikconfig_init);
-module_exit(cleanup_ikconfig);
+module_exit(ikconfig_cleanup);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Randy Dunlap");
diff -puN kernel/Makefile~ikconfig-gzipped-2 kernel/Makefile
--- 25/kernel/Makefile~ikconfig-gzipped-2	Thu Sep  4 15:41:28 2003
+++ 25-akpm/kernel/Makefile	Thu Sep  4 15:42:12 2003
@@ -19,6 +19,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_IKCONFIG) += configs.o
+obj-$(CONFIG_IKCONFIG_PROC) += configs.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
@@ -29,12 +30,32 @@ ifneq ($(CONFIG_IA64),y)
 CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
 endif
 
+# configs.o uses generated files - dependecies must be listed explicitly
+$(obj)/configs.o: $(obj)/ikconfig.h
+
+ifdef CONFIG_IKCONFIG_PROC
+$(obj)/configs.o: $(obj)/config_data.h
+endif
+
+# ikconfig.h contains all the selected config entries - generated
+# from top-level Makefile and .config. Info from ikconfig.h can
+# be extracted from the kernel binary.
+
 quiet_cmd_ikconfig = IKCFG   $@
       cmd_ikconfig = $(CONFIG_SHELL) $< .config $(srctree)/Makefile > $@
 
 targets += ikconfig.h
-
 $(obj)/ikconfig.h: scripts/mkconfigs .config Makefile FORCE
 	$(call if_changed,ikconfig)
 
-$(obj)/configs.o: $(obj)/ikconfig.h
+# config_data.h contains the same information as ikconfig.h but gzipped.
+# Info from config_data can be extracted from /proc/config*
+targets += config_data.gz
+$(obj)/config_data.gz: .config FORCE
+	$(call if_changed,gzip)
+
+quiet_cmd_ikconfiggz = IKCFG   $@
+      cmd_ikconfiggz = cat $< | scripts/bin2c kernel_config_data > $@
+targets += config_data.h
+$(obj)/config_data.h: $(obj)/config_data.gz FORCE
+	$(call if_changed,ikconfiggz)
diff -puN /dev/null scripts/bin2c.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/scripts/bin2c.c	Thu Sep  4 15:42:28 2003
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+	int ch, total=0;
+
+	if (argc > 1)
+		printf("const char %s[] %s=\n",
+			argv[1], argc > 2 ? argv[2] : "");
+
+	do {
+		printf("\t\"");
+		while ((ch = getchar()) != EOF)
+		{
+			total++;
+			printf("\\x%02x",ch);
+			if (total % 16 == 0)
+				break;
+		}
+		printf("\"\n");
+	} while (ch != EOF);
+
+	if (argc > 1)
+		printf("\t;\n\nconst int %s_size = %d;\n", argv[1], total);
+
+	return 0;
+}
diff -puN scripts/Makefile~ikconfig-gzipped-2 scripts/Makefile
--- 25/scripts/Makefile~ikconfig-gzipped-2	Thu Sep  4 15:41:28 2003
+++ 25-akpm/scripts/Makefile	Thu Sep  4 15:42:12 2003
@@ -9,7 +9,7 @@
 # conmakehash:	 Create arrays for initializing the kernel console tables
 
 host-progs	:= fixdep split-include conmakehash docproc kallsyms modpost \
-		   mk_elfconfig pnmtologo
+		   mk_elfconfig pnmtologo bin2c
 always		:= $(host-progs) empty.o
 
 modpost-objs	:= modpost.o file2alias.o
diff -puN scripts/mkconfigs~ikconfig-gzipped-2 scripts/mkconfigs
--- 25/scripts/mkconfigs~ikconfig-gzipped-2	Thu Sep  4 15:41:28 2003
+++ 25-akpm/scripts/mkconfigs	Thu Sep  4 15:42:28 2003
@@ -66,15 +66,13 @@ echo \
  *
  */"
 
-echo "static char *ikconfig_built_with ="
+echo "#ifdef CONFIG_IKCONFIG_PROC"
+echo "static char const ikconfig_build_info[] ="
 echo "    \"`uname -s` `uname -r` `uname -v` `uname -m`\";"
+echo "#endif"
 echo
 kernel_version $makefile
-echo "#ifdef CONFIG_IKCONFIG_PROC"
-echo "static char *ikconfig_config = "
-echo "#else"
-echo "static char *ikconfig_config __initdata __attribute__((unused)) = "
-echo "#endif"
+echo "static char const ikconfig_config[] __attribute__((unused)) = "
 echo "\"CONFIG_BEGIN=n\\n\\"
 echo "`cat $config | sed 's/\"/\\\\\"/g' | grep "^#\? \?CONFIG_" | awk '{ print $0 "\\\\n\\\\" }' `"
 echo "CONFIG_END=n\\n\";"

_