diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 79 |
1 files changed, 48 insertions, 31 deletions
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 */ |
539 | struct module_use | 540 | struct 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 | */ | ||
569 | static 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 */ |
561 | int use_module(struct module *a, struct module *b) | 590 | int 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 | } |
594 | EXPORT_SYMBOL_GPL(use_module); | 617 | EXPORT_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. */ |
597 | static void module_unload_free(struct module *mod) | 620 | static 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) { |