Commit bd77c047 authored by Eric Dumazet's avatar Eric Dumazet Committed by Rusty Russell

module: struct module_ref should contains long fields

module_ref contains two "unsigned int" fields.

Thats now too small, since some machines can open more than 2^32 files.

Check commit 518de9b3 (fs: allow for more than 2^31 files) for
reference.

We can add an aligned(2 * sizeof(unsigned long)) attribute to force
alloc_percpu() allocating module_ref areas in single cache lines.
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: Tejun Heo <tj@kernel.org>
CC: Robin Holt <holt@sgi.com>
CC: David Miller <davem@davemloft.net>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 48fd1188
...@@ -205,6 +205,20 @@ enum module_state ...@@ -205,6 +205,20 @@ enum module_state
MODULE_STATE_GOING, MODULE_STATE_GOING,
}; };
/**
* struct module_ref - per cpu module reference counts
* @incs: number of module get on this cpu
* @decs: number of module put on this cpu
*
* We force an alignment on 8 or 16 bytes, so that alloc_percpu()
* put @incs/@decs in same cache line, with no extra memory cost,
* since alloc_percpu() is fine grained.
*/
struct module_ref {
unsigned long incs;
unsigned long decs;
} __attribute((aligned(2 * sizeof(unsigned long))));
struct module struct module
{ {
enum module_state state; enum module_state state;
...@@ -347,10 +361,7 @@ struct module ...@@ -347,10 +361,7 @@ struct module
/* Destruction function. */ /* Destruction function. */
void (*exit)(void); void (*exit)(void);
struct module_ref { struct module_ref __percpu *refptr;
unsigned int incs;
unsigned int decs;
} __percpu *refptr;
#endif #endif
#ifdef CONFIG_CONSTRUCTORS #ifdef CONFIG_CONSTRUCTORS
...@@ -434,7 +445,7 @@ extern void __module_put_and_exit(struct module *mod, long code) ...@@ -434,7 +445,7 @@ extern void __module_put_and_exit(struct module *mod, long code)
#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code); #define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
#ifdef CONFIG_MODULE_UNLOAD #ifdef CONFIG_MODULE_UNLOAD
unsigned int module_refcount(struct module *mod); unsigned long module_refcount(struct module *mod);
void __symbol_put(const char *symbol); void __symbol_put(const char *symbol);
#define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x) #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x)
void symbol_put_addr(void *addr); void symbol_put_addr(void *addr);
......
...@@ -1982,7 +1982,7 @@ static int kdb_lsmod(int argc, const char **argv) ...@@ -1982,7 +1982,7 @@ static int kdb_lsmod(int argc, const char **argv)
kdb_printf("%-20s%8u 0x%p ", mod->name, kdb_printf("%-20s%8u 0x%p ", mod->name,
mod->core_size, (void *)mod); mod->core_size, (void *)mod);
#ifdef CONFIG_MODULE_UNLOAD #ifdef CONFIG_MODULE_UNLOAD
kdb_printf("%4d ", module_refcount(mod)); kdb_printf("%4ld ", module_refcount(mod));
#endif #endif
if (mod->state == MODULE_STATE_GOING) if (mod->state == MODULE_STATE_GOING)
kdb_printf(" (Unloading)"); kdb_printf(" (Unloading)");
......
...@@ -725,9 +725,9 @@ static int try_stop_module(struct module *mod, int flags, int *forced) ...@@ -725,9 +725,9 @@ static int try_stop_module(struct module *mod, int flags, int *forced)
} }
} }
unsigned int module_refcount(struct module *mod) unsigned long module_refcount(struct module *mod)
{ {
unsigned int incs = 0, decs = 0; unsigned long incs = 0, decs = 0;
int cpu; int cpu;
for_each_possible_cpu(cpu) for_each_possible_cpu(cpu)
...@@ -853,7 +853,7 @@ static inline void print_unload_info(struct seq_file *m, struct module *mod) ...@@ -853,7 +853,7 @@ static inline void print_unload_info(struct seq_file *m, struct module *mod)
struct module_use *use; struct module_use *use;
int printed_something = 0; int printed_something = 0;
seq_printf(m, " %u ", module_refcount(mod)); seq_printf(m, " %lu ", module_refcount(mod));
/* Always include a trailing , so userspace can differentiate /* Always include a trailing , so userspace can differentiate
between this and the old multi-field proc format. */ between this and the old multi-field proc format. */
...@@ -903,7 +903,7 @@ EXPORT_SYMBOL_GPL(symbol_put_addr); ...@@ -903,7 +903,7 @@ EXPORT_SYMBOL_GPL(symbol_put_addr);
static ssize_t show_refcnt(struct module_attribute *mattr, static ssize_t show_refcnt(struct module_attribute *mattr,
struct module_kobject *mk, char *buffer) struct module_kobject *mk, char *buffer)
{ {
return sprintf(buffer, "%u\n", module_refcount(mk->mod)); return sprintf(buffer, "%lu\n", module_refcount(mk->mod));
} }
static struct module_attribute refcnt = { static struct module_attribute refcnt = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment