[RFC][PATCH] make module refcounts use percpu_counters

From: Dave Hansen
Date: Fri Sep 28 2007 - 19:01:30 EST



Module refcounts currently use a percpu counter stored
in the 'struct module'. However, we also have a more
generic implementation that does stuff like handle
hotplug cpus.

I'm not actually all that convinced that this refcount
actually does a lot of good, with cpus racing bumping
the counters at the same time that they're being
summed up. But, it certainly isn't any worse than
what was there before. We also get any hotplug-cpu
compatible changes that happen to percpu_counters for
free.


Signed-off-by: Dave Hansen <haveblue@xxxxxxxxxx>
---

lxc-dave/include/linux/module.h | 10 ++++------
lxc-dave/kernel/module.c | 17 ++++-------------
2 files changed, 8 insertions(+), 19 deletions(-)

diff -puN lib/percpu_counter.c~make-module-refcounts-use-percpu_counters lib/percpu_counter.c
diff -puN include/linux/percpu_counter.h~make-module-refcounts-use-percpu_counters include/linux/percpu_counter.h
diff -puN kernel/module.c~make-module-refcounts-use-percpu_counters kernel/module.c
--- lxc/kernel/module.c~make-module-refcounts-use-percpu_counters 2007-09-28 15:48:57.000000000 -0700
+++ lxc-dave/kernel/module.c 2007-09-28 15:48:57.000000000 -0700
@@ -502,13 +502,9 @@ MODINFO_ATTR(srcversion);
/* Init the unload section of the module. */
static void module_unload_init(struct module *mod)
{
- unsigned int i;
-
INIT_LIST_HEAD(&mod->modules_which_use_me);
- for (i = 0; i < NR_CPUS; i++)
- local_set(&mod->ref[i].count, 0);
/* Hold reference count during initialization. */
- local_set(&mod->ref[raw_smp_processor_id()].count, 1);
+ percpu_counter_init(&mod->ref, 1);
/* Backwards compatibility macros put refcount during init. */
mod->waiter = current;
}
@@ -629,11 +625,7 @@ static int try_stop_module(struct module

unsigned int module_refcount(struct module *mod)
{
- unsigned int i, total = 0;
-
- for (i = 0; i < NR_CPUS; i++)
- total += local_read(&mod->ref[i].count);
- return total;
+ return percpu_counter_sum(&mod->ref);
}
EXPORT_SYMBOL(module_refcount);

@@ -720,6 +712,7 @@ sys_delete_module(const char __user *nam
/* Never wait if forced. */
if (!forced && module_refcount(mod) != 0)
wait_for_zero_refcount(mod);
+ percpu_counter_destroy(&mod->ref);

/* Final destruction now noone is using it. */
if (mod->exit != NULL) {
@@ -802,12 +795,10 @@ static struct module_attribute refcnt =
void module_put(struct module *module)
{
if (module) {
- unsigned int cpu = get_cpu();
- local_dec(&module->ref[cpu].count);
+ percpu_counter_dec(&module->ref);
/* Maybe they're waiting for us to drop reference? */
if (unlikely(!module_is_live(module)))
wake_up_process(module->waiter);
- put_cpu();
}
}
EXPORT_SYMBOL(module_put);
diff -puN include/asm-alpha/local.h~make-module-refcounts-use-percpu_counters include/asm-alpha/local.h
diff -puN include/asm-generic/local.h~make-module-refcounts-use-percpu_counters include/asm-generic/local.h
diff -puN include/asm-i386/local.h~make-module-refcounts-use-percpu_counters include/asm-i386/local.h
diff -puN include/asm-mips/local.h~make-module-refcounts-use-percpu_counters include/asm-mips/local.h
diff -puN include/asm-powerpc/local.h~make-module-refcounts-use-percpu_counters include/asm-powerpc/local.h
diff -puN fs/file_table.c~make-module-refcounts-use-percpu_counters fs/file_table.c
diff -puN include/linux/module.h~make-module-refcounts-use-percpu_counters include/linux/module.h
--- lxc/include/linux/module.h~make-module-refcounts-use-percpu_counters 2007-09-28 15:48:57.000000000 -0700
+++ lxc-dave/include/linux/module.h 2007-09-28 15:48:57.000000000 -0700
@@ -15,6 +15,7 @@
#include <linux/stringify.h>
#include <linux/kobject.h>
#include <linux/moduleparam.h>
+#include <linux/percpu_counter.h>
#include <asm/local.h>

#include <asm/module.h>
@@ -339,7 +340,7 @@ struct module

#ifdef CONFIG_MODULE_UNLOAD
/* Reference counts */
- struct module_ref ref[NR_CPUS];
+ struct percpu_counter ref;

/* What modules depend on me? */
struct list_head modules_which_use_me;
@@ -412,8 +413,7 @@ static inline void __module_get(struct m
{
if (module) {
BUG_ON(module_refcount(module) == 0);
- local_inc(&module->ref[get_cpu()].count);
- put_cpu();
+ percpu_counter_inc(&module->ref);
}
}

@@ -422,12 +422,10 @@ static inline int try_module_get(struct
int ret = 1;

if (module) {
- unsigned int cpu = get_cpu();
if (likely(module_is_live(module)))
- local_inc(&module->ref[cpu].count);
+ percpu_counter_inc(&module->ref);
else
ret = 0;
- put_cpu();
}
return ret;
}
_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/