Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5344876 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
  stop_machine: fix error code handling on multiple cpus
  stop_machine: use workqueues instead of kernel threads
  workqueue: introduce create_rt_workqueue
  Call init_workqueues before pre smp initcalls.
  Make panic= and panic_on_oops into core_params
  Make initcall_debug a core_param
  core_param() for genuinely core kernel parameters
  param: Fix duplicate module prefixes
  module: check kernel param length at compile time, not runtime
  Remove stop_machine during module load v2
  module: simplify load_module.
parents 296e1ce0 8163bcac
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@
#define MODULE_SYMBOL_PREFIX ""
#endif

#define MODULE_NAME_LEN (64 - sizeof(unsigned long))
#define MODULE_NAME_LEN MAX_PARAM_PREFIX_LEN

struct kernel_symbol
{
@@ -60,6 +60,7 @@ struct module_kobject
	struct kobject kobj;
	struct module *mod;
	struct kobject *drivers_dir;
	struct module_param_attrs *mp;
};

/* These are either module local, or the kernel's dummy ones. */
@@ -242,7 +243,6 @@ struct module

	/* Sysfs stuff. */
	struct module_kobject mkobj;
	struct module_param_attrs *param_attrs;
	struct module_attribute *modinfo_attrs;
	const char *version;
	const char *srcversion;
@@ -277,7 +277,7 @@ struct module

	/* Exception table */
	unsigned int num_exentries;
	const struct exception_table_entry *extable;
	struct exception_table_entry *extable;

	/* Startup function. */
	int (*init)(void);
+24 −1
Original line number Diff line number Diff line
@@ -13,6 +13,9 @@
#define MODULE_PARAM_PREFIX KBUILD_MODNAME "."
#endif

/* Chosen so that structs with an unsigned long line up. */
#define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long))

#ifdef MODULE
#define ___module_cat(a,b) __mod_ ## a ## b
#define __module_cat(a,b) ___module_cat(a,b)
@@ -79,7 +82,8 @@ struct kparam_array
#define __module_param_call(prefix, name, set, get, arg, perm)		\
	/* Default value instead of permissions? */			\
	static int __param_perm_check_##name __attribute__((unused)) =	\
	BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2));	\
	BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2))	\
	+ BUILD_BUG_ON_ZERO(sizeof(""prefix) > MAX_PARAM_PREFIX_LEN);	\
	static const char __param_str_##name[] = prefix #name;		\
	static struct kernel_param __moduleparam_const __param_##name	\
	__used								\
@@ -100,6 +104,25 @@ struct kparam_array
#define module_param(name, type, perm)				\
	module_param_named(name, name, type, perm)

#ifndef MODULE
/**
 * core_param - define a historical core kernel parameter.
 * @name: the name of the cmdline and sysfs parameter (often the same as var)
 * @var: the variable
 * @type: the type (for param_set_##type and param_get_##type)
 * @perm: visibility in sysfs
 *
 * core_param is just like module_param(), but cannot be modular and
 * doesn't add a prefix (such as "printk.").  This is for compatibility
 * with __setup(), and it makes sense as truly core parameters aren't
 * tied to the particular file they're in.
 */
#define core_param(name, var, type, perm)				\
	param_check_##type(name, &(var));				\
	__module_param_call("", name, param_set_##type, param_get_##type, \
			    &var, perm)
#endif /* !MODULE */

/* Actually copy string: maxlen param is usually sizeof(string). */
#define module_param_string(name, string, len, perm)			\
	static const struct kparam_string __param_string_##name		\
+10 −8
Original line number Diff line number Diff line
@@ -149,11 +149,11 @@ struct execute_work {

extern struct workqueue_struct *
__create_workqueue_key(const char *name, int singlethread,
		       int freezeable, struct lock_class_key *key,
		       int freezeable, int rt, struct lock_class_key *key,
		       const char *lock_name);

#ifdef CONFIG_LOCKDEP
#define __create_workqueue(name, singlethread, freezeable)	\
#define __create_workqueue(name, singlethread, freezeable, rt)	\
({								\
	static struct lock_class_key __key;			\
	const char *__lock_name;				\
@@ -164,17 +164,19 @@ __create_workqueue_key(const char *name, int singlethread,
		__lock_name = #name;				\
								\
	__create_workqueue_key((name), (singlethread),		\
			       (freezeable), &__key,		\
			       (freezeable), (rt), &__key,	\
			       __lock_name);			\
})
#else
#define __create_workqueue(name, singlethread, freezeable)	\
	__create_workqueue_key((name), (singlethread), (freezeable), NULL, NULL)
#define __create_workqueue(name, singlethread, freezeable, rt)	\
	__create_workqueue_key((name), (singlethread), (freezeable), (rt), \
			       NULL, NULL)
#endif

#define create_workqueue(name) __create_workqueue((name), 0, 0)
#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1)
#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0)
#define create_workqueue(name) __create_workqueue((name), 0, 0, 0)
#define create_rt_workqueue(name) __create_workqueue((name), 0, 0, 1)
#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1, 0)
#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0, 0)

extern void destroy_workqueue(struct workqueue_struct *wq);

+3 −9
Original line number Diff line number Diff line
@@ -699,13 +699,7 @@ asmlinkage void __init start_kernel(void)
}

static int initcall_debug;

static int __init initcall_debug_setup(char *str)
{
	initcall_debug = 1;
	return 1;
}
__setup("initcall_debug", initcall_debug_setup);
core_param(initcall_debug, initcall_debug, bool, 0644);

int do_one_initcall(initcall_t fn)
{
@@ -775,8 +769,6 @@ static void __init do_initcalls(void)
static void __init do_basic_setup(void)
{
	rcu_init_sched(); /* needed by module_init stage. */
	/* drivers will send hotplug events */
	init_workqueues();
	usermodehelper_init();
	driver_init();
	init_irq_proc();
@@ -860,6 +852,8 @@ static int __init kernel_init(void * unused)

	cad_pid = task_pid(current);

	init_workqueues();

	smp_prepare_cpus(setup_max_cpus);

	do_pre_smp_initcalls();
+122 −162
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/unwind.h>
#include <linux/rculist.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
#include <linux/license.h>
@@ -63,7 +64,7 @@
#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))

/* List of modules, protected by module_mutex or preempt_disable
 * (add/delete uses stop_machine). */
 * (delete uses stop_machine/add uses RCU list operations). */
static DEFINE_MUTEX(module_mutex);
static LIST_HEAD(modules);

@@ -132,6 +133,29 @@ static unsigned int find_sec(Elf_Ehdr *hdr,
	return 0;
}

/* Find a module section, or NULL. */
static void *section_addr(Elf_Ehdr *hdr, Elf_Shdr *shdrs,
			  const char *secstrings, const char *name)
{
	/* Section 0 has sh_addr 0. */
	return (void *)shdrs[find_sec(hdr, shdrs, secstrings, name)].sh_addr;
}

/* Find a module section, or NULL.  Fill in number of "objects" in section. */
static void *section_objs(Elf_Ehdr *hdr,
			  Elf_Shdr *sechdrs,
			  const char *secstrings,
			  const char *name,
			  size_t object_size,
			  unsigned int *num)
{
	unsigned int sec = find_sec(hdr, sechdrs, secstrings, name);

	/* Section 0 has sh_addr 0 and sh_size 0. */
	*num = sechdrs[sec].sh_size / object_size;
	return (void *)sechdrs[sec].sh_addr;
}

/* Provided by the linker */
extern const struct kernel_symbol __start___ksymtab[];
extern const struct kernel_symbol __stop___ksymtab[];
@@ -218,7 +242,7 @@ static bool each_symbol(bool (*fn)(const struct symsearch *arr,
	if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))
		return true;

	list_for_each_entry(mod, &modules, list) {
	list_for_each_entry_rcu(mod, &modules, list) {
		struct symsearch arr[] = {
			{ mod->syms, mod->syms + mod->num_syms, mod->crcs,
			  NOT_GPL_ONLY, false },
@@ -1393,17 +1417,6 @@ static void mod_kobject_remove(struct module *mod)
	mod_sysfs_fini(mod);
}

/*
 * link the module with the whole machine is stopped with interrupts off
 * - this defends against kallsyms not taking locks
 */
static int __link_module(void *_mod)
{
	struct module *mod = _mod;
	list_add(&mod->list, &modules);
	return 0;
}

/*
 * unlink the module with the whole machine is stopped with interrupts off
 * - this defends against kallsyms not taking locks
@@ -1789,32 +1802,20 @@ static inline void add_kallsyms(struct module *mod,
}
#endif /* CONFIG_KALLSYMS */

#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex)
static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num)
{
	struct mod_debug *debug_info;
	unsigned long pos, end;
	unsigned int num_verbose;

	pos = sechdrs[verboseindex].sh_addr;
	num_verbose = sechdrs[verboseindex].sh_size /
				sizeof(struct mod_debug);
	end = pos + (num_verbose * sizeof(struct mod_debug));
#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
	unsigned int i;

	for (; pos < end; pos += sizeof(struct mod_debug)) {
		debug_info = (struct mod_debug *)pos;
		register_dynamic_debug_module(debug_info->modname,
			debug_info->type, debug_info->logical_modname,
			debug_info->flag_names, debug_info->hash,
			debug_info->hash2);
	}
}
#else
static inline void dynamic_printk_setup(Elf_Shdr *sechdrs,
					unsigned int verboseindex)
{
	for (i = 0; i < num; i++) {
		register_dynamic_debug_module(debug[i].modname,
					      debug[i].type,
					      debug[i].logical_modname,
					      debug[i].flag_names,
					      debug[i].hash, debug[i].hash2);
	}
#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
}

static void *module_alloc_update_bounds(unsigned long size)
{
@@ -1843,37 +1844,14 @@ static noinline struct module *load_module(void __user *umod,
	unsigned int i;
	unsigned int symindex = 0;
	unsigned int strindex = 0;
	unsigned int setupindex;
	unsigned int exindex;
	unsigned int exportindex;
	unsigned int modindex;
	unsigned int obsparmindex;
	unsigned int infoindex;
	unsigned int gplindex;
	unsigned int crcindex;
	unsigned int gplcrcindex;
	unsigned int versindex;
	unsigned int pcpuindex;
	unsigned int gplfutureindex;
	unsigned int gplfuturecrcindex;
	unsigned int modindex, versindex, infoindex, pcpuindex;
	unsigned int unwindex = 0;
#ifdef CONFIG_UNUSED_SYMBOLS
	unsigned int unusedindex;
	unsigned int unusedcrcindex;
	unsigned int unusedgplindex;
	unsigned int unusedgplcrcindex;
#endif
	unsigned int markersindex;
	unsigned int markersstringsindex;
	unsigned int verboseindex;
	unsigned int tracepointsindex;
	unsigned int tracepointsstringsindex;
	unsigned int mcountindex;
	unsigned int num_kp, num_mcount;
	struct kernel_param *kp;
	struct module *mod;
	long err = 0;
	void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
	void *mseg;
	struct exception_table_entry *extable;
	unsigned long *mseg;
	mm_segment_t old_fs;

	DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
@@ -1937,6 +1915,7 @@ static noinline struct module *load_module(void __user *umod,
		err = -ENOEXEC;
		goto free_hdr;
	}
	/* This is temporary: point mod into copy of data. */
	mod = (void *)sechdrs[modindex].sh_addr;

	if (symindex == 0) {
@@ -1946,22 +1925,6 @@ static noinline struct module *load_module(void __user *umod,
		goto free_hdr;
	}

	/* 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");
#ifdef CONFIG_UNUSED_SYMBOLS
	unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
	unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
	unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused");
	unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl");
#endif
	setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
	exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
	obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
	versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
	infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
	pcpuindex = find_pcpusec(hdr, sechdrs, secstrings);
@@ -2117,42 +2080,57 @@ static noinline struct module *load_module(void __user *umod,
	if (err < 0)
		goto cleanup;

	/* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */
	mod->num_syms = sechdrs[exportindex].sh_size / sizeof(*mod->syms);
	mod->syms = (void *)sechdrs[exportindex].sh_addr;
	if (crcindex)
		mod->crcs = (void *)sechdrs[crcindex].sh_addr;
	mod->num_gpl_syms = sechdrs[gplindex].sh_size / sizeof(*mod->gpl_syms);
	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;
	/* Now we've got everything in the final locations, we can
	 * find optional sections. */
	kp = section_objs(hdr, sechdrs, secstrings, "__param", sizeof(*kp),
			  &num_kp);
	mod->syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab",
				 sizeof(*mod->syms), &mod->num_syms);
	mod->crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab");
	mod->gpl_syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab_gpl",
				     sizeof(*mod->gpl_syms),
				     &mod->num_gpl_syms);
	mod->gpl_crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab_gpl");
	mod->gpl_future_syms = section_objs(hdr, sechdrs, secstrings,
					    "__ksymtab_gpl_future",
					    sizeof(*mod->gpl_future_syms),
					    &mod->num_gpl_future_syms);
	mod->gpl_future_crcs = section_addr(hdr, sechdrs, secstrings,
					    "__kcrctab_gpl_future");

#ifdef CONFIG_UNUSED_SYMBOLS
	mod->num_unused_syms = sechdrs[unusedindex].sh_size /
					sizeof(*mod->unused_syms);
	mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
					sizeof(*mod->unused_gpl_syms);
	mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;
	if (unusedcrcindex)
		mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;
	mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr;
	if (unusedgplcrcindex)
		mod->unused_gpl_crcs
			= (void *)sechdrs[unusedgplcrcindex].sh_addr;
	mod->unused_syms = section_objs(hdr, sechdrs, secstrings,
					"__ksymtab_unused",
					sizeof(*mod->unused_syms),
					&mod->num_unused_syms);
	mod->unused_crcs = section_addr(hdr, sechdrs, secstrings,
					"__kcrctab_unused");
	mod->unused_gpl_syms = section_objs(hdr, sechdrs, secstrings,
					    "__ksymtab_unused_gpl",
					    sizeof(*mod->unused_gpl_syms),
					    &mod->num_unused_gpl_syms);
	mod->unused_gpl_crcs = section_addr(hdr, sechdrs, secstrings,
					    "__kcrctab_unused_gpl");
#endif

#ifdef CONFIG_MARKERS
	mod->markers = section_objs(hdr, sechdrs, secstrings, "__markers",
				    sizeof(*mod->markers), &mod->num_markers);
#endif
#ifdef CONFIG_TRACEPOINTS
	mod->tracepoints = section_objs(hdr, sechdrs, secstrings,
					"__tracepoints",
					sizeof(*mod->tracepoints),
					&mod->num_tracepoints);
#endif

#ifdef CONFIG_MODVERSIONS
	if ((mod->num_syms && !crcindex)
	    || (mod->num_gpl_syms && !gplcrcindex)
	    || (mod->num_gpl_future_syms && !gplfuturecrcindex)
	if ((mod->num_syms && !mod->crcs)
	    || (mod->num_gpl_syms && !mod->gpl_crcs)
	    || (mod->num_gpl_future_syms && !mod->gpl_future_crcs)
#ifdef CONFIG_UNUSED_SYMBOLS
	    || (mod->num_unused_syms && !unusedcrcindex)
	    || (mod->num_unused_gpl_syms && !unusedgplcrcindex)
	    || (mod->num_unused_syms && !mod->unused_crcs)
	    || (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs)
#endif
		) {
		printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name);
@@ -2161,16 +2139,6 @@ static noinline struct module *load_module(void __user *umod,
			goto cleanup;
	}
#endif
	markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
 	markersstringsindex = find_sec(hdr, sechdrs, secstrings,
					"__markers_strings");
	verboseindex = find_sec(hdr, sechdrs, secstrings, "__verbose");
	tracepointsindex = find_sec(hdr, sechdrs, secstrings, "__tracepoints");
	tracepointsstringsindex = find_sec(hdr, sechdrs, secstrings,
					"__tracepoints_strings");

	mcountindex = find_sec(hdr, sechdrs, secstrings,
			       "__mcount_loc");

	/* Now do relocations. */
	for (i = 1; i < hdr->e_shnum; i++) {
@@ -2193,28 +2161,16 @@ static noinline struct module *load_module(void __user *umod,
		if (err < 0)
			goto cleanup;
	}
#ifdef CONFIG_MARKERS
	mod->markers = (void *)sechdrs[markersindex].sh_addr;
	mod->num_markers =
		sechdrs[markersindex].sh_size / sizeof(*mod->markers);
#endif
#ifdef CONFIG_TRACEPOINTS
	mod->tracepoints = (void *)sechdrs[tracepointsindex].sh_addr;
	mod->num_tracepoints =
		sechdrs[tracepointsindex].sh_size / sizeof(*mod->tracepoints);
#endif


        /* Find duplicate symbols */
	err = verify_export_symbols(mod);

	if (err < 0)
		goto cleanup;

  	/* Set up and sort exception table */
	mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
	mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
	sort_extable(extable, extable + mod->num_exentries);
	mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table",
				    sizeof(*mod->extable), &mod->num_exentries);
	sort_extable(mod->extable, mod->extable + mod->num_exentries);

	/* Finally, copy percpu area over. */
	percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
@@ -2223,11 +2179,17 @@ static noinline struct module *load_module(void __user *umod,
	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);

	if (!mod->taints) {
		struct mod_debug *debug;
		unsigned int num_debug;

#ifdef CONFIG_MARKERS
		marker_update_probe_range(mod->markers,
			mod->markers + mod->num_markers);
#endif
	dynamic_printk_setup(sechdrs, verboseindex);
		debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
				     sizeof(*debug), &num_debug);
		dynamic_printk_setup(debug, num_debug);

#ifdef CONFIG_TRACEPOINTS
		tracepoint_update_probe_range(mod->tracepoints,
			mod->tracepoints + mod->num_tracepoints);
@@ -2235,8 +2197,9 @@ static noinline struct module *load_module(void __user *umod,
	}

	/* sechdrs[0].sh_size is always zero */
	mseg = (void *)sechdrs[mcountindex].sh_addr;
	ftrace_init_module(mseg, mseg + sechdrs[mcountindex].sh_size);
	mseg = section_objs(hdr, sechdrs, secstrings, "__mcount_loc",
			    sizeof(*mseg), &num_mcount);
	ftrace_init_module(mseg, mseg + num_mcount);

	err = module_finalize(hdr, sechdrs, mod);
	if (err < 0)
@@ -2261,30 +2224,24 @@ static noinline struct module *load_module(void __user *umod,
	set_fs(old_fs);

	mod->args = args;
	if (obsparmindex)
	if (section_addr(hdr, sechdrs, secstrings, "__obsparm"))
		printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
		       mod->name);

	/* Now sew it into the lists so we can get lockdep and oops
	 * info during argument parsing.  Noone should access us, since
         * strong_try_module_get() will fail. */
	stop_machine(__link_module, mod, NULL);

	/* Size of section 0 is 0, so this works well if no params */
	err = parse_args(mod->name, mod->args,
			 (struct kernel_param *)
			 sechdrs[setupindex].sh_addr,
			 sechdrs[setupindex].sh_size
			 / sizeof(struct kernel_param),
			 NULL);
	 * strong_try_module_get() will fail.
	 * lockdep/oops can run asynchronous, so use the RCU list insertion
	 * function to insert in a way safe to concurrent readers.
	 * The mutex protects against concurrent writers.
	 */
	list_add_rcu(&mod->list, &modules);

	err = parse_args(mod->name, mod->args, kp, num_kp, NULL);
	if (err < 0)
		goto unlink;

	err = mod_sysfs_setup(mod,
			      (struct kernel_param *)
			      sechdrs[setupindex].sh_addr,
			      sechdrs[setupindex].sh_size
			      / sizeof(struct kernel_param));
	err = mod_sysfs_setup(mod, kp, num_kp);
	if (err < 0)
		goto unlink;
	add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
@@ -2473,7 +2430,7 @@ const char *module_address_lookup(unsigned long addr,
	const char *ret = NULL;

	preempt_disable();
	list_for_each_entry(mod, &modules, list) {
	list_for_each_entry_rcu(mod, &modules, list) {
		if (within(addr, mod->module_init, mod->init_size)
		    || within(addr, mod->module_core, mod->core_size)) {
			if (modname)
@@ -2496,7 +2453,7 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)
	struct module *mod;

	preempt_disable();
	list_for_each_entry(mod, &modules, list) {
	list_for_each_entry_rcu(mod, &modules, list) {
		if (within(addr, mod->module_init, mod->init_size) ||
		    within(addr, mod->module_core, mod->core_size)) {
			const char *sym;
@@ -2520,7 +2477,7 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
	struct module *mod;

	preempt_disable();
	list_for_each_entry(mod, &modules, list) {
	list_for_each_entry_rcu(mod, &modules, list) {
		if (within(addr, mod->module_init, mod->init_size) ||
		    within(addr, mod->module_core, mod->core_size)) {
			const char *sym;
@@ -2547,7 +2504,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
	struct module *mod;

	preempt_disable();
	list_for_each_entry(mod, &modules, list) {
	list_for_each_entry_rcu(mod, &modules, list) {
		if (symnum < mod->num_symtab) {
			*value = mod->symtab[symnum].st_value;
			*type = mod->symtab[symnum].st_info;
@@ -2590,7 +2547,7 @@ unsigned long module_kallsyms_lookup_name(const char *name)
			ret = mod_find_symname(mod, colon+1);
		*colon = ':';
	} else {
		list_for_each_entry(mod, &modules, list)
		list_for_each_entry_rcu(mod, &modules, list)
			if ((ret = mod_find_symname(mod, name)) != 0)
				break;
	}
@@ -2693,7 +2650,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
	struct module *mod;

	preempt_disable();
	list_for_each_entry(mod, &modules, list) {
	list_for_each_entry_rcu(mod, &modules, list) {
		if (mod->num_exentries == 0)
			continue;

@@ -2719,7 +2676,7 @@ int is_module_address(unsigned long addr)

	preempt_disable();

	list_for_each_entry(mod, &modules, list) {
	list_for_each_entry_rcu(mod, &modules, list) {
		if (within(addr, mod->module_core, mod->core_size)) {
			preempt_enable();
			return 1;
@@ -2740,7 +2697,7 @@ struct module *__module_text_address(unsigned long addr)
	if (addr < module_addr_min || addr > module_addr_max)
		return NULL;

	list_for_each_entry(mod, &modules, list)
	list_for_each_entry_rcu(mod, &modules, list)
		if (within(addr, mod->module_init, mod->init_text_size)
		    || within(addr, mod->module_core, mod->core_text_size))
			return mod;
@@ -2765,8 +2722,11 @@ void print_modules(void)
	char buf[8];

	printk("Modules linked in:");
	list_for_each_entry(mod, &modules, list)
	/* Most callers should already have preempt disabled, but make sure */
	preempt_disable();
	list_for_each_entry_rcu(mod, &modules, list)
		printk(" %s%s", mod->name, module_flags(mod, buf));
	preempt_enable();
	if (last_unloaded_module[0])
		printk(" [last unloaded: %s]", last_unloaded_module);
	printk("\n");
Loading