[PATCH] add EXPORT_SYMBOL_GPL_FUTURE()
[linux-2.6-block.git] / kernel / module.c
index 2a892b20d68f33a8291e8659bea60d4bfd245390..5ca99fbe9f44276c5bb6a1ca245ba7217a5a4cb8 100644 (file)
@@ -126,8 +126,11 @@ extern const struct kernel_symbol __start___ksymtab[];
 extern const struct kernel_symbol __stop___ksymtab[];
 extern const struct kernel_symbol __start___ksymtab_gpl[];
 extern const struct kernel_symbol __stop___ksymtab_gpl[];
+extern const struct kernel_symbol __start___ksymtab_gpl_future[];
+extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
 extern const unsigned long __start___kcrctab[];
 extern const unsigned long __start___kcrctab_gpl[];
+extern const unsigned long __start___kcrctab_gpl_future[];
 
 #ifndef CONFIG_MODVERSIONS
 #define symversion(base, idx) NULL
@@ -172,6 +175,22 @@ static unsigned long __find_symbol(const char *name,
                        return ks->value;
                }
        }
+       ks = lookup_symbol(name, __start___ksymtab_gpl_future,
+                                __stop___ksymtab_gpl_future);
+       if (ks) {
+               if (!gplok) {
+                       printk(KERN_WARNING "Symbol %s is being used "
+                              "by a non-GPL module, which will not "
+                              "be allowed in the future\n", name);
+                       printk(KERN_WARNING "Please see the file "
+                              "Documentation/feature-removal-schedule.txt "
+                              "in the kernel source tree for more "
+                              "details.\n");
+               }
+               *crc = symversion(__start___kcrctab_gpl_future,
+                                 (ks - __start___ksymtab_gpl_future));
+               return ks->value;
+       }
 
        /* Now try modules. */ 
        list_for_each_entry(mod, &modules, list) {
@@ -191,6 +210,23 @@ static unsigned long __find_symbol(const char *name,
                                return ks->value;
                        }
                }
+               ks = lookup_symbol(name, mod->gpl_future_syms,
+                                  (mod->gpl_future_syms +
+                                   mod->num_gpl_future_syms));
+               if (ks) {
+                       if (!gplok) {
+                               printk(KERN_WARNING "Symbol %s is being used "
+                                      "by a non-GPL module, which will not "
+                                      "be allowed in the future\n", name);
+                               printk(KERN_WARNING "Please see the file "
+                                      "Documentation/feature-removal-schedule.txt "
+                                      "in the kernel source tree for more "
+                                      "details.\n");
+                       }
+                       *crc = symversion(mod->gpl_future_crcs,
+                                         (ks - mod->gpl_future_syms));
+                       return ks->value;
+               }
        }
        DEBUGP("Failed to find symbol %s\n", name);
        return 0;
@@ -1546,7 +1582,8 @@ static struct module *load_module(void __user *umod,
        char *secstrings, *args, *modmagic, *strtab = NULL;
        unsigned int i, symindex = 0, strindex = 0, setupindex, exindex,
                exportindex, modindex, obsparmindex, infoindex, gplindex,
-               crcindex, gplcrcindex, versindex, pcpuindex;
+               crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex,
+               gplfuturecrcindex;
        long arglen;
        struct module *mod;
        long err = 0;
@@ -1627,8 +1664,10 @@ static struct module *load_module(void __user *umod,
        /* Optional sections */
        exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
        gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
+       gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");
        crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
        gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
+       gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");
        setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
        exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
        obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
@@ -1784,10 +1823,16 @@ static struct module *load_module(void __user *umod,
        mod->gpl_syms = (void *)sechdrs[gplindex].sh_addr;
        if (gplcrcindex)
                mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
+       mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /
+                                       sizeof(*mod->gpl_future_syms);
+       mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;
+       if (gplfuturecrcindex)
+               mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;
 
 #ifdef CONFIG_MODVERSIONS
        if ((mod->num_syms && !crcindex) || 
-           (mod->num_gpl_syms && !gplcrcindex)) {
+           (mod->num_gpl_syms && !gplcrcindex) ||
+           (mod->num_gpl_future_syms && !gplfuturecrcindex)) {
                printk(KERN_WARNING "%s: No versions for exported symbols."
                       " Tainting kernel.\n", mod->name);
                add_taint(TAINT_FORCED_MODULE);