Mainly boring here, too. rmmod --wait finally removed, though.

Cheers,
 Rusty.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.14 (GNU/Linux)
 
 iQIcBAABAgAGBQJSe3ngAAoJENkgDmzRrbjxqkMP/jFwTIVy+tZbPL36xR4C7UI/
 JZ9JU2c2HTyAtqp/T/bljA0QUDQWUASCfwG5WmRgyvMkEwhfuGrQ3dveQLRq5iKD
 Ln/LIN8JXXijhRr+ywhXLAcp1P5ysSJJYYS5lZTCmJ2Cv9jnAvmUl0KqdTEx+ZNH
 YsWBiI9+WmwhODiAdUlqtThDK37w8OsWeMq2agf97bBERlRYnRZvzwy3tSP2mf5j
 4wx8viOdzPC7NVblyX1cj3gonFFQJtMI4s/e787QzkUpNQjvrN3XecPiQX6aBCX3
 seVjuv6panv1tw1HqyU1KXWo7fs2uCc9mVR5Rr3Zok+8qpKWkj0dyCnF3A+ufsrO
 vlkrFLUsv/U1NUkWJM6mJKzMjKRD4iF702QsEEpNA5rlOsAMMGSSlju4eu6GvadI
 ZJ+ZDaNWUDPbWa9Xgjyp+DKWR6vybNgEHZmLmcCdeLt1u8Th1E/ujsKxv4SN6eIO
 2v+lNPjGEivoNXUX52toRZ1324U3FFzburCSA0c55+r1sjPT6SXCfl8kISSKvVtt
 iFemsDxhaSwqVzqbsx3ztU010Z0f9uVbpZHAQgZ514Uk25HtwhkaQSdiIP+cPXE8
 rClzj9m4gD+Jy0T+P0HjPlSxKCGSlgLiEBWEigX36/F4Isv+GL1HjvrGGCWM4VnO
 lIyw5ux/UH8USct9nH4x
 =xg2p
 -----END PGP SIGNATURE-----

Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux

Pull module updates from Rusty Russell:
 "Mainly boring here, too.  rmmod --wait finally removed, though"

* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  modpost: fix bogus 'exported twice' warnings.
  init: fix in-place parameter modification regression
  asmlinkage, module: Make ksymtab and kcrctab symbols and __this_module __visible
  kernel: add support for init_array constructors
  modpost: Optionally ignore secondary errors seen if a single module build fails
  module: remove rmmod --wait option.
This commit is contained in:
Linus Torvalds 2013-11-15 13:27:50 +09:00
commit ce6513f758
7 changed files with 55 additions and 52 deletions

View File

@ -473,6 +473,7 @@
#define KERNEL_CTORS() . = ALIGN(8); \ #define KERNEL_CTORS() . = ALIGN(8); \
VMLINUX_SYMBOL(__ctors_start) = .; \ VMLINUX_SYMBOL(__ctors_start) = .; \
*(.ctors) \ *(.ctors) \
*(.init_array) \
VMLINUX_SYMBOL(__ctors_end) = .; VMLINUX_SYMBOL(__ctors_end) = .;
#else #else
#define KERNEL_CTORS() #define KERNEL_CTORS()

View File

@ -43,7 +43,7 @@ extern struct module __this_module;
/* Mark the CRC weak since genksyms apparently decides not to /* Mark the CRC weak since genksyms apparently decides not to
* generate a checksums for some symbols */ * generate a checksums for some symbols */
#define __CRC_SYMBOL(sym, sec) \ #define __CRC_SYMBOL(sym, sec) \
extern void *__crc_##sym __attribute__((weak)); \ extern __visible void *__crc_##sym __attribute__((weak)); \
static const unsigned long __kcrctab_##sym \ static const unsigned long __kcrctab_##sym \
__used \ __used \
__attribute__((section("___kcrctab" sec "+" #sym), unused)) \ __attribute__((section("___kcrctab" sec "+" #sym), unused)) \
@ -59,7 +59,7 @@ extern struct module __this_module;
static const char __kstrtab_##sym[] \ static const char __kstrtab_##sym[] \
__attribute__((section("__ksymtab_strings"), aligned(1))) \ __attribute__((section("__ksymtab_strings"), aligned(1))) \
= VMLINUX_SYMBOL_STR(sym); \ = VMLINUX_SYMBOL_STR(sym); \
static const struct kernel_symbol __ksymtab_##sym \ __visible const struct kernel_symbol __ksymtab_##sym \
__used \ __used \
__attribute__((section("___ksymtab" sec "+" #sym), unused)) \ __attribute__((section("___ksymtab" sec "+" #sym), unused)) \
= { (unsigned long)&sym, __kstrtab_##sym } = { (unsigned long)&sym, __kstrtab_##sym }

View File

@ -367,9 +367,6 @@ struct module
/* What modules do I depend on? */ /* What modules do I depend on? */
struct list_head target_list; struct list_head target_list;
/* Who is waiting for us to be unloaded */
struct task_struct *waiter;
/* Destruction function. */ /* Destruction function. */
void (*exit)(void); void (*exit)(void);

View File

@ -131,6 +131,8 @@ char __initdata boot_command_line[COMMAND_LINE_SIZE];
char *saved_command_line; char *saved_command_line;
/* Command line for parameter parsing */ /* Command line for parameter parsing */
static char *static_command_line; static char *static_command_line;
/* Command line for per-initcall parameter parsing */
static char *initcall_command_line;
static char *execute_command; static char *execute_command;
static char *ramdisk_execute_command; static char *ramdisk_execute_command;
@ -354,6 +356,7 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { }
static void __init setup_command_line(char *command_line) static void __init setup_command_line(char *command_line)
{ {
saved_command_line = alloc_bootmem(strlen (boot_command_line)+1); saved_command_line = alloc_bootmem(strlen (boot_command_line)+1);
initcall_command_line = alloc_bootmem(strlen (boot_command_line)+1);
static_command_line = alloc_bootmem(strlen (command_line)+1); static_command_line = alloc_bootmem(strlen (command_line)+1);
strcpy (saved_command_line, boot_command_line); strcpy (saved_command_line, boot_command_line);
strcpy (static_command_line, command_line); strcpy (static_command_line, command_line);
@ -751,9 +754,9 @@ static void __init do_initcall_level(int level)
extern const struct kernel_param __start___param[], __stop___param[]; extern const struct kernel_param __start___param[], __stop___param[];
initcall_t *fn; initcall_t *fn;
strcpy(static_command_line, saved_command_line); strcpy(initcall_command_line, saved_command_line);
parse_args(initcall_level_names[level], parse_args(initcall_level_names[level],
static_command_line, __start___param, initcall_command_line, __start___param,
__stop___param - __start___param, __stop___param - __start___param,
level, level, level, level,
&repair_env_string); &repair_env_string);

View File

@ -641,8 +641,6 @@ static int module_unload_init(struct module *mod)
/* Hold reference count during initialization. */ /* Hold reference count during initialization. */
__this_cpu_write(mod->refptr->incs, 1); __this_cpu_write(mod->refptr->incs, 1);
/* Backwards compatibility macros put refcount during init. */
mod->waiter = current;
return 0; return 0;
} }
@ -768,16 +766,9 @@ static int __try_stop_module(void *_sref)
static int try_stop_module(struct module *mod, int flags, int *forced) static int try_stop_module(struct module *mod, int flags, int *forced)
{ {
if (flags & O_NONBLOCK) { struct stopref sref = { mod, flags, forced };
struct stopref sref = { mod, flags, forced };
return stop_machine(__try_stop_module, &sref, NULL); return stop_machine(__try_stop_module, &sref, NULL);
} else {
/* We don't need to stop the machine for this. */
mod->state = MODULE_STATE_GOING;
synchronize_sched();
return 0;
}
} }
unsigned long module_refcount(struct module *mod) unsigned long module_refcount(struct module *mod)
@ -810,21 +801,6 @@ EXPORT_SYMBOL(module_refcount);
/* This exists whether we can unload or not */ /* This exists whether we can unload or not */
static void free_module(struct module *mod); static void free_module(struct module *mod);
static void wait_for_zero_refcount(struct module *mod)
{
/* Since we might sleep for some time, release the mutex first */
mutex_unlock(&module_mutex);
for (;;) {
pr_debug("Looking at refcount...\n");
set_current_state(TASK_UNINTERRUPTIBLE);
if (module_refcount(mod) == 0)
break;
schedule();
}
current->state = TASK_RUNNING;
mutex_lock(&module_mutex);
}
SYSCALL_DEFINE2(delete_module, const char __user *, name_user, SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
unsigned int, flags) unsigned int, flags)
{ {
@ -839,6 +815,11 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
return -EFAULT; return -EFAULT;
name[MODULE_NAME_LEN-1] = '\0'; name[MODULE_NAME_LEN-1] = '\0';
if (!(flags & O_NONBLOCK)) {
printk(KERN_WARNING
"waiting module removal not supported: please upgrade");
}
if (mutex_lock_interruptible(&module_mutex) != 0) if (mutex_lock_interruptible(&module_mutex) != 0)
return -EINTR; return -EINTR;
@ -856,8 +837,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
/* Doing init or already dying? */ /* Doing init or already dying? */
if (mod->state != MODULE_STATE_LIVE) { if (mod->state != MODULE_STATE_LIVE) {
/* FIXME: if (force), slam module count and wake up /* FIXME: if (force), slam module count damn the torpedoes */
waiter --RR */
pr_debug("%s already dying\n", mod->name); pr_debug("%s already dying\n", mod->name);
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
@ -873,18 +853,11 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
} }
} }
/* Set this up before setting mod->state */
mod->waiter = current;
/* Stop the machine so refcounts can't move and disable module. */ /* Stop the machine so refcounts can't move and disable module. */
ret = try_stop_module(mod, flags, &forced); ret = try_stop_module(mod, flags, &forced);
if (ret != 0) if (ret != 0)
goto out; goto out;
/* Never wait if forced. */
if (!forced && module_refcount(mod) != 0)
wait_for_zero_refcount(mod);
mutex_unlock(&module_mutex); mutex_unlock(&module_mutex);
/* Final destruction now no one is using it. */ /* Final destruction now no one is using it. */
if (mod->exit != NULL) if (mod->exit != NULL)
@ -1002,9 +975,6 @@ void module_put(struct module *module)
__this_cpu_inc(module->refptr->decs); __this_cpu_inc(module->refptr->decs);
trace_module_put(module, _RET_IP_); trace_module_put(module, _RET_IP_);
/* Maybe they're waiting for us to drop reference? */
if (unlikely(!module_is_live(module)))
wake_up_process(module->waiter);
preempt_enable(); preempt_enable();
} }
} }
@ -2728,7 +2698,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
return 0; return 0;
} }
static void find_module_sections(struct module *mod, struct load_info *info) static int find_module_sections(struct module *mod, struct load_info *info)
{ {
mod->kp = section_objs(info, "__param", mod->kp = section_objs(info, "__param",
sizeof(*mod->kp), &mod->num_kp); sizeof(*mod->kp), &mod->num_kp);
@ -2758,6 +2728,18 @@ static void find_module_sections(struct module *mod, struct load_info *info)
#ifdef CONFIG_CONSTRUCTORS #ifdef CONFIG_CONSTRUCTORS
mod->ctors = section_objs(info, ".ctors", mod->ctors = section_objs(info, ".ctors",
sizeof(*mod->ctors), &mod->num_ctors); sizeof(*mod->ctors), &mod->num_ctors);
if (!mod->ctors)
mod->ctors = section_objs(info, ".init_array",
sizeof(*mod->ctors), &mod->num_ctors);
else if (find_sec(info, ".init_array")) {
/*
* This shouldn't happen with same compiler and binutils
* building all parts of the module.
*/
printk(KERN_WARNING "%s: has both .ctors and .init_array.\n",
mod->name);
return -EINVAL;
}
#endif #endif
#ifdef CONFIG_TRACEPOINTS #ifdef CONFIG_TRACEPOINTS
@ -2795,6 +2777,8 @@ static void find_module_sections(struct module *mod, struct load_info *info)
info->debug = section_objs(info, "__verbose", info->debug = section_objs(info, "__verbose",
sizeof(*info->debug), &info->num_debug); sizeof(*info->debug), &info->num_debug);
return 0;
} }
static int move_module(struct module *mod, struct load_info *info) static int move_module(struct module *mod, struct load_info *info)
@ -3248,7 +3232,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
/* Now we've got everything in the final locations, we can /* Now we've got everything in the final locations, we can
* find optional sections. */ * find optional sections. */
find_module_sections(mod, info); err = find_module_sections(mod, info);
if (err)
goto free_unload;
err = check_module_license_and_versions(mod); err = check_module_license_and_versions(mod);
if (err) if (err)

View File

@ -79,9 +79,11 @@ modpost = scripts/mod/modpost \
$(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
$(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
# We can go over command line length here, so be careful. # We can go over command line length here, so be careful.
quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
cmd_modpost = $(MODLISTCMD) | sed 's/\.ko$$/.o/' | $(modpost) -s -T - cmd_modpost = $(MODLISTCMD) | sed 's/\.ko$$/.o/' | $(modpost) $(MODPOST_OPT) -s -T -
PHONY += __modpost PHONY += __modpost
__modpost: $(modules:.ko=.o) FORCE __modpost: $(modules:.ko=.o) FORCE

View File

@ -17,6 +17,7 @@
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <stdbool.h> #include <stdbool.h>
#include <errno.h>
#include "modpost.h" #include "modpost.h"
#include "../../include/generated/autoconf.h" #include "../../include/generated/autoconf.h"
#include "../../include/linux/license.h" #include "../../include/linux/license.h"
@ -37,6 +38,8 @@ static int warn_unresolved = 0;
/* How a symbol is exported */ /* How a symbol is exported */
static int sec_mismatch_count = 0; static int sec_mismatch_count = 0;
static int sec_mismatch_verbose = 1; static int sec_mismatch_verbose = 1;
/* ignore missing files */
static int ignore_missing_files;
enum export { enum export {
export_plain, export_unused, export_gpl, export_plain, export_unused, export_gpl,
@ -161,7 +164,7 @@ struct symbol {
unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
unsigned int kernel:1; /* 1 if symbol is from kernel unsigned int kernel:1; /* 1 if symbol is from kernel
* (only for external modules) **/ * (only for external modules) **/
unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ unsigned int preloaded:1; /* 1 if symbol from Module.symvers, or crc */
enum export export; /* Type of export */ enum export export; /* Type of export */
char name[0]; char name[0];
}; };
@ -329,8 +332,11 @@ static void sym_update_crc(const char *name, struct module *mod,
{ {
struct symbol *s = find_symbol(name); struct symbol *s = find_symbol(name);
if (!s) if (!s) {
s = new_symbol(name, mod, export); s = new_symbol(name, mod, export);
/* Don't complain when we find it later. */
s->preloaded = 1;
}
s->crc = crc; s->crc = crc;
s->crc_valid = 1; s->crc_valid = 1;
} }
@ -407,6 +413,11 @@ static int parse_elf(struct elf_info *info, const char *filename)
hdr = grab_file(filename, &info->size); hdr = grab_file(filename, &info->size);
if (!hdr) { if (!hdr) {
if (ignore_missing_files) {
fprintf(stderr, "%s: %s (ignored)\n", filename,
strerror(errno));
return 0;
}
perror(filename); perror(filename);
exit(1); exit(1);
} }
@ -1852,7 +1863,7 @@ static void add_header(struct buffer *b, struct module *mod)
buf_printf(b, "\n"); buf_printf(b, "\n");
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
buf_printf(b, "\n"); buf_printf(b, "\n");
buf_printf(b, "struct module __this_module\n"); buf_printf(b, "__visible struct module __this_module\n");
buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
buf_printf(b, "\t.name = KBUILD_MODNAME,\n"); buf_printf(b, "\t.name = KBUILD_MODNAME,\n");
if (mod->has_init) if (mod->has_init)
@ -2118,7 +2129,7 @@ int main(int argc, char **argv)
struct ext_sym_list *extsym_iter; struct ext_sym_list *extsym_iter;
struct ext_sym_list *extsym_start = NULL; struct ext_sym_list *extsym_start = NULL;
while ((opt = getopt(argc, argv, "i:I:e:msST:o:awM:K:")) != -1) { while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:")) != -1) {
switch (opt) { switch (opt) {
case 'i': case 'i':
kernel_read = optarg; kernel_read = optarg;
@ -2138,6 +2149,9 @@ int main(int argc, char **argv)
case 'm': case 'm':
modversions = 1; modversions = 1;
break; break;
case 'n':
ignore_missing_files = 1;
break;
case 'o': case 'o':
dump_write = optarg; dump_write = optarg;
break; break;