aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2006-06-28 07:26:45 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-28 17:59:04 -0400
commitf71d20e961474dde77e6558396efb93d6ac80a4b (patch)
tree669610f79521fd173c28fc47bef39ecd4cdf52ab
parentf5e54d6e53a20cef45af7499e86164f0e0d16bb2 (diff)
[PATCH] Add EXPORT_UNUSED_SYMBOL and EXPORT_UNUSED_SYMBOL_GPL
Temporarily add EXPORT_UNUSED_SYMBOL and EXPORT_UNUSED_SYMBOL_GPL. These will be used as a transition measure for symbols that aren't used in the kernel and are on the way out. When a module uses such a symbol, a warning is printk'd at modprobe time. The main reason for removing unused exports is size: eacho export takes roughly between 100 and 150 bytes of kernel space in the binary. This patch gives users the option to immediately get this size gain via a config option. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/feature-removal-schedule.txt10
-rw-r--r--include/asm-generic/vmlinux.lds.h28
-rw-r--r--include/linux/module.h20
-rw-r--r--kernel/module.c78
-rw-r--r--lib/Kconfig.debug16
5 files changed, 150 insertions, 2 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 027285d0c26c..033ac91da07a 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -177,6 +177,16 @@ Who: Jean Delvare <khali@linux-fr.org>
177 177
178--------------------------- 178---------------------------
179 179
180What: Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
181 (temporary transition config option provided until then)
182 The transition config option will also be removed at the same time.
183When: before 2.6.19
184Why: Unused symbols are both increasing the size of the kernel binary
185 and are often a sign of "wrong API"
186Who: Arjan van de Ven <arjan@linux.intel.com>
187
188---------------------------
189
180What: remove EXPORT_SYMBOL(tasklist_lock) 190What: remove EXPORT_SYMBOL(tasklist_lock)
181When: August 2006 191When: August 2006
182Files: kernel/fork.c 192Files: kernel/fork.c
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 9d11550b4818..db5a3732f106 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -58,6 +58,20 @@
58 VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ 58 VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
59 } \ 59 } \
60 \ 60 \
61 /* Kernel symbol table: Normal unused symbols */ \
62 __ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \
63 VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \
64 *(__ksymtab_unused) \
65 VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \
66 } \
67 \
68 /* Kernel symbol table: GPL-only unused symbols */ \
69 __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
70 VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \
71 *(__ksymtab_unused_gpl) \
72 VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \
73 } \
74 \
61 /* Kernel symbol table: GPL-future-only symbols */ \ 75 /* Kernel symbol table: GPL-future-only symbols */ \
62 __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \ 76 __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
63 VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \ 77 VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
@@ -79,6 +93,20 @@
79 VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \ 93 VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
80 } \ 94 } \
81 \ 95 \
96 /* Kernel symbol table: Normal unused symbols */ \
97 __kcrctab_unused : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) { \
98 VMLINUX_SYMBOL(__start___kcrctab_unused) = .; \
99 *(__kcrctab_unused) \
100 VMLINUX_SYMBOL(__stop___kcrctab_unused) = .; \
101 } \
102 \
103 /* Kernel symbol table: GPL-only unused symbols */ \
104 __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
105 VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \
106 *(__kcrctab_unused_gpl) \
107 VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \
108 } \
109 \
82 /* Kernel symbol table: GPL-future-only symbols */ \ 110 /* Kernel symbol table: GPL-future-only symbols */ \
83 __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \ 111 __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
84 VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \ 112 VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \
diff --git a/include/linux/module.h b/include/linux/module.h
index 9ebbb74b7b72..9e9dc7c24d95 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -203,6 +203,15 @@ void *__symbol_get_gpl(const char *symbol);
203#define EXPORT_SYMBOL_GPL_FUTURE(sym) \ 203#define EXPORT_SYMBOL_GPL_FUTURE(sym) \
204 __EXPORT_SYMBOL(sym, "_gpl_future") 204 __EXPORT_SYMBOL(sym, "_gpl_future")
205 205
206
207#ifdef CONFIG_UNUSED_SYMBOLS
208#define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused")
209#define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl")
210#else
211#define EXPORT_UNUSED_SYMBOL(sym)
212#define EXPORT_UNUSED_SYMBOL_GPL(sym)
213#endif
214
206#endif 215#endif
207 216
208struct module_ref 217struct module_ref
@@ -261,6 +270,15 @@ struct module
261 unsigned int num_gpl_syms; 270 unsigned int num_gpl_syms;
262 const unsigned long *gpl_crcs; 271 const unsigned long *gpl_crcs;
263 272
273 /* unused exported symbols. */
274 const struct kernel_symbol *unused_syms;
275 unsigned int num_unused_syms;
276 const unsigned long *unused_crcs;
277 /* GPL-only, unused exported symbols. */
278 const struct kernel_symbol *unused_gpl_syms;
279 unsigned int num_unused_gpl_syms;
280 const unsigned long *unused_gpl_crcs;
281
264 /* symbols that will be GPL-only in the near future. */ 282 /* symbols that will be GPL-only in the near future. */
265 const struct kernel_symbol *gpl_future_syms; 283 const struct kernel_symbol *gpl_future_syms;
266 unsigned int num_gpl_future_syms; 284 unsigned int num_gpl_future_syms;
@@ -456,6 +474,8 @@ void module_remove_driver(struct device_driver *);
456#define EXPORT_SYMBOL(sym) 474#define EXPORT_SYMBOL(sym)
457#define EXPORT_SYMBOL_GPL(sym) 475#define EXPORT_SYMBOL_GPL(sym)
458#define EXPORT_SYMBOL_GPL_FUTURE(sym) 476#define EXPORT_SYMBOL_GPL_FUTURE(sym)
477#define EXPORT_UNUSED_SYMBOL(sym)
478#define EXPORT_UNUSED_SYMBOL_GPL(sym)
459 479
460/* Given an address, look for it in the exception tables. */ 480/* Given an address, look for it in the exception tables. */
461static inline const struct exception_table_entry * 481static inline const struct exception_table_entry *
diff --git a/kernel/module.c b/kernel/module.c
index 10e5b872adf6..03b738172a8c 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1,4 +1,4 @@
1/* Rewritten by Rusty Russell, on the backs of many others... 1/*
2 Copyright (C) 2002 Richard Henderson 2 Copyright (C) 2002 Richard Henderson
3 Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. 3 Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
4 4
@@ -122,9 +122,17 @@ extern const struct kernel_symbol __start___ksymtab_gpl[];
122extern const struct kernel_symbol __stop___ksymtab_gpl[]; 122extern const struct kernel_symbol __stop___ksymtab_gpl[];
123extern const struct kernel_symbol __start___ksymtab_gpl_future[]; 123extern const struct kernel_symbol __start___ksymtab_gpl_future[];
124extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; 124extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
125extern const struct kernel_symbol __start___ksymtab_unused[];
126extern const struct kernel_symbol __stop___ksymtab_unused[];
127extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
128extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
129extern const struct kernel_symbol __start___ksymtab_gpl_future[];
130extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
125extern const unsigned long __start___kcrctab[]; 131extern const unsigned long __start___kcrctab[];
126extern const unsigned long __start___kcrctab_gpl[]; 132extern const unsigned long __start___kcrctab_gpl[];
127extern const unsigned long __start___kcrctab_gpl_future[]; 133extern const unsigned long __start___kcrctab_gpl_future[];
134extern const unsigned long __start___kcrctab_unused[];
135extern const unsigned long __start___kcrctab_unused_gpl[];
128 136
129#ifndef CONFIG_MODVERSIONS 137#ifndef CONFIG_MODVERSIONS
130#define symversion(base, idx) NULL 138#define symversion(base, idx) NULL
@@ -144,6 +152,17 @@ static const struct kernel_symbol *lookup_symbol(const char *name,
144 return NULL; 152 return NULL;
145} 153}
146 154
155static void printk_unused_warning(const char *name)
156{
157 printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
158 "however this module is using it.\n", name);
159 printk(KERN_WARNING "This symbol will go away in the future.\n");
160 printk(KERN_WARNING "Please evalute if this is the right api to use, "
161 "and if it really is, submit a report the linux kernel "
162 "mailinglist together with submitting your code for "
163 "inclusion.\n");
164}
165
147/* Find a symbol, return value, crc and module which owns it */ 166/* Find a symbol, return value, crc and module which owns it */
148static unsigned long __find_symbol(const char *name, 167static unsigned long __find_symbol(const char *name,
149 struct module **owner, 168 struct module **owner,
@@ -186,6 +205,25 @@ static unsigned long __find_symbol(const char *name,
186 return ks->value; 205 return ks->value;
187 } 206 }
188 207
208 ks = lookup_symbol(name, __start___ksymtab_unused,
209 __stop___ksymtab_unused);
210 if (ks) {
211 printk_unused_warning(name);
212 *crc = symversion(__start___kcrctab_unused,
213 (ks - __start___ksymtab_unused));
214 return ks->value;
215 }
216
217 if (gplok)
218 ks = lookup_symbol(name, __start___ksymtab_unused_gpl,
219 __stop___ksymtab_unused_gpl);
220 if (ks) {
221 printk_unused_warning(name);
222 *crc = symversion(__start___kcrctab_unused_gpl,
223 (ks - __start___ksymtab_unused_gpl));
224 return ks->value;
225 }
226
189 /* Now try modules. */ 227 /* Now try modules. */
190 list_for_each_entry(mod, &modules, list) { 228 list_for_each_entry(mod, &modules, list) {
191 *owner = mod; 229 *owner = mod;
@@ -204,6 +242,23 @@ static unsigned long __find_symbol(const char *name,
204 return ks->value; 242 return ks->value;
205 } 243 }
206 } 244 }
245 ks = lookup_symbol(name, mod->unused_syms, mod->unused_syms + mod->num_unused_syms);
246 if (ks) {
247 printk_unused_warning(name);
248 *crc = symversion(mod->unused_crcs, (ks - mod->unused_syms));
249 return ks->value;
250 }
251
252 if (gplok) {
253 ks = lookup_symbol(name, mod->unused_gpl_syms,
254 mod->unused_gpl_syms + mod->num_unused_gpl_syms);
255 if (ks) {
256 printk_unused_warning(name);
257 *crc = symversion(mod->unused_gpl_crcs,
258 (ks - mod->unused_gpl_syms));
259 return ks->value;
260 }
261 }
207 ks = lookup_symbol(name, mod->gpl_future_syms, 262 ks = lookup_symbol(name, mod->gpl_future_syms,
208 (mod->gpl_future_syms + 263 (mod->gpl_future_syms +
209 mod->num_gpl_future_syms)); 264 mod->num_gpl_future_syms));
@@ -1407,6 +1462,8 @@ static struct module *load_module(void __user *umod,
1407 exportindex, modindex, obsparmindex, infoindex, gplindex, 1462 exportindex, modindex, obsparmindex, infoindex, gplindex,
1408 crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex, 1463 crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex,
1409 gplfuturecrcindex, unwindex = 0; 1464 gplfuturecrcindex, unwindex = 0;
1465 unsigned int unusedindex, unusedcrcindex, unusedgplindex,
1466 unusedgplcrcindex;
1410 struct module *mod; 1467 struct module *mod;
1411 long err = 0; 1468 long err = 0;
1412 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1469 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1487,9 +1544,13 @@ static struct module *load_module(void __user *umod,
1487 exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); 1544 exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
1488 gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); 1545 gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
1489 gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); 1546 gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");
1547 unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
1548 unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
1490 crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); 1549 crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
1491 gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); 1550 gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
1492 gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); 1551 gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");
1552 unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused");
1553 unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl");
1493 setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); 1554 setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
1494 exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); 1555 exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
1495 obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); 1556 obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
@@ -1638,14 +1699,27 @@ static struct module *load_module(void __user *umod,
1638 mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; 1699 mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
1639 mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / 1700 mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /
1640 sizeof(*mod->gpl_future_syms); 1701 sizeof(*mod->gpl_future_syms);
1702 mod->num_unused_syms = sechdrs[unusedindex].sh_size /
1703 sizeof(*mod->unused_syms);
1704 mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
1705 sizeof(*mod->unused_gpl_syms);
1641 mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; 1706 mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;
1642 if (gplfuturecrcindex) 1707 if (gplfuturecrcindex)
1643 mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; 1708 mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;
1644 1709
1710 mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;
1711 if (unusedcrcindex)
1712 mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;
1713 mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr;
1714 if (unusedgplcrcindex)
1715 mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr;
1716
1645#ifdef CONFIG_MODVERSIONS 1717#ifdef CONFIG_MODVERSIONS
1646 if ((mod->num_syms && !crcindex) || 1718 if ((mod->num_syms && !crcindex) ||
1647 (mod->num_gpl_syms && !gplcrcindex) || 1719 (mod->num_gpl_syms && !gplcrcindex) ||
1648 (mod->num_gpl_future_syms && !gplfuturecrcindex)) { 1720 (mod->num_gpl_future_syms && !gplfuturecrcindex) ||
1721 (mod->num_unused_syms && !unusedcrcindex) ||
1722 (mod->num_unused_gpl_syms && !unusedgplcrcindex)) {
1649 printk(KERN_WARNING "%s: No versions for exported symbols." 1723 printk(KERN_WARNING "%s: No versions for exported symbols."
1650 " Tainting kernel.\n", mod->name); 1724 " Tainting kernel.\n", mod->name);
1651 add_taint(TAINT_FORCED_MODULE); 1725 add_taint(TAINT_FORCED_MODULE);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5330911ebd30..e4fcbd12cf6e 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -23,6 +23,22 @@ config MAGIC_SYSRQ
23 keys are documented in <file:Documentation/sysrq.txt>. Don't say Y 23 keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
24 unless you really know what this hack does. 24 unless you really know what this hack does.
25 25
26config UNUSED_SYMBOLS
27 bool "Enable unused/obsolete exported symbols"
28 default y if X86
29 help
30 Unused but exported symbols make the kernel needlessly bigger. For
31 that reason most of these unused exports will soon be removed. This
32 option is provided temporarily to provide a transition period in case
33 some external kernel module needs one of these symbols anyway. If you
34 encounter such a case in your module, consider if you are actually
35 using the right API. (rationale: since nobody in the kernel is using
36 this in a module, there is a pretty good chance it's actually the
37 wrong interface to use). If you really need the symbol, please send a
38 mail to the linux kernel mailing list mentioning the symbol and why
39 you really need it, and what the merge plan to the mainline kernel for
40 your module is.
41
26config DEBUG_KERNEL 42config DEBUG_KERNEL
27 bool "Kernel debugging" 43 bool "Kernel debugging"
28 help 44 help