diff options
| -rw-r--r-- | include/linux/module.h | 4 | ||||
| -rw-r--r-- | kernel/module.c | 79 |
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 */ |
| 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) { |
