]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
kmod_module: use 'modname/aliasname' as key for hash
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 14 Dec 2011 17:21:10 +0000 (15:21 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 14 Dec 2011 17:26:04 +0000 (15:26 -0200)
1 alias may correspond to more than 1 module. This would cause a
conflict in the hash table when inserting a module there and bad things
could happen.

Now we use 'modname/aliasname' as key, '/aliasname' part being optional.
Internally kmod_module_new_from_alias() will setup a 'modname/aliasname'
string and pass to kmod_module_new_from_name() that will treat the case
with a '/' in the name.

User might call kmod_module_new_from_name() without any slashes, so the
key my not contain it.

TODO
libkmod/libkmod-module.c

diff --git a/TODO b/TODO
index 30141071a493250f8e988d04c061602e5c2b33d6..28b4fcd636d0384e61228d4de6f30f103c4e98f5 100644 (file)
--- a/TODO
+++ b/TODO
@@ -32,8 +32,5 @@ Features:
    - dump configuration
    - use softdep, install and remove commands
 
-Bugs:
+Known Bugs:
 
-* With last changes to the hash of kmod module's, if an alias resolves to more
-  than one module it will conflict in the table. The proper solution is to use
-  'modname/modalias' as the hash key.
index faa736e27f7de400d9c079586c1c735f010005e1..d26ce0ab7ce237e916cc31a5e20082a8753eb9a3 100644 (file)
@@ -218,6 +218,7 @@ KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
        struct kmod_module *m;
        size_t namelen;
        char name_norm[NAME_MAX];
+       char *namesep;
 
        if (ctx == NULL || name == NULL)
                return -ENOENT;
@@ -241,10 +242,18 @@ KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
        m->ctx = kmod_ref(ctx);
        m->name = (char *)m + sizeof(*m);
        memcpy(m->name, name_norm, namelen + 1);
+
        m->refcount = 1;
 
+       /* set alias later, so m->name is still modname/modalias */
        kmod_pool_add_module(ctx, m);
 
+       namesep = strchr(m->name, '/');
+       if (namesep != NULL) {
+               *namesep = '\0';
+               m->alias = namesep + 1;
+       }
+
        *mod = m;
 
        return 0;
@@ -254,29 +263,22 @@ int kmod_module_new_from_alias(struct kmod_ctx *ctx, const char *alias,
                                const char *name, struct kmod_module **mod)
 {
        int err;
-       struct kmod_module *m;
+       char key[NAME_MAX];
+       size_t namelen = strlen(name);
+       size_t aliaslen = strlen(alias);
 
-       err = kmod_module_new_from_name(ctx, alias, mod);
-       if (err < 0)
-               return err;
+       if (namelen + aliaslen + 2 > NAME_MAX)
+               return -ENAMETOOLONG;
 
-       m = *mod;
+       memcpy(key, name, namelen);
+       memcpy(key + namelen + 1, alias, aliaslen + 1);
+       key[namelen] = '/';
 
-       /* if module did not came from pool */
-       if (m->alias == NULL) {
-               m->alias = m->name;
-               m->name = strdup(name);
-               if (m->name == NULL)
-                       goto fail_oom;
-       }
+       err = kmod_module_new_from_name(ctx, key, mod);
+       if (err < 0)
+               return err;
 
        return 0;
-
-fail_oom:
-       ERR(ctx, "out of memory\n");
-       kmod_module_unref(m);
-       *mod = NULL;
-       return err;
 }
 
 /**
@@ -391,8 +393,6 @@ KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
        free(mod->install_commands);
        free(mod->remove_commands);
        free(mod->path);
-       if (mod->alias != NULL)
-               free(mod->name);
        free(mod);
        return NULL;
 }