/* Rewritten by Rusty Russell, on the backs of many others... Copyright (C) 2002 Richard Henderson Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <linux/config.h>#include <linux/module.h>#include <linux/moduleloader.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/elf.h>#include <linux/seq_file.h>#include <linux/syscalls.h>#include <linux/fcntl.h>#include <linux/rcupdate.h>#include <linux/cpu.h>#include <linux/moduleparam.h>#include <linux/errno.h>#include <linux/err.h>#include <linux/vermagic.h>#include <linux/notifier.h>#include <linux/stop_machine.h>#include <linux/device.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#include <asm/cacheflush.h> #if 0#define DEBUGP printk#else#define DEBUGP(fmt , a...)#endif #ifndef ARCH_SHF_SMALL#define ARCH_SHF_SMALL 0#endif /* If this is set, the section belongs in the init part of the module */#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) /* Protects module list */static DEFINE_SPINLOCK(modlist_lock); /* List of modules, protected by module_mutex AND modlist_lock */static DECLARE_MUTEX(module_mutex);static LIST_HEAD(modules); static DECLARE_MUTEX(notify_mutex);static struct notifier_block * module_notify_list; int register_module_notifier(struct notifier_block * nb){ int err; down(¬ify_mutex); err = notifier_chain_register(&module_notify_list, nb); up(¬ify_mutex); return err;}EXPORT_SYMBOL(register_module_notifier); int unregister_module_notifier(struct notifier_block * nb){ int err; down(¬ify_mutex); err = notifier_chain_unregister(&module_notify_list, nb); up(¬ify_mutex); return err;}EXPORT_SYMBOL(unregister_module_notifier); /* We require a truly strong try_module_get() */static inline int strong_try_module_get(struct module *mod){ if (mod && mod->state == MODULE_STATE_COMING) return 0; return try_module_get(mod);} /* A thread that wants to hold a reference to a module only while it * is running can call ths to safely exit. * nfsd and lockd use this. */void __module_put_and_exit(struct module *mod, long code){ module_put(mod); do_exit(code);}EXPORT_SYMBOL(__module_put_and_exit); /* Find a module section: 0 means not found. */static unsigned int find_sec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const char *secstrings, const char *name){ unsigned int i; for (i = 1; i < hdr->e_shnum; i++) /* Alloc bit cleared means "ignore it." */ if ((sechdrs[i].sh_flags & SHF_ALLOC) && strcmp(secstrings+sechdrs[i].sh_name, name) == 0) return i; return 0;} /* Provided by the linker */extern const struct kernel_symbol __start___ksymtab[];extern const struct kernel_symbol __stop___ksymtab[];extern const struct kernel_symbol __start___ksymtab_gpl[];extern const struct kernel_symbol __stop___ksymtab_gpl[];extern const unsigned long __start___kcrctab[];extern const unsigned long __start___kcrctab_gpl[]; #ifndef CONFIG_MODVERSIONS#define symversion(base, idx) NULL#else#define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL)#endif /* Find a symbol, return value, crc and module which owns it */static unsigned long __find_symbol(const char *name, struct module **owner, const unsigned long **crc, int gplok){ struct module *mod; unsigned int i; /* Core kernel first. */ *owner = NULL; for (i = 0; __start___ksymtab+i < __stop___ksymtab; i++) { if (strcmp(__start___ksymtab[i].name, name) == 0) { *crc = symversion(__start___kcrctab, i); return __start___ksymtab[i].value; } } if (gplok) { for (i = 0; __start___ksymtab_gpl+i<__stop___ksymtab_gpl; i++) if (strcmp(__start___ksymtab_gpl[i].name, name) == 0) { *crc = symversion(__start___kcrctab_gpl, i); return __start___ksymtab_gpl[i].value; } } /* Now try modules. */ list_for_each_entry(mod, &modules, list) { *owner = mod; for (i = 0; i < mod->num_syms; i++) if (strcmp(mod->syms[i].name, name) == 0) { *crc = symversion(mod->crcs, i); return mod->syms[i].value; } if (gplok) { for (i = 0; i < mod->num_gpl_syms; i++) { if (strcmp(mod->gpl_syms[i].name, name) == 0) { *crc = symversion(mod->gpl_crcs, i); return mod->gpl_syms[i].value; } } } } DEBUGP("Failed to find symbol %s\n", name); return 0;} /* Find a symbol in this elf symbol table */static unsigned long find_local_symbol(Elf_Shdr *sechdrs, unsigned int symindex, const char *strtab, const char *name){ unsigned int i; Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr; /* Search (defined) internal symbols first. */ for (i = 1; i < sechdrs[symindex].sh_size/sizeof(*sym); i++) { if (sym[i].st_shndx != SHN_UNDEF && strcmp(name, strtab + sym[i].st_name) == 0) return sym[i].st_value; } return 0;} /* Search for module by name: must hold module_mutex. */static struct module *find_module(const char *name){ struct module *mod; list_for_each_entry(mod, &modules, list) { if (strcmp(mod->name, name) == 0) return mod; } return NULL;} #ifdef CONFIG_SMP/* Number of blocks used and allocated. */static unsigned int pcpu_num_used, pcpu_num_allocated;/* Size of each block. -ve means used. */static int *pcpu_size; static int split_block(unsigned int i, unsigned short size){ /* Reallocation required? */ if (pcpu_num_used + 1 > pcpu_num_allocated) { int *new = kmalloc(sizeof(new[0]) * pcpu_num_allocated*2, GFP_KERNEL); if (!new) return 0; memcpy(new, pcpu_size, sizeof(new[0])*pcpu_num_allocated); pcpu_num_allocated *= 2; kfree(pcpu_size); pcpu_size = new; } /* Insert a new subblock */ memmove(&pcpu_size[i+1], &pcpu_size[i], sizeof(pcpu_size[0]) * (pcpu_num_used - i)); pcpu_num_used++; pcpu_size[i+1] -= size; pcpu_size[i] = size; return 1;} static inline unsigned int block_size(int val){ if (val < 0) return -val; return val;} /* Created by linker magic */extern char __per_cpu_start[], __per_cpu_end[]; static void *percpu_modalloc(unsigned long size, unsigned long align){ unsigned long extra; unsigned int i; void *ptr; BUG_ON(align > SMP_CACHE_BYTES); ptr = __per_cpu_start; for (i = 0; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { /* Extra for alignment requirement. */ extra = ALIGN((unsigned long)ptr, align) - (unsigned long)ptr; BUG_ON(i == 0 && extra != 0); if (pcpu_size[i] < 0 || pcpu_size[i] < extra + size) continue; /* Transfer extra to previous block. */ if (pcpu_size[i-1] < 0) pcpu_size[i-1] -= extra; else pcpu_size[i-1] += extra; pcpu_size[i] -= extra; ptr += extra; /* Split block if warranted */ if (pcpu_size[i] - size > sizeof(unsigned long)) if (!split_block(i, size)) return NULL; /* Mark allocated */ pcpu_size[i] = -pcpu_size[i]; return ptr; } printk(KERN_WARNING "Could not allocate %lu bytes percpu data\n", size); return NULL;} static void percpu_modfree(void *freeme){ unsigned int i; void *ptr = __per_cpu_start + block_size(pcpu_size[0]); /* First entry is core kernel percpu data. */ for (i = 1; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { if (ptr == freeme) { pcpu_size[i] = -pcpu_size[i]; goto free; } } BUG(); free: /* Merge with previous? */ if (pcpu_size[i-1] >= 0) { pcpu_size[i-1] += pcpu_size[i]; pcpu_num_used--; memmove(&pcpu_size[i], &pcpu_size[i+1], (pcpu_num_used - i) * sizeof(pcpu_size[0])); i--; } /* Merge with next? */ if (i+1 < pcpu_num_used && pcpu_size[i+1] >= 0) { pcpu_size[i] += pcpu_size[i+1]; pcpu_num_used--; memmove(&pcpu_size[i+1], &pcpu_size[i+2], (pcpu_num_used - (i+1)) * sizeof(pcpu_size[0])); }} static unsigned int find_pcpusec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const char *secstrings){ return find_sec(hdr, sechdrs, secstrings, ".data.percpu");} static int percpu_modinit(void){ pcpu_num_used = 2; pcpu_num_allocated = 2; pcpu_size = kmalloc(sizeof(pcpu_size[0]) * pcpu_num_allocated, GFP_KERNEL); /* Static in-kernel percpu data (used). */ pcpu_size[0] = -ALIGN(__per_cpu_end-__per_cpu_start, SMP_CACHE_BYTES); /* Free room. */ pcpu_size[1] = PERCPU_ENOUGH_ROOM + pcpu_size[0]; if (pcpu_size[1] < 0) { printk(KERN_ERR "No per-cpu room for modules.\n"); pcpu_num_used = 1; } return 0;} __initcall(percpu_modinit);#else /* ... !CONFIG_SMP */static inline void *percpu_modalloc(unsigned long size, unsigned long align){ return NULL;}static inline void percpu_modfree(void *pcpuptr){ BUG();}static inline unsigned int find_pcpusec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const char *secstrings){ return 0;}static inline void percpu_modcopy(void *pcpudst, const void *src, unsigned long size){ /* pcpusec should be 0, and size of that section should be 0. */ BUG_ON(size != 0);}#endif /* CONFIG_SMP */ #ifdef CONFIG_MODULE_UNLOAD/* 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[_smp_processor_id()].count, 1); /* Backwards compatibility macros put refcount during init. */ mod->waiter = current;} /* modules using other modules */struct module_use{ struct list_head list; struct module *module_which_uses;}; /* Does a already use b? */static int already_uses(struct module *a, struct module *b){ struct module_use *use; list_for_each_entry(use, &b->modules_which_use_me, list) { if (use->module_which_uses == a) { DEBUGP("%s uses %s!\n", a->name, b->name); return 1; } } DEBUGP("%s does not use %s!\n", a->name, b->name); return 0;} /* Module a uses b */static int use_module(struct module *a, struct module *b){ struct module_use *use; if (b == NULL || already_uses(a, b)) return 1; if (!strong_try_module_get(b)) return 0; DEBUGP("Allocating new usage for %s.\n", a->name); use = kmalloc(sizeof(*use), GFP_ATOMIC); if (!use) { printk("%s: out of memory loading\n", a->name); module_put(b); return 0; } use->module_which_uses = a; list_add(&use->list, &b->modules_which_use_me); return 1;} /* Clear the unload stuff of the module. */static void module_unload_free(struct module *mod){ struct module *i; list_for_each_entry(i, &modules, list) { struct module_use *use; list_for_each_entry(use, &i->modules_which_use_me, list) { if (use->module_which_uses == mod) { DEBUGP("%s unusing %s\n", mod->name, i->name); module_put(i); list_del(&use->list); kfree(use); /* There can be at most one match. */ break; } } }} #ifdef CONFIG_MODULE_FORCE_UNLOADstatic inline int try_force(unsigned int flags){ int ret = (flags & O_TRUNC); if (ret) tainted |= TAINT_FORCED_MODULE; return ret;}#elsestatic inline int try_force(unsigned int flags){ return 0;}#endif /* CONFIG_MODULE_FORCE_UNLOAD */ struct stopref{ struct module *mod; int flags; int *forced;}; /* Whole machine is stopped with interrupts off when this runs. */static int __try_stop_module(void *_sref){ struct stopref *sref = _sref; /* If it's not unused, quit unless we are told to block. */ if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) { if (!(*sref->forced = try_force(sref->flags))) return -EWOULDBLOCK; } /* Mark it as dying. */ sref->mod->state = MODULE_STATE_GOING; return 0;} static int try_stop_module(struct module *mod, int flags, int *forced){ struct stopref sref = { mod, flags, forced }; return stop_machine_run(__try_stop_module, &sref, NR_CPUS);} unsigned int module_refcount(struct module *mod){ unsigned int i, total = 0; Lines 1–500 of 2108. Load more
/* Rewritten by Rusty Russell, on the backs of many others... Copyright (C) 2002 Richard Henderson Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/config.h> #include <linux/module.h> #include <linux/moduleloader.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/elf.h> #include <linux/seq_file.h> #include <linux/syscalls.h> #include <linux/fcntl.h> #include <linux/rcupdate.h> #include <linux/cpu.h> #include <linux/moduleparam.h> #include <linux/errno.h> #include <linux/err.h> #include <linux/vermagic.h> #include <linux/notifier.h> #include <linux/stop_machine.h> #include <linux/device.h> #include <asm/uaccess.h> #include <asm/semaphore.h> #include <asm/cacheflush.h> #if 0 #define DEBUGP printk #else #define DEBUGP(fmt , a...) #endif #ifndef ARCH_SHF_SMALL #define ARCH_SHF_SMALL 0 #endif /* If this is set, the section belongs in the init part of the module */ #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) /* Protects module list */ static DEFINE_SPINLOCK(modlist_lock); /* List of modules, protected by module_mutex AND modlist_lock */ static DECLARE_MUTEX(module_mutex); static LIST_HEAD(modules); static DECLARE_MUTEX(notify_mutex); static struct notifier_block * module_notify_list; int register_module_notifier(struct notifier_block * nb) { int err; down(¬ify_mutex); err = notifier_chain_register(&module_notify_list, nb); up(¬ify_mutex); return err; } EXPORT_SYMBOL(register_module_notifier); int unregister_module_notifier(struct notifier_block * nb) { int err; down(¬ify_mutex); err = notifier_chain_unregister(&module_notify_list, nb); up(¬ify_mutex); return err; } EXPORT_SYMBOL(unregister_module_notifier); /* We require a truly strong try_module_get() */ static inline int strong_try_module_get(struct module *mod) { if (mod && mod->state == MODULE_STATE_COMING) return 0; return try_module_get(mod); } /* A thread that wants to hold a reference to a module only while it * is running can call ths to safely exit. * nfsd and lockd use this. */ void __module_put_and_exit(struct module *mod, long code) { module_put(mod); do_exit(code); } EXPORT_SYMBOL(__module_put_and_exit); /* Find a module section: 0 means not found. */ static unsigned int find_sec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const char *secstrings, const char *name) { unsigned int i; for (i = 1; i < hdr->e_shnum; i++) /* Alloc bit cleared means "ignore it." */ if ((sechdrs[i].sh_flags & SHF_ALLOC) && strcmp(secstrings+sechdrs[i].sh_name, name) == 0) return i; return 0; } /* Provided by the linker */ extern const struct kernel_symbol __start___ksymtab[]; extern const struct kernel_symbol __stop___ksymtab[]; extern const struct kernel_symbol __start___ksymtab_gpl[]; extern const struct kernel_symbol __stop___ksymtab_gpl[]; extern const unsigned long __start___kcrctab[]; extern const unsigned long __start___kcrctab_gpl[]; #ifndef CONFIG_MODVERSIONS #define symversion(base, idx) NULL #else #define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL) #endif /* Find a symbol, return value, crc and module which owns it */ static unsigned long __find_symbol(const char *name, struct module **owner, const unsigned long **crc, int gplok) { struct module *mod; unsigned int i; /* Core kernel first. */ *owner = NULL; for (i = 0; __start___ksymtab+i < __stop___ksymtab; i++) { if (strcmp(__start___ksymtab[i].name, name) == 0) { *crc = symversion(__start___kcrctab, i); return __start___ksymtab[i].value; } } if (gplok) { for (i = 0; __start___ksymtab_gpl+i<__stop___ksymtab_gpl; i++) if (strcmp(__start___ksymtab_gpl[i].name, name) == 0) { *crc = symversion(__start___kcrctab_gpl, i); return __start___ksymtab_gpl[i].value; } } /* Now try modules. */ list_for_each_entry(mod, &modules, list) { *owner = mod; for (i = 0; i < mod->num_syms; i++) if (strcmp(mod->syms[i].name, name) == 0) { *crc = symversion(mod->crcs, i); return mod->syms[i].value; } if (gplok) { for (i = 0; i < mod->num_gpl_syms; i++) { if (strcmp(mod->gpl_syms[i].name, name) == 0) { *crc = symversion(mod->gpl_crcs, i); return mod->gpl_syms[i].value; } } } } DEBUGP("Failed to find symbol %s\n", name); return 0; } /* Find a symbol in this elf symbol table */ static unsigned long find_local_symbol(Elf_Shdr *sechdrs, unsigned int symindex, const char *strtab, const char *name) { unsigned int i; Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr; /* Search (defined) internal symbols first. */ for (i = 1; i < sechdrs[symindex].sh_size/sizeof(*sym); i++) { if (sym[i].st_shndx != SHN_UNDEF && strcmp(name, strtab + sym[i].st_name) == 0) return sym[i].st_value; } return 0; } /* Search for module by name: must hold module_mutex. */ static struct module *find_module(const char *name) { struct module *mod; list_for_each_entry(mod, &modules, list) { if (strcmp(mod->name, name) == 0) return mod; } return NULL; } #ifdef CONFIG_SMP /* Number of blocks used and allocated. */ static unsigned int pcpu_num_used, pcpu_num_allocated; /* Size of each block. -ve means used. */ static int *pcpu_size; static int split_block(unsigned int i, unsigned short size) { /* Reallocation required? */ if (pcpu_num_used + 1 > pcpu_num_allocated) { int *new = kmalloc(sizeof(new[0]) * pcpu_num_allocated*2, GFP_KERNEL); if (!new) return 0; memcpy(new, pcpu_size, sizeof(new[0])*pcpu_num_allocated); pcpu_num_allocated *= 2; kfree(pcpu_size); pcpu_size = new; } /* Insert a new subblock */ memmove(&pcpu_size[i+1], &pcpu_size[i], sizeof(pcpu_size[0]) * (pcpu_num_used - i)); pcpu_num_used++; pcpu_size[i+1] -= size; pcpu_size[i] = size; return 1; } static inline unsigned int block_size(int val) { if (val < 0) return -val; return val; } /* Created by linker magic */ extern char __per_cpu_start[], __per_cpu_end[]; static void *percpu_modalloc(unsigned long size, unsigned long align) { unsigned long extra; unsigned int i; void *ptr; BUG_ON(align > SMP_CACHE_BYTES); ptr = __per_cpu_start; for (i = 0; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { /* Extra for alignment requirement. */ extra = ALIGN((unsigned long)ptr, align) - (unsigned long)ptr; BUG_ON(i == 0 && extra != 0); if (pcpu_size[i] < 0 || pcpu_size[i] < extra + size) continue; /* Transfer extra to previous block. */ if (pcpu_size[i-1] < 0) pcpu_size[i-1] -= extra; else pcpu_size[i-1] += extra; pcpu_size[i] -= extra; ptr += extra; /* Split block if warranted */ if (pcpu_size[i] - size > sizeof(unsigned long)) if (!split_block(i, size)) return NULL; /* Mark allocated */ pcpu_size[i] = -pcpu_size[i]; return ptr; } printk(KERN_WARNING "Could not allocate %lu bytes percpu data\n", size); return NULL; } static void percpu_modfree(void *freeme) { unsigned int i; void *ptr = __per_cpu_start + block_size(pcpu_size[0]); /* First entry is core kernel percpu data. */ for (i = 1; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { if (ptr == freeme) { pcpu_size[i] = -pcpu_size[i]; goto free; } } BUG(); free: /* Merge with previous? */ if (pcpu_size[i-1] >= 0) { pcpu_size[i-1] += pcpu_size[i]; pcpu_num_used--; memmove(&pcpu_size[i], &pcpu_size[i+1], (pcpu_num_used - i) * sizeof(pcpu_size[0])); i--; } /* Merge with next? */ if (i+1 < pcpu_num_used && pcpu_size[i+1] >= 0) { pcpu_size[i] += pcpu_size[i+1]; pcpu_num_used--; memmove(&pcpu_size[i+1], &pcpu_size[i+2], (pcpu_num_used - (i+1)) * sizeof(pcpu_size[0])); } } static unsigned int find_pcpusec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const char *secstrings) { return find_sec(hdr, sechdrs, secstrings, ".data.percpu"); } static int percpu_modinit(void) { pcpu_num_used = 2; pcpu_num_allocated = 2; pcpu_size = kmalloc(sizeof(pcpu_size[0]) * pcpu_num_allocated, GFP_KERNEL); /* Static in-kernel percpu data (used). */ pcpu_size[0] = -ALIGN(__per_cpu_end-__per_cpu_start, SMP_CACHE_BYTES); /* Free room. */ pcpu_size[1] = PERCPU_ENOUGH_ROOM + pcpu_size[0]; if (pcpu_size[1] < 0) { printk(KERN_ERR "No per-cpu room for modules.\n"); pcpu_num_used = 1; } return 0; } __initcall(percpu_modinit); #else /* ... !CONFIG_SMP */ static inline void *percpu_modalloc(unsigned long size, unsigned long align) { return NULL; } static inline void percpu_modfree(void *pcpuptr) { BUG(); } static inline unsigned int find_pcpusec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const char *secstrings) { return 0; } static inline void percpu_modcopy(void *pcpudst, const void *src, unsigned long size) { /* pcpusec should be 0, and size of that section should be 0. */ BUG_ON(size != 0); } #endif /* CONFIG_SMP */ #ifdef CONFIG_MODULE_UNLOAD /* 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[_smp_processor_id()].count, 1); /* Backwards compatibility macros put refcount during init. */ mod->waiter = current; } /* modules using other modules */ struct module_use { struct list_head list; struct module *module_which_uses; }; /* Does a already use b? */ static int already_uses(struct module *a, struct module *b) { struct module_use *use; list_for_each_entry(use, &b->modules_which_use_me, list) { if (use->module_which_uses == a) { DEBUGP("%s uses %s!\n", a->name, b->name); return 1; } } DEBUGP("%s does not use %s!\n", a->name, b->name); return 0; } /* Module a uses b */ static int use_module(struct module *a, struct module *b) { struct module_use *use; if (b == NULL || already_uses(a, b)) return 1; if (!strong_try_module_get(b)) return 0; DEBUGP("Allocating new usage for %s.\n", a->name); use = kmalloc(sizeof(*use), GFP_ATOMIC); if (!use) { printk("%s: out of memory loading\n", a->name); module_put(b); return 0; } use->module_which_uses = a; list_add(&use->list, &b->modules_which_use_me); return 1; } /* Clear the unload stuff of the module. */ static void module_unload_free(struct module *mod) { struct module *i; list_for_each_entry(i, &modules, list) { struct module_use *use; list_for_each_entry(use, &i->modules_which_use_me, list) { if (use->module_which_uses == mod) { DEBUGP("%s unusing %s\n", mod->name, i->name); module_put(i); list_del(&use->list); kfree(use); /* There can be at most one match. */ break; } } } } #ifdef CONFIG_MODULE_FORCE_UNLOAD static inline int try_force(unsigned int flags) { int ret = (flags & O_TRUNC); if (ret) tainted |= TAINT_FORCED_MODULE; return ret; } #else static inline int try_force(unsigned int flags) { return 0; } #endif /* CONFIG_MODULE_FORCE_UNLOAD */ struct stopref { struct module *mod; int flags; int *forced; }; /* Whole machine is stopped with interrupts off when this runs. */ static int __try_stop_module(void *_sref) { struct stopref *sref = _sref; /* If it's not unused, quit unless we are told to block. */ if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) { if (!(*sref->forced = try_force(sref->flags))) return -EWOULDBLOCK; } /* Mark it as dying. */ sref->mod->state = MODULE_STATE_GOING; return 0; } static int try_stop_module(struct module *mod, int flags, int *forced) { struct stopref sref = { mod, flags, forced }; return stop_machine_run(__try_stop_module, &sref, NR_CPUS); } unsigned int module_refcount(struct module *mod) { unsigned int i, total = 0;