1 From: Jeff Mahoney <jeffm@suse.com>
2 Subject: Export supported status via sysfs
4 This patch adds a /sys/kernel/supported file indicating the supportability
5 status of the entire kernel.
7 It also adds a /sys/module/<module>/supported file indicating the
8 supportability status of individual modules.
10 This is useful because it can be used to obtain the supported status
11 of a running system without current modules (ie: immediately after
12 a kernel update but before a reboot) and without generating an oops.
14 Signed-off-by: Jeff Mahoney <jeffm@suse.com>
18 include/linux/module.h | 1
19 kernel/ksysfs.c | 18 ++++++++++++
20 kernel/module.c | 70 ++++++++++++++++++++++++++++++++-----------------
21 3 files changed, 66 insertions(+), 23 deletions(-)
23 --- a/include/linux/module.h
24 +++ b/include/linux/module.h
25 @@ -363,6 +363,7 @@ static inline int module_is_live(struct
26 struct module *module_text_address(unsigned long addr);
27 struct module *__module_text_address(unsigned long addr);
28 int is_module_address(unsigned long addr);
29 +const char *supported_printable(int taint);
31 /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
32 symnum out of range. */
35 @@ -104,6 +104,23 @@ static struct bin_attribute notes_attr =
36 struct kobject *kernel_kobj;
37 EXPORT_SYMBOL_GPL(kernel_kobj);
39 +const char *supported_printable(int taint)
41 + if (taint & TAINT_NO_SUPPORT)
43 + else if (taint & TAINT_EXTERNAL_SUPPORT)
44 + return "Yes, External";
49 +static ssize_t supported_show(struct kobject *kobj,
50 + struct kobj_attribute *attr, char *buf)
52 + return sprintf(buf, "%s\n", supported_printable(tainted));
54 +KERNEL_ATTR_RO(supported);
56 static struct attribute * kernel_attrs[] = {
57 #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
58 &uevent_seqnum_attr.attr,
59 @@ -114,6 +131,7 @@ static struct attribute * kernel_attrs[]
60 &kexec_crash_loaded_attr.attr,
61 &vmcoreinfo_attr.attr,
63 + &supported_attr.attr,
69 @@ -922,10 +922,36 @@ static struct module_attribute initstate
70 .show = show_initstate,
73 +static void setup_modinfo_supported(struct module *mod, const char *s)
76 + mod->taints |= TAINT_NO_SUPPORT;
80 + if (strcmp(s, "external") == 0)
81 + mod->taints |= TAINT_EXTERNAL_SUPPORT;
82 + else if (strcmp(s, "yes"))
83 + mod->taints |= TAINT_NO_SUPPORT;
86 +static ssize_t show_modinfo_supported(struct module_attribute *mattr,
87 + struct module *mod, char *buffer)
89 + return sprintf(buffer, "%s\n", supported_printable(mod->taints));
92 +static struct module_attribute modinfo_supported = {
93 + .attr = { .name = "supported", .mode = 0444 },
94 + .show = show_modinfo_supported,
95 + .setup = setup_modinfo_supported,
98 static struct module_attribute *modinfo_attrs[] = {
102 + &modinfo_supported,
103 #ifdef CONFIG_MODULE_UNLOAD
106 @@ -1820,7 +1846,6 @@ static noinline struct module *load_modu
109 char *secstrings, *args, *modmagic, *strtab = NULL;
112 unsigned int symindex = 0;
113 unsigned int strindex = 0;
114 @@ -1975,28 +2000,6 @@ static noinline struct module *load_modu
118 - supported = get_modinfo(sechdrs, infoindex, "supported");
120 - if (!strcmp(supported, "external"))
121 - add_taint_module(mod, TAINT_EXTERNAL_SUPPORT);
122 - else if (strcmp(supported, "yes"))
126 - if (unsupported == 0) {
127 - printk(KERN_WARNING "%s: module not supported by "
128 - "Novell, refusing to load. To override, echo "
129 - "1 > /proc/sys/kernel/unsupported\n", mod->name);
133 - add_taint_module(mod, TAINT_NO_SUPPORT);
134 - if (unsupported == 1) {
135 - printk(KERN_WARNING "%s: module not supported by "
136 - "Novell, setting U taint flag.\n", mod->name);
140 /* Now copy in args */
141 args = strndup_user(uargs, ~0UL >> 1);
143 @@ -2256,6 +2259,26 @@ static noinline struct module *load_modu
144 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
145 add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
147 + /* We don't use add_taint() here because it also disables lockdep. */
148 + if (mod->taints & TAINT_EXTERNAL_SUPPORT)
149 + tainted |= TAINT_EXTERNAL_SUPPORT;
150 + else if (mod->taints == TAINT_NO_SUPPORT) {
151 + if (unsupported == 0) {
152 + printk(KERN_WARNING "%s: module not supported by "
153 + "Novell, refusing to load. To override, echo "
154 + "1 > /proc/sys/kernel/unsupported\n", mod->name);
158 + tainted |= TAINT_NO_SUPPORT;
159 + if (unsupported == 1) {
160 + printk(KERN_WARNING "%s: module is not supported by "
161 + "Novell. Novell Technical Services may decline "
162 + "your support request if it involves a kernel "
163 + "fault.\n", mod->name);
167 /* Size of section 0 is 0, so this works well if no unwind info. */
168 mod->unwind_info = unwind_add_table(mod,
169 (void *)sechdrs[unwindex].sh_addr,
170 @@ -2735,6 +2758,7 @@ void print_modules(void)
171 if (last_unloaded_module[0])
172 printk(" [last unloaded: %s]", last_unloaded_module);
174 + printk("Supported: %s\n", supported_printable(tainted));
177 #ifdef CONFIG_MODVERSIONS