diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/kernel/module.c b/kernel/module.c index 9f8d23d8b3a8..1016b75b026a 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -521,11 +521,13 @@ static void module_unload_init(struct module *mod) | |||
521 | int cpu; | 521 | int cpu; |
522 | 522 | ||
523 | INIT_LIST_HEAD(&mod->modules_which_use_me); | 523 | INIT_LIST_HEAD(&mod->modules_which_use_me); |
524 | for_each_possible_cpu(cpu) | 524 | for_each_possible_cpu(cpu) { |
525 | per_cpu_ptr(mod->refptr, cpu)->count = 0; | 525 | per_cpu_ptr(mod->refptr, cpu)->incs = 0; |
526 | per_cpu_ptr(mod->refptr, cpu)->decs = 0; | ||
527 | } | ||
526 | 528 | ||
527 | /* Hold reference count during initialization. */ | 529 | /* Hold reference count during initialization. */ |
528 | __this_cpu_write(mod->refptr->count, 1); | 530 | __this_cpu_write(mod->refptr->incs, 1); |
529 | /* Backwards compatibility macros put refcount during init. */ | 531 | /* Backwards compatibility macros put refcount during init. */ |
530 | mod->waiter = current; | 532 | mod->waiter = current; |
531 | } | 533 | } |
@@ -664,12 +666,28 @@ static int try_stop_module(struct module *mod, int flags, int *forced) | |||
664 | 666 | ||
665 | unsigned int module_refcount(struct module *mod) | 667 | unsigned int module_refcount(struct module *mod) |
666 | { | 668 | { |
667 | unsigned int total = 0; | 669 | unsigned int incs = 0, decs = 0; |
668 | int cpu; | 670 | int cpu; |
669 | 671 | ||
670 | for_each_possible_cpu(cpu) | 672 | for_each_possible_cpu(cpu) |
671 | total += per_cpu_ptr(mod->refptr, cpu)->count; | 673 | decs += per_cpu_ptr(mod->refptr, cpu)->decs; |
672 | return total; | 674 | /* |
675 | * ensure the incs are added up after the decs. | ||
676 | * module_put ensures incs are visible before decs with smp_wmb. | ||
677 | * | ||
678 | * This 2-count scheme avoids the situation where the refcount | ||
679 | * for CPU0 is read, then CPU0 increments the module refcount, | ||
680 | * then CPU1 drops that refcount, then the refcount for CPU1 is | ||
681 | * read. We would record a decrement but not its corresponding | ||
682 | * increment so we would see a low count (disaster). | ||
683 | * | ||
684 | * Rare situation? But module_refcount can be preempted, and we | ||
685 | * might be tallying up 4096+ CPUs. So it is not impossible. | ||
686 | */ | ||
687 | smp_rmb(); | ||
688 | for_each_possible_cpu(cpu) | ||
689 | incs += per_cpu_ptr(mod->refptr, cpu)->incs; | ||
690 | return incs - decs; | ||
673 | } | 691 | } |
674 | EXPORT_SYMBOL(module_refcount); | 692 | EXPORT_SYMBOL(module_refcount); |
675 | 693 | ||
@@ -846,10 +864,11 @@ void module_put(struct module *module) | |||
846 | { | 864 | { |
847 | if (module) { | 865 | if (module) { |
848 | preempt_disable(); | 866 | preempt_disable(); |
849 | __this_cpu_dec(module->refptr->count); | 867 | smp_wmb(); /* see comment in module_refcount */ |
868 | __this_cpu_inc(module->refptr->decs); | ||
850 | 869 | ||
851 | trace_module_put(module, _RET_IP_, | 870 | trace_module_put(module, _RET_IP_, |
852 | __this_cpu_read(module->refptr->count)); | 871 | __this_cpu_read(module->refptr->decs)); |
853 | /* Maybe they're waiting for us to drop reference? */ | 872 | /* Maybe they're waiting for us to drop reference? */ |
854 | if (unlikely(!module_is_live(module))) | 873 | if (unlikely(!module_is_live(module))) |
855 | wake_up_process(module->waiter); | 874 | wake_up_process(module->waiter); |