mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 05:04:09 +08:00
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:
commit
ce6513f758
@ -473,6 +473,7 @@
|
||||
#define KERNEL_CTORS() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__ctors_start) = .; \
|
||||
*(.ctors) \
|
||||
*(.init_array) \
|
||||
VMLINUX_SYMBOL(__ctors_end) = .;
|
||||
#else
|
||||
#define KERNEL_CTORS()
|
||||
|
@ -43,7 +43,7 @@ extern struct module __this_module;
|
||||
/* Mark the CRC weak since genksyms apparently decides not to
|
||||
* generate a checksums for some symbols */
|
||||
#define __CRC_SYMBOL(sym, sec) \
|
||||
extern void *__crc_##sym __attribute__((weak)); \
|
||||
extern __visible void *__crc_##sym __attribute__((weak)); \
|
||||
static const unsigned long __kcrctab_##sym \
|
||||
__used \
|
||||
__attribute__((section("___kcrctab" sec "+" #sym), unused)) \
|
||||
@ -59,7 +59,7 @@ extern struct module __this_module;
|
||||
static const char __kstrtab_##sym[] \
|
||||
__attribute__((section("__ksymtab_strings"), aligned(1))) \
|
||||
= VMLINUX_SYMBOL_STR(sym); \
|
||||
static const struct kernel_symbol __ksymtab_##sym \
|
||||
__visible const struct kernel_symbol __ksymtab_##sym \
|
||||
__used \
|
||||
__attribute__((section("___ksymtab" sec "+" #sym), unused)) \
|
||||
= { (unsigned long)&sym, __kstrtab_##sym }
|
||||
|
@ -367,9 +367,6 @@ struct module
|
||||
/* What modules do I depend on? */
|
||||
struct list_head target_list;
|
||||
|
||||
/* Who is waiting for us to be unloaded */
|
||||
struct task_struct *waiter;
|
||||
|
||||
/* Destruction function. */
|
||||
void (*exit)(void);
|
||||
|
||||
|
@ -131,6 +131,8 @@ char __initdata boot_command_line[COMMAND_LINE_SIZE];
|
||||
char *saved_command_line;
|
||||
/* Command line for parameter parsing */
|
||||
static char *static_command_line;
|
||||
/* Command line for per-initcall parameter parsing */
|
||||
static char *initcall_command_line;
|
||||
|
||||
static char *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)
|
||||
{
|
||||
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);
|
||||
strcpy (saved_command_line, boot_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[];
|
||||
initcall_t *fn;
|
||||
|
||||
strcpy(static_command_line, saved_command_line);
|
||||
strcpy(initcall_command_line, saved_command_line);
|
||||
parse_args(initcall_level_names[level],
|
||||
static_command_line, __start___param,
|
||||
initcall_command_line, __start___param,
|
||||
__stop___param - __start___param,
|
||||
level, level,
|
||||
&repair_env_string);
|
||||
|
@ -641,8 +641,6 @@ static int module_unload_init(struct module *mod)
|
||||
|
||||
/* Hold reference count during initialization. */
|
||||
__this_cpu_write(mod->refptr->incs, 1);
|
||||
/* Backwards compatibility macros put refcount during init. */
|
||||
mod->waiter = current;
|
||||
|
||||
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)
|
||||
{
|
||||
if (flags & O_NONBLOCK) {
|
||||
struct stopref sref = { mod, flags, forced };
|
||||
struct stopref sref = { mod, flags, forced };
|
||||
|
||||
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;
|
||||
}
|
||||
return stop_machine(__try_stop_module, &sref, NULL);
|
||||
}
|
||||
|
||||
unsigned long module_refcount(struct module *mod)
|
||||
@ -810,21 +801,6 @@ EXPORT_SYMBOL(module_refcount);
|
||||
/* This exists whether we can unload or not */
|
||||
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,
|
||||
unsigned int, flags)
|
||||
{
|
||||
@ -839,6 +815,11 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
|
||||
return -EFAULT;
|
||||
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)
|
||||
return -EINTR;
|
||||
|
||||
@ -856,8 +837,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
|
||||
|
||||
/* Doing init or already dying? */
|
||||
if (mod->state != MODULE_STATE_LIVE) {
|
||||
/* FIXME: if (force), slam module count and wake up
|
||||
waiter --RR */
|
||||
/* FIXME: if (force), slam module count damn the torpedoes */
|
||||
pr_debug("%s already dying\n", mod->name);
|
||||
ret = -EBUSY;
|
||||
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. */
|
||||
ret = try_stop_module(mod, flags, &forced);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
/* Never wait if forced. */
|
||||
if (!forced && module_refcount(mod) != 0)
|
||||
wait_for_zero_refcount(mod);
|
||||
|
||||
mutex_unlock(&module_mutex);
|
||||
/* Final destruction now no one is using it. */
|
||||
if (mod->exit != NULL)
|
||||
@ -1002,9 +975,6 @@ void module_put(struct module *module)
|
||||
__this_cpu_inc(module->refptr->decs);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -2728,7 +2698,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
|
||||
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",
|
||||
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
|
||||
mod->ctors = section_objs(info, ".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
|
||||
|
||||
#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",
|
||||
sizeof(*info->debug), &info->num_debug);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
* 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);
|
||||
if (err)
|
||||
|
@ -79,9 +79,11 @@ modpost = scripts/mod/modpost \
|
||||
$(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
|
||||
$(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.
|
||||
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
|
||||
__modpost: $(modules:.ko=.o) FORCE
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include "modpost.h"
|
||||
#include "../../include/generated/autoconf.h"
|
||||
#include "../../include/linux/license.h"
|
||||
@ -37,6 +38,8 @@ static int warn_unresolved = 0;
|
||||
/* How a symbol is exported */
|
||||
static int sec_mismatch_count = 0;
|
||||
static int sec_mismatch_verbose = 1;
|
||||
/* ignore missing files */
|
||||
static int ignore_missing_files;
|
||||
|
||||
enum export {
|
||||
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 kernel:1; /* 1 if symbol is from kernel
|
||||
* (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 */
|
||||
char name[0];
|
||||
};
|
||||
@ -329,8 +332,11 @@ static void sym_update_crc(const char *name, struct module *mod,
|
||||
{
|
||||
struct symbol *s = find_symbol(name);
|
||||
|
||||
if (!s)
|
||||
if (!s) {
|
||||
s = new_symbol(name, mod, export);
|
||||
/* Don't complain when we find it later. */
|
||||
s->preloaded = 1;
|
||||
}
|
||||
s->crc = crc;
|
||||
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);
|
||||
if (!hdr) {
|
||||
if (ignore_missing_files) {
|
||||
fprintf(stderr, "%s: %s (ignored)\n", filename,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
@ -1852,7 +1863,7 @@ static void add_header(struct buffer *b, struct module *mod)
|
||||
buf_printf(b, "\n");
|
||||
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\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, "\t.name = KBUILD_MODNAME,\n");
|
||||
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_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) {
|
||||
case 'i':
|
||||
kernel_read = optarg;
|
||||
@ -2138,6 +2149,9 @@ int main(int argc, char **argv)
|
||||
case 'm':
|
||||
modversions = 1;
|
||||
break;
|
||||
case 'n':
|
||||
ignore_missing_files = 1;
|
||||
break;
|
||||
case 'o':
|
||||
dump_write = optarg;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user