Revision e26110cf util/module.c

b/util/module.c
13 13
 * GNU GPL, version 2 or (at your option) any later version.
14 14
 */
15 15

  
16
#include <stdlib.h>
17
#include <gmodule.h>
16 18
#include "qemu-common.h"
17 19
#include "qemu/queue.h"
18 20
#include "qemu/module.h"
......
21 23
{
22 24
    void (*init)(void);
23 25
    QTAILQ_ENTRY(ModuleEntry) node;
26
    module_init_type type;
24 27
} ModuleEntry;
25 28

  
26 29
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
27 30

  
28 31
static ModuleTypeList init_type_list[MODULE_INIT_MAX];
29 32

  
30
static void init_types(void)
33
static ModuleTypeList dso_init_list;
34

  
35
static void init_lists(void)
31 36
{
32 37
    static int inited;
33 38
    int i;
......
40 45
        QTAILQ_INIT(&init_type_list[i]);
41 46
    }
42 47

  
48
    QTAILQ_INIT(&dso_init_list);
49

  
43 50
    inited = 1;
44 51
}
45 52

  
......
48 55
{
49 56
    ModuleTypeList *l;
50 57

  
51
    init_types();
58
    init_lists();
52 59

  
53 60
    l = &init_type_list[type];
54 61

  
......
62 69

  
63 70
    e = g_malloc0(sizeof(*e));
64 71
    e->init = fn;
72
    e->type = type;
65 73

  
66 74
    l = find_type(type);
67 75

  
68 76
    QTAILQ_INSERT_TAIL(l, e, node);
69 77
}
70 78

  
79
void register_dso_module_init(void (*fn)(void), module_init_type type)
80
{
81
    ModuleEntry *e;
82

  
83
    init_lists();
84

  
85
    e = g_malloc0(sizeof(*e));
86
    e->init = fn;
87
    e->type = type;
88

  
89
    QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
90
}
91

  
92
static void module_load(module_init_type type);
93

  
71 94
void module_call_init(module_init_type type)
72 95
{
73 96
    ModuleTypeList *l;
74 97
    ModuleEntry *e;
75 98

  
99
    module_load(type);
76 100
    l = find_type(type);
77 101

  
78 102
    QTAILQ_FOREACH(e, l, node) {
79 103
        e->init();
80 104
    }
81 105
}
106

  
107
#ifdef CONFIG_MODULES
108
static int module_load_file(const char *fname)
109
{
110
    GModule *g_module;
111
    void (*sym)(void);
112
    const char *dsosuf = HOST_DSOSUF;
113
    int len = strlen(fname);
114
    int suf_len = strlen(dsosuf);
115
    ModuleEntry *e, *next;
116
    int ret;
117

  
118
    if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) {
119
        /* wrong suffix */
120
        ret = -EINVAL;
121
        goto out;
122
    }
123
    if (access(fname, F_OK)) {
124
        ret = -ENOENT;
125
        goto out;
126
    }
127

  
128
    assert(QTAILQ_EMPTY(&dso_init_list));
129

  
130
    g_module = g_module_open(fname, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
131
    if (!g_module) {
132
        fprintf(stderr, "Failed to open module: %s\n",
133
                g_module_error());
134
        ret = -EINVAL;
135
        goto out;
136
    }
137
    if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) {
138
        fprintf(stderr, "Failed to initialize module: %s\n",
139
                fname);
140
        /* Print some info if this is a QEMU module (but from different build),
141
         * this will make debugging user problems easier. */
142
        if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) {
143
            fprintf(stderr,
144
                    "Note: only modules from the same build can be loaded.\n");
145
        }
146
        g_module_close(g_module);
147
        ret = -EINVAL;
148
    } else {
149
        QTAILQ_FOREACH(e, &dso_init_list, node) {
150
            register_module_init(e->init, e->type);
151
        }
152
        ret = 0;
153
    }
154

  
155
    QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
156
        QTAILQ_REMOVE(&dso_init_list, e, node);
157
        g_free(e);
158
    }
159
out:
160
    return ret;
161
}
162
#endif
163

  
164
void module_load(module_init_type type)
165
{
166
#ifdef CONFIG_MODULES
167
    char *fname = NULL;
168
    const char **mp;
169
    static const char *block_modules[] = {
170
        CONFIG_BLOCK_MODULES
171
    };
172
    char *exec_dir;
173
    char *dirs[3];
174
    int i = 0;
175
    int ret;
176

  
177
    if (!g_module_supported()) {
178
        fprintf(stderr, "Module is not supported by system.\n");
179
        return;
180
    }
181

  
182
    switch (type) {
183
    case MODULE_INIT_BLOCK:
184
        mp = block_modules;
185
        break;
186
    default:
187
        /* no other types have dynamic modules for now*/
188
        return;
189
    }
190

  
191
    exec_dir = qemu_get_exec_dir();
192
    dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
193
    dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : "");
194
    dirs[i++] = g_strdup_printf("%s", exec_dir ? : "");
195
    assert(i == ARRAY_SIZE(dirs));
196
    g_free(exec_dir);
197
    exec_dir = NULL;
198

  
199
    for ( ; *mp; mp++) {
200
        for (i = 0; i < ARRAY_SIZE(dirs); i++) {
201
            fname = g_strdup_printf("%s/%s%s", dirs[i], *mp, HOST_DSOSUF);
202
            ret = module_load_file(fname);
203
            /* Try loading until loaded a module file */
204
            if (!ret) {
205
                break;
206
            }
207
            g_free(fname);
208
            fname = NULL;
209
        }
210
        if (ret == -ENOENT) {
211
            fprintf(stderr, "Can't find module: %s\n", *mp);
212
        }
213

  
214
        g_free(fname);
215
    }
216

  
217
    for (i = 0; i < ARRAY_SIZE(dirs); i++) {
218
        g_free(dirs[i]);
219
    }
220

  
221
#endif
222
}

Also available in: Unified diff