]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/module.c
module: don't use stop_machine for waiting rmmod
[linux-2.6-omap-h63xx.git] / kernel / module.c
index 8e4528c9909feab87fe000ea56beb3d69fc26819..705e1d5d516cc54b1056003737407af9c7090447 100644 (file)
@@ -639,8 +639,8 @@ 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 it's not unused, quit unless we're forcing. */
+       if (module_refcount(sref->mod) != 0) {
                if (!(*sref->forced = try_force_unload(sref->flags)))
                        return -EWOULDBLOCK;
        }
@@ -652,9 +652,16 @@ static int __try_stop_module(void *_sref)
 
 static int try_stop_module(struct module *mod, int flags, int *forced)
 {
-       struct stopref sref = { mod, flags, forced };
+       if (flags & O_NONBLOCK) {
+               struct stopref sref = { mod, flags, forced };
 
-       return stop_machine_run(__try_stop_module, &sref, NR_CPUS);
+               return stop_machine_run(__try_stop_module, &sref, NR_CPUS);
+       } else {
+               /* We don't need to stop the machine for this. */
+               mod->state = MODULE_STATE_GOING;
+               synchronize_sched();
+               return 0;
+       }
 }
 
 unsigned int module_refcount(struct module *mod)
@@ -917,6 +924,10 @@ static int check_version(Elf_Shdr *sechdrs,
        if (!crc)
                return 1;
 
+       /* No versions at all?  modprobe --force does this. */
+       if (versindex == 0)
+               return try_to_force_load(mod, symname) == 0;
+
        versions = (void *) sechdrs[versindex].sh_addr;
        num_versions = sechdrs[versindex].sh_size
                / sizeof(struct modversion_info);
@@ -932,8 +943,9 @@ static int check_version(Elf_Shdr *sechdrs,
                goto bad_version;
        }
 
-       if (!try_to_force_load(mod, symname))
-               return 1;
+       printk(KERN_WARNING "%s: no symbol version for %s\n",
+              mod->name, symname);
+       return 0;
 
 bad_version:
        printk("%s: disagrees about version of symbol %s\n",
@@ -952,11 +964,14 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
        return check_version(sechdrs, versindex, "struct_module", mod, crc);
 }
 
-/* First part is kernel version, which we ignore. */
-static inline int same_magic(const char *amagic, const char *bmagic)
+/* First part is kernel version, which we ignore if module has crcs. */
+static inline int same_magic(const char *amagic, const char *bmagic,
+                            bool has_crcs)
 {
-       amagic += strcspn(amagic, " ");
-       bmagic += strcspn(bmagic, " ");
+       if (has_crcs) {
+               amagic += strcspn(amagic, " ");
+               bmagic += strcspn(bmagic, " ");
+       }
        return strcmp(amagic, bmagic) == 0;
 }
 #else
@@ -976,7 +991,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
        return 1;
 }
 
-static inline int same_magic(const char *amagic, const char *bmagic)
+static inline int same_magic(const char *amagic, const char *bmagic,
+                            bool has_crcs)
 {
        return strcmp(amagic, bmagic) == 0;
 }
@@ -1328,7 +1344,19 @@ out_unreg:
        kobject_put(&mod->mkobj.kobj);
        return err;
 }
-#endif
+
+static void mod_sysfs_fini(struct module *mod)
+{
+       kobject_put(&mod->mkobj.kobj);
+}
+
+#else /* CONFIG_SYSFS */
+
+static void mod_sysfs_fini(struct module *mod)
+{
+}
+
+#endif /* CONFIG_SYSFS */
 
 static void mod_kobject_remove(struct module *mod)
 {
@@ -1336,7 +1364,7 @@ static void mod_kobject_remove(struct module *mod)
        module_param_sysfs_remove(mod);
        kobject_put(mod->mkobj.drivers_dir);
        kobject_put(mod->holders_dir);
-       kobject_put(&mod->mkobj.kobj);
+       mod_sysfs_fini(mod);
 }
 
 /*
@@ -1771,7 +1799,7 @@ static struct module *load_module(void __user *umod,
 
        /* Sanity checks against insmoding binaries or wrong arch,
            weird elf version */
-       if (memcmp(hdr->e_ident, ELFMAG, 4) != 0
+       if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0
            || hdr->e_type != ET_REL
            || !elf_check_arch(hdr)
            || hdr->e_shentsize != sizeof(*sechdrs)) {
@@ -1869,7 +1897,7 @@ static struct module *load_module(void __user *umod,
                err = try_to_force_load(mod, "magic");
                if (err)
                        goto free_hdr;
-       } else if (!same_magic(modmagic, vermagic)) {
+       } else if (!same_magic(modmagic, vermagic, versindex)) {
                printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
                       mod->name, modmagic, vermagic);
                err = -ENOEXEC;