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

@ -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)