From: Rusty Russell <rusty@rustcorp.com.au>
To: torvalds@transmeta.com, akpm@zip.com.au
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] Bump module ref during init.
Date: Fri, 09 May 2003 18:40:01 +1000 [thread overview]
Message-ID: <20030509084045.792762C0F8@lists.samba.org> (raw)
At the moment, __module_get is technically allowed during module init,
because the module is being held in by its non-live state. But doing
so triggers the BUG(), so bump the refcount during init.
Also cleans up unload code a little, making it clearer.
Thanks,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
Name: Hold Initial Reference To Module
Author: Rusty Russell
Status: Tested on 2.5.69-bk3
D: __module_get is theoretically allowed on module inside init, since
D: we already hold an implicit reference. Currently this BUG()s: make
D: the reference count explicit, which also simplifies delete path.
D: Also cleans up unload path, such that it only drops semaphore when
D: it's actually sleeping for rmmod --wait.
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .7932-linux-2.5.69/kernel/module.c .7932-linux-2.5.69.updated/kernel/module.c
--- .7932-linux-2.5.69/kernel/module.c 2003-05-05 12:37:13.000000000 +1000
+++ .7932-linux-2.5.69.updated/kernel/module.c 2003-05-07 12:47:45.000000000 +1000
@@ -214,6 +214,8 @@ static void module_unload_init(struct mo
INIT_LIST_HEAD(&mod->modules_which_use_me);
for (i = 0; i < NR_CPUS; i++)
atomic_set(&mod->ref[i].count, 0);
+ /* Hold reference count during initialization. */
+ atomic_set(&mod->ref[smp_processor_id()].count, 1);
/* Backwards compatibility macros put refcount during init. */
mod->waiter = current;
}
@@ -462,6 +464,21 @@ void cleanup_module(void)
}
EXPORT_SYMBOL(cleanup_module);
+static void wait_for_zero_refcount(struct module *mod)
+{
+ /* Since we might sleep for some time, drop the semaphore first */
+ up(&module_mutex);
+ for (;;) {
+ DEBUGP("Looking at refcount...\n");
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (module_refcount(mod) == 0)
+ break;
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ down(&module_mutex);
+}
+
asmlinkage long
sys_delete_module(const char __user *name_user, unsigned int flags)
{
@@ -500,16 +517,6 @@ sys_delete_module(const char __user *nam
goto out;
}
- /* Coming up? Allow force on stuck modules. */
- if (mod->state == MODULE_STATE_COMING) {
- forced = try_force(flags);
- if (!forced) {
- /* This module can't be removed */
- ret = -EBUSY;
- goto out;
- }
- }
-
/* If it has an init func, it must have an exit func to unload */
if ((mod->init != init_module && mod->exit == cleanup_module)
|| mod->unsafe) {
@@ -529,35 +536,22 @@ sys_delete_module(const char __user *nam
/* If it's not unused, quit unless we are told to block. */
if ((flags & O_NONBLOCK) && module_refcount(mod) != 0) {
forced = try_force(flags);
- if (!forced)
+ if (!forced) {
ret = -EWOULDBLOCK;
- } else {
- mod->waiter = current;
- mod->state = MODULE_STATE_GOING;
+ restart_refcounts();
+ goto out;
+ }
}
- restart_refcounts();
-
- if (ret != 0)
- goto out;
-
- if (forced)
- goto destroy;
- /* Since we might sleep for some time, drop the semaphore first */
- up(&module_mutex);
- for (;;) {
- DEBUGP("Looking at refcount...\n");
- set_current_state(TASK_UNINTERRUPTIBLE);
- if (module_refcount(mod) == 0)
- break;
- schedule();
- }
- current->state = TASK_RUNNING;
+ /* Mark it as dying. */
+ mod->waiter = current;
+ mod->state = MODULE_STATE_GOING;
+ restart_refcounts();
- DEBUGP("Regrabbing mutex...\n");
- down(&module_mutex);
+ /* Never wait if forced. */
+ if (!forced && module_refcount(mod) != 0)
+ wait_for_zero_refcount(mod);
- destroy:
/* Final destruction now noone is using it. */
mod->exit();
free_module(mod);
@@ -1448,6 +1442,7 @@ sys_init_module(void __user *umod,
printk(KERN_ERR "%s: module is now stuck!\n",
mod->name);
else {
+ module_put(mod);
down(&module_mutex);
free_module(mod);
up(&module_mutex);
@@ -1458,6 +1453,8 @@ sys_init_module(void __user *umod,
/* Now it's a first class citizen! */
down(&module_mutex);
mod->state = MODULE_STATE_LIVE;
+ /* Drop initial reference. */
+ module_put(mod);
module_free(mod, mod->module_init);
mod->module_init = NULL;
mod->init_size = 0;
next reply other threads:[~2003-05-09 8:28 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-05-09 8:40 Rusty Russell [this message]
2003-05-09 8:54 ` Andrew Morton
2003-05-12 0:44 ` Rusty Russell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20030509084045.792762C0F8@lists.samba.org \
--to=rusty@rustcorp.com.au \
--cc=akpm@zip.com.au \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@transmeta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®