aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-31 15:19:37 -0400
committerRusty Russell <rusty@rustcorp.com.au>2010-06-04 21:47:35 -0400
commit2c02dfe7fe3fba97a5665d329d039d2415ea5607 (patch)
tree7f50644bbfcc119cb85e21642a76eabfaf77b8ad
parentad8456361fa19068cf49b50a4f98e41b73c08e76 (diff)
module: Make the 'usage' lists be two-way
When adding a module that depends on another one, we used to create a one-way list of "modules_which_use_me", so that module unloading could see who needs a module. It's actually quite simple to make that list go both ways: so that we not only can see "who uses me", but also see a list of modules that are "used by me". In fact, we always wanted that list in "module_unload_free()": when we unload a module, we want to also release all the other modules that are used by that module. But because we didn't have that list, we used to first iterate over all modules, and then iterate over each "used by me" list of that module. By making the list two-way, we simplify module_unload_free(), and it allows for some trivial fixes later too. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (cleaned & rebased)
-rw-r--r--include/linux/module.h4
-rw-r--r--kernel/module.c79
2 files changed, 51 insertions, 32 deletions
diff --git a/include/linux/module.h b/include/linux/module.h
index 6914fcad4673..680db9e2ac36 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -359,7 +359,9 @@ struct module
359 359
360#ifdef CONFIG_MODULE_UNLOAD 360#ifdef CONFIG_MODULE_UNLOAD
361 /* What modules depend on me? */ 361 /* What modules depend on me? */
362 struct list_head modules_which_use_me; 362 struct list_head source_list;
363 /* What modules do I depend on? */
364 struct list_head target_list;
363 365
364 /* Who is waiting for us to be unloaded */ 366 /* Who is waiting for us to be unloaded */
365 struct task_struct *waiter; 367 struct task_struct *waiter;
diff --git a/kernel/module.c b/kernel/module.c
index 0129769301e3..be18c3e34684 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -523,7 +523,8 @@ static void module_unload_init(struct module *mod)
523{ 523{
524 int cpu; 524 int cpu;
525 525
526 INIT_LIST_HEAD(&mod->modules_which_use_me); 526 INIT_LIST_HEAD(&mod->source_list);
527 INIT_LIST_HEAD(&mod->target_list);
527 for_each_possible_cpu(cpu) { 528 for_each_possible_cpu(cpu) {
528 per_cpu_ptr(mod->refptr, cpu)->incs = 0; 529 per_cpu_ptr(mod->refptr, cpu)->incs = 0;
529 per_cpu_ptr(mod->refptr, cpu)->decs = 0; 530 per_cpu_ptr(mod->refptr, cpu)->decs = 0;
@@ -538,8 +539,9 @@ static void module_unload_init(struct module *mod)
538/* modules using other modules */ 539/* modules using other modules */
539struct module_use 540struct module_use
540{ 541{
541 struct list_head list; 542 struct list_head source_list;
542 struct module *module_which_uses; 543 struct list_head target_list;
544 struct module *source, *target;
543}; 545};
544 546
545/* Does a already use b? */ 547/* Does a already use b? */
@@ -547,8 +549,8 @@ static int already_uses(struct module *a, struct module *b)
547{ 549{
548 struct module_use *use; 550 struct module_use *use;
549 551
550 list_for_each_entry(use, &b->modules_which_use_me, list) { 552 list_for_each_entry(use, &b->source_list, source_list) {
551 if (use->module_which_uses == a) { 553 if (use->source == a) {
552 DEBUGP("%s uses %s!\n", a->name, b->name); 554 DEBUGP("%s uses %s!\n", a->name, b->name);
553 return 1; 555 return 1;
554 } 556 }
@@ -557,6 +559,33 @@ static int already_uses(struct module *a, struct module *b)
557 return 0; 559 return 0;
558} 560}
559 561
562/*
563 * Module a uses b
564 * - we add 'a' as a "source", 'b' as a "target" of module use
565 * - the module_use is added to the list of 'b' sources (so
566 * 'b' can walk the list to see who sourced them), and of 'a'
567 * targets (so 'a' can see what modules it targets).
568 */
569static int add_module_usage(struct module *a, struct module *b)
570{
571 int no_warn;
572 struct module_use *use;
573
574 DEBUGP("Allocating new usage for %s.\n", a->name);
575 use = kmalloc(sizeof(*use), GFP_ATOMIC);
576 if (!use) {
577 printk(KERN_WARNING "%s: out of memory loading\n", a->name);
578 return -ENOMEM;
579 }
580
581 use->source = a;
582 use->target = b;
583 list_add(&use->source_list, &b->source_list);
584 list_add(&use->target_list, &a->target_list);
585 no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
586 return 0;
587}
588
560/* Module a uses b */ 589/* Module a uses b */
561int use_module(struct module *a, struct module *b) 590int use_module(struct module *a, struct module *b)
562{ 591{
@@ -578,17 +607,11 @@ int use_module(struct module *a, struct module *b)
578 if (err) 607 if (err)
579 return 0; 608 return 0;
580 609
581 DEBUGP("Allocating new usage for %s.\n", a->name); 610 err = add_module_usage(a, b);
582 use = kmalloc(sizeof(*use), GFP_ATOMIC); 611 if (err) {
583 if (!use) {
584 printk("%s: out of memory loading\n", a->name);
585 module_put(b); 612 module_put(b);
586 return 0; 613 return 0;
587 } 614 }
588
589 use->module_which_uses = a;
590 list_add(&use->list, &b->modules_which_use_me);
591 no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
592 return 1; 615 return 1;
593} 616}
594EXPORT_SYMBOL_GPL(use_module); 617EXPORT_SYMBOL_GPL(use_module);
@@ -596,22 +619,16 @@ EXPORT_SYMBOL_GPL(use_module);
596/* Clear the unload stuff of the module. */ 619/* Clear the unload stuff of the module. */
597static void module_unload_free(struct module *mod) 620static void module_unload_free(struct module *mod)
598{ 621{
599 struct module *i; 622 struct module_use *use, *tmp;
600
601 list_for_each_entry(i, &modules, list) {
602 struct module_use *use;
603 623
604 list_for_each_entry(use, &i->modules_which_use_me, list) { 624 list_for_each_entry_safe(use, tmp, &mod->target_list, target_list) {
605 if (use->module_which_uses == mod) { 625 struct module *i = use->target;
606 DEBUGP("%s unusing %s\n", mod->name, i->name); 626 DEBUGP("%s unusing %s\n", mod->name, i->name);
607 module_put(i); 627 module_put(i);
608 list_del(&use->list); 628 list_del(&use->source_list);
609 kfree(use); 629 list_del(&use->target_list);
610 sysfs_remove_link(i->holders_dir, mod->name); 630 kfree(use);
611 /* There can be at most one match. */ 631 sysfs_remove_link(i->holders_dir, mod->name);
612 break;
613 }
614 }
615 } 632 }
616} 633}
617 634
@@ -735,7 +752,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
735 goto out; 752 goto out;
736 } 753 }
737 754
738 if (!list_empty(&mod->modules_which_use_me)) { 755 if (!list_empty(&mod->source_list)) {
739 /* Other modules depend on us: get rid of them first. */ 756 /* Other modules depend on us: get rid of them first. */
740 ret = -EWOULDBLOCK; 757 ret = -EWOULDBLOCK;
741 goto out; 758 goto out;
@@ -799,9 +816,9 @@ static inline void print_unload_info(struct seq_file *m, struct module *mod)
799 816
800 /* Always include a trailing , so userspace can differentiate 817 /* Always include a trailing , so userspace can differentiate
801 between this and the old multi-field proc format. */ 818 between this and the old multi-field proc format. */
802 list_for_each_entry(use, &mod->modules_which_use_me, list) { 819 list_for_each_entry(use, &mod->source_list, source_list) {
803 printed_something = 1; 820 printed_something = 1;
804 seq_printf(m, "%s,", use->module_which_uses->name); 821 seq_printf(m, "%s,", use->source->name);
805 } 822 }
806 823
807 if (mod->init != NULL && mod->exit == NULL) { 824 if (mod->init != NULL && mod->exit == NULL) {