Skip to content

Commit

Permalink
module: wait for dependent modules doing init.
Browse files Browse the repository at this point in the history
There have been reports of modules failing to load because the modules
they depend on are still loading.  This changes the modules to wait
for a reasonable length of time in that case.  We time out eventually,
because there can be module loops or broken modules.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
Rusty Russell committed Jan 29, 2008
1 parent a2da405 commit c9a3ba5
Showing 1 changed file with 23 additions and 5 deletions.
28 changes: 23 additions & 5 deletions kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
static DEFINE_MUTEX(module_mutex);
static LIST_HEAD(modules);

/* Waiting for a module to finish initializing? */
static DECLARE_WAIT_QUEUE_HEAD(module_wq);

static BLOCKING_NOTIFIER_HEAD(module_notify_list);

int register_module_notifier(struct notifier_block * nb)
Expand All @@ -84,8 +87,11 @@ EXPORT_SYMBOL(unregister_module_notifier);
static inline int strong_try_module_get(struct module *mod)
{
if (mod && mod->state == MODULE_STATE_COMING)
return -EBUSY;
if (try_module_get(mod))
return 0;
return try_module_get(mod);
else
return -ENOENT;
}

static inline void add_taint_module(struct module *mod, unsigned flag)
Expand Down Expand Up @@ -539,11 +545,21 @@ static int already_uses(struct module *a, struct module *b)
static int use_module(struct module *a, struct module *b)
{
struct module_use *use;
int no_warn;
int no_warn, err;

if (b == NULL || already_uses(a, b)) return 1;

if (!strong_try_module_get(b))
/* If we're interrupted or time out, we fail. */
if (wait_event_interruptible_timeout(
module_wq, (err = strong_try_module_get(b)) != -EBUSY,
30 * HZ) <= 0) {
printk("%s: gave up waiting for init of module %s.\n",
a->name, b->name);
return 0;
}

/* If strong_try_module_get() returned a different error, we fail. */
if (err)
return 0;

DEBUGP("Allocating new usage for %s.\n", a->name);
Expand Down Expand Up @@ -816,7 +832,7 @@ static inline void module_unload_free(struct module *mod)

static inline int use_module(struct module *a, struct module *b)
{
return strong_try_module_get(b);
return strong_try_module_get(b) == 0;
}

static inline void module_unload_init(struct module *mod)
Expand Down Expand Up @@ -1326,7 +1342,7 @@ void *__symbol_get(const char *symbol)

preempt_disable();
value = __find_symbol(symbol, &owner, &crc, 1);
if (value && !strong_try_module_get(owner))
if (value && strong_try_module_get(owner) != 0)
value = 0;
preempt_enable();

Expand Down Expand Up @@ -2132,6 +2148,7 @@ sys_init_module(void __user *umod,
mutex_lock(&module_mutex);
free_module(mod);
mutex_unlock(&module_mutex);
wake_up(&module_wq);
return ret;
}

Expand All @@ -2146,6 +2163,7 @@ sys_init_module(void __user *umod,
mod->init_size = 0;
mod->init_text_size = 0;
mutex_unlock(&module_mutex);
wake_up(&module_wq);

return 0;
}
Expand Down

0 comments on commit c9a3ba5

Please sign in to comment.