Maintain a pool of modules alive
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Tue, 6 Dec 2011 05:38:37 +0000 (03:38 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Tue, 6 Dec 2011 05:49:07 +0000 (03:49 -0200)
Based on previous implementation by
Gustavo Sverzut Barbieri <barbieri@profusion.mobi>

libkmod/libkmod-module.c
libkmod/libkmod-private.h
libkmod/libkmod.c

index 9c8a627..432f453 100644 (file)
@@ -144,6 +144,12 @@ KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
 
        path_to_modname(name, name_norm, &namelen);
 
+       m = kmod_pool_get_module(ctx, name_norm);
+       if (m != NULL) {
+               *mod = kmod_module_ref(m);
+               return 0;
+       }
+
        m = calloc(1, sizeof(*m) + namelen + 1);
        if (m == NULL) {
                free(m);
@@ -154,6 +160,8 @@ KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
        memcpy(m->name, name_norm, namelen + 1);
        m->refcount = 1;
 
+       kmod_pool_add_module(ctx, m);
+
        *mod = m;
 
        return 0;
@@ -178,6 +186,12 @@ KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
 
        path_to_modname(path, name, &namelen);
 
+       m = kmod_pool_get_module(ctx, name);
+       if (m != NULL) {
+               *mod = kmod_module_ref(m);
+               return 0;
+       }
+
        m = calloc(1, sizeof(*m) + namelen + 1);
        if (m == NULL)
                return -errno;
@@ -193,6 +207,8 @@ KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
        memcpy(m->name, name, namelen);
        m->refcount = 1;
 
+       kmod_pool_add_module(ctx, m);
+
        *mod = m;
 
        return 0;
index 5479cc9..f1e0350 100644 (file)
@@ -66,12 +66,19 @@ struct kmod_list *kmod_list_append_list(struct kmod_list *list1, struct kmod_lis
 
 /* libkmod.c */
 const char *kmod_get_dirname(const struct kmod_ctx *ctx) __attribute__((nonnull(1)));
+
 int kmod_lookup_alias_from_config(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
 int kmod_lookup_alias_from_symbols_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
 int kmod_lookup_alias_from_aliases_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
 int kmod_lookup_alias_from_moddep_file(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
+
 char *kmod_search_moddep(struct kmod_ctx *ctx, const char *name) __attribute__((nonnull(1,2)));
 
+struct kmod_module *kmod_pool_get_module(struct kmod_ctx *ctx, const char *name) __attribute__((nonnull(1,2)));
+void kmod_pool_add_module(struct kmod_ctx *ctx, struct kmod_module *mod) __attribute__((nonnull(1,2)));
+void kmod_pool_del_module(struct kmod_ctx *ctx, struct kmod_module *mod) __attribute__((nonnull(1,2)));
+
+
 /* libkmod-config.c */
 struct kmod_config {
        struct kmod_ctx *ctx;
index 248203b..fa1fdbb 100644 (file)
@@ -33,6 +33,9 @@
 #include "libkmod-private.h"
 #include "libkmod-index.h"
 
+#define KMOD_HASH_SIZE (256)
+#define KMOD_LRU_MAX (128)
+
 /**
  * SECTION:libkmod
  * @short_description: libkmod context
@@ -55,6 +58,7 @@ struct kmod_ctx {
        const void *userdata;
        char *dirname;
        struct kmod_config *config;
+       struct kmod_hash *modules_by_name;
 };
 
 void kmod_log(struct kmod_ctx *ctx,
@@ -181,16 +185,26 @@ KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname)
 
        err = kmod_config_new(ctx, &ctx->config);
        if (err < 0) {
-               ERR(ctx, "could not create config");
-               free(ctx->dirname);
-               free(ctx);
-               return NULL;
+               ERR(ctx, "could not create config\n");
+               goto fail;
+       }
+
+       ctx->modules_by_name = kmod_hash_new(KMOD_HASH_SIZE, NULL);
+       if (ctx->modules_by_name == NULL) {
+               ERR(ctx, "could not create by-name hash\n");
+               goto fail;
        }
 
        INFO(ctx, "ctx %p created\n", ctx);
        DBG(ctx, "log_priority=%d\n", ctx->log_priority);
 
        return ctx;
+
+fail:
+       free(ctx->modules_by_name);
+       free(ctx->dirname);
+       free(ctx);
+       return NULL;
 }
 
 /**
@@ -225,6 +239,7 @@ KMOD_EXPORT struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx)
        if (--ctx->refcount > 0)
                return ctx;
        INFO(ctx, "context %p released\n", ctx);
+       kmod_hash_free(ctx->modules_by_name);
        free(ctx->dirname);
        if (ctx->config)
                kmod_config_free(ctx->config);
@@ -276,6 +291,35 @@ KMOD_EXPORT void kmod_set_log_priority(struct kmod_ctx *ctx, int priority)
        ctx->log_priority = priority;
 }
 
+struct kmod_module *kmod_pool_get_module(struct kmod_ctx *ctx,
+                                                       const char *name)
+{
+       struct kmod_module *mod;
+
+       mod = kmod_hash_find(ctx->modules_by_name, name);
+
+       DBG(ctx, "get module name='%s' found=%p\n", name, mod);
+
+       return mod;
+}
+
+void kmod_pool_add_module(struct kmod_ctx *ctx, struct kmod_module *mod)
+{
+       const char *name = kmod_module_get_name(mod);
+
+       DBG(ctx, "add %p name='%s'\n", mod, name);
+
+       kmod_hash_add(ctx->modules_by_name, name, mod);
+}
+
+void kmod_pool_del_module(struct kmod_ctx *ctx, struct kmod_module *mod)
+{
+       const char *name = kmod_module_get_name(mod);
+
+       DBG(ctx, "del %p name='%s'\n", mod, name);
+
+       kmod_hash_del(ctx->modules_by_name, name);
+}
 
 static int kmod_lookup_alias_from_alias_bin(struct kmod_ctx *ctx,
                                                const char *file,