aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-03-06 22:48:11 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-03-06 22:48:11 +0000
commita6b6f05379b0d68229b1bb230753ac498692e694 (patch)
tree41815898279f371724b60899cceca8c3ae54cca5
parent8517d6fc1fbb2181954cfa22997e20dd9ae9cc18 (diff)
downloadbusybox-w32-a6b6f05379b0d68229b1bb230753ac498692e694.tar.gz
busybox-w32-a6b6f05379b0d68229b1bb230753ac498692e694.tar.bz2
busybox-w32-a6b6f05379b0d68229b1bb230753ac498692e694.zip
further work on modprobe
function old new delta gather_options_str - 75 +75 config_file_action 388 413 +25 load_modules_dep 175 192 +17 add_probe 67 72 +5 modprobe_main 494 488 -6 gather_options 89 - -89 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 3/1 up/down: 122/-95) Total: 27 bytes
-rw-r--r--modutils/modprobe.c184
1 files changed, 110 insertions, 74 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index a5ade2add..218a898a8 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -13,18 +13,23 @@
13#include <sys/utsname.h> 13#include <sys/utsname.h>
14#include <fnmatch.h> 14#include <fnmatch.h>
15 15
16//#define DBG(...) bb_error_msg(__VA_ARGS__)
17#define DBG(...) ((void)0)
18
16#define MODULE_FLAG_LOADED 0x0001 19#define MODULE_FLAG_LOADED 0x0001
17#define MODULE_FLAG_NEED_DEPS 0x0002 20#define MODULE_FLAG_NEED_DEPS 0x0002
18//Misnomer? Seems to mean "was seen in modules.dep": 21/* "was seen in modules.dep": */
19#define MODULE_FLAG_EXISTS 0x0004 22#define MODULE_FLAG_FOUND_IN_MODDEP 0x0004
20#define MODULE_FLAG_BLACKLISTED 0x0008 23#define MODULE_FLAG_BLACKLISTED 0x0008
21 24
22struct module_entry { /* I'll call it ME. */ 25struct module_entry { /* I'll call it ME. */
23 unsigned flags; 26 unsigned flags;
24 char *modname; /* stripped of /path/, .ext and s/-/_/g */ 27 char *modname; /* stripped of /path/, .ext and s/-/_/g */
25 const char *probed_name; /* verbatim as seen on cmdline */ 28 const char *probed_name; /* verbatim as seen on cmdline */
26 llist_t *aliases; /* strings. aliases from config files */ 29 char *options; /* options from config files */
27 llist_t *options; /* strings. options from config files */ 30 llist_t *realnames; /* strings. if this module is an alias, */
31 /* real module name is one of these. */
32//Can there really be more than one? Example from real kernel?
28 llist_t *deps; /* strings. modules we depend on */ 33 llist_t *deps; /* strings. modules we depend on */
29}; 34};
30 35
@@ -45,8 +50,8 @@ enum {
45struct globals { 50struct globals {
46 llist_t *db; /* MEs of all modules ever seen (caching for speed) */ 51 llist_t *db; /* MEs of all modules ever seen (caching for speed) */
47 llist_t *probes; /* MEs of module(s) requested on cmdline */ 52 llist_t *probes; /* MEs of module(s) requested on cmdline */
48 llist_t *cmdline_mopts; /* strings. module options (from cmdline) */ 53 char *cmdline_mopts; /* module options from cmdline */
49 int num_deps; /* what is this? */ 54 int num_unresolved_deps;
50 /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ 55 /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */
51 smallint need_symbols; 56 smallint need_symbols;
52}; 57};
@@ -56,6 +61,19 @@ struct globals {
56 61
57static int read_config(const char *path); 62static int read_config(const char *path);
58 63
64static char *gather_options_str(char *opts, const char *append)
65{
66 /* Speed-optimized. We call gather_options_str many times. */
67 if (opts == NULL) {
68 opts = xstrdup(append);
69 } else {
70 int optlen = strlen(opts);
71 opts = xrealloc(opts, optlen + strlen(append) + 2);
72 sprintf(opts + optlen, " %s", append);
73 }
74 return opts;
75}
76
59static struct module_entry *helper_get_module(const char *module, int create) 77static struct module_entry *helper_get_module(const char *module, int create)
60{ 78{
61 char modname[MODULE_NAME_LEN]; 79 char modname[MODULE_NAME_LEN];
@@ -91,14 +109,20 @@ static void add_probe(const char *name)
91 struct module_entry *m; 109 struct module_entry *m;
92 110
93 m = get_or_add_modentry(name); 111 m = get_or_add_modentry(name);
112 if (m->flags & MODULE_FLAG_LOADED) {
113 DBG("skipping %s, it is already loaded", name);
114 return;
115 }
116
94 m->probed_name = name; 117 m->probed_name = name;
95 m->flags |= MODULE_FLAG_NEED_DEPS; 118 m->flags |= MODULE_FLAG_NEED_DEPS;
96 llist_add_to(&G.probes, m); 119 llist_add_to_end(&G.probes, m);
97 120 G.num_unresolved_deps++;
98 G.num_deps++;
99 if (ENABLE_FEATURE_MODUTILS_SYMBOLS 121 if (ENABLE_FEATURE_MODUTILS_SYMBOLS
100 && strncmp(m->modname, "symbol:", 7) == 0) 122 && strncmp(m->modname, "symbol:", 7) == 0
123 ) {
101 G.need_symbols = 1; 124 G.need_symbols = 1;
125 }
102} 126}
103 127
104static int FAST_FUNC config_file_action(const char *filename, 128static int FAST_FUNC config_file_action(const char *filename,
@@ -106,10 +130,8 @@ static int FAST_FUNC config_file_action(const char *filename,
106 void *userdata UNUSED_PARAM, 130 void *userdata UNUSED_PARAM,
107 int depth UNUSED_PARAM) 131 int depth UNUSED_PARAM)
108{ 132{
109 RESERVE_CONFIG_BUFFER(modname, MODULE_NAME_LEN); 133 char *tokens[3];
110 char *tokens[3], *rmod;
111 parser_t *p; 134 parser_t *p;
112 llist_t *l;
113 struct module_entry *m; 135 struct module_entry *m;
114 int rc = TRUE; 136 int rc = TRUE;
115 137
@@ -125,42 +147,51 @@ static int FAST_FUNC config_file_action(const char *filename,
125 while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) { 147 while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) {
126//Use index_in_strings? 148//Use index_in_strings?
127 if (strcmp(tokens[0], "alias") == 0) { 149 if (strcmp(tokens[0], "alias") == 0) {
128 filename2modname(tokens[1], modname); 150 /* alias <wildcard> <modulename> */
151 llist_t *l;
152 char wildcard[MODULE_NAME_LEN];
153 char *rmod;
154
129 if (tokens[2] == NULL) 155 if (tokens[2] == NULL)
130 continue; 156 continue;
157 filename2modname(tokens[1], wildcard);
131 158
132 for (l = G.probes; l != NULL; l = l->link) { 159 for (l = G.probes; l != NULL; l = l->link) {
133 m = (struct module_entry *) l->data; 160 m = (struct module_entry *) l->data;
134 if (fnmatch(modname, m->modname, 0) != 0) 161 if (fnmatch(wildcard, m->modname, 0) != 0)
135 continue; 162 continue;
136 rmod = filename2modname(tokens[2], NULL); 163 rmod = filename2modname(tokens[2], NULL);
137 llist_add_to(&m->aliases, rmod); 164 llist_add_to(&m->realnames, rmod);
138 165
139 if (m->flags & MODULE_FLAG_NEED_DEPS) { 166 if (m->flags & MODULE_FLAG_NEED_DEPS) {
140 m->flags &= ~MODULE_FLAG_NEED_DEPS; 167 m->flags &= ~MODULE_FLAG_NEED_DEPS;
141 G.num_deps--; 168 G.num_unresolved_deps--;
142 } 169 }
143 170
144 m = get_or_add_modentry(rmod); 171 m = get_or_add_modentry(rmod);
145 m->flags |= MODULE_FLAG_NEED_DEPS; 172 if (!(m->flags & MODULE_FLAG_NEED_DEPS)) {
146 G.num_deps++; 173 m->flags |= MODULE_FLAG_NEED_DEPS;
174 G.num_unresolved_deps++;
175 }
147 } 176 }
148 } else if (strcmp(tokens[0], "options") == 0) { 177 } else if (strcmp(tokens[0], "options") == 0) {
178 /* options <modulename> <option...> */
149 if (tokens[2] == NULL) 179 if (tokens[2] == NULL)
150 continue; 180 continue;
151 m = get_or_add_modentry(tokens[1]); 181 m = get_or_add_modentry(tokens[1]);
152 llist_add_to(&m->options, xstrdup(tokens[2])); 182 m->options = gather_options_str(m->options, tokens[2]);
153 } else if (strcmp(tokens[0], "include") == 0) { 183 } else if (strcmp(tokens[0], "include") == 0) {
184 /* include <filename> */
154 read_config(tokens[1]); 185 read_config(tokens[1]);
155 } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST 186 } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST
156 && strcmp(tokens[0], "blacklist") == 0 187 && strcmp(tokens[0], "blacklist") == 0
157 ) { 188 ) {
189 /* blacklist <modulename> */
158 get_or_add_modentry(tokens[1])->flags |= MODULE_FLAG_BLACKLISTED; 190 get_or_add_modentry(tokens[1])->flags |= MODULE_FLAG_BLACKLISTED;
159 } 191 }
160 } 192 }
161 config_close(p); 193 config_close(p);
162error: 194error:
163 RELEASE_CONFIG_BUFFER(modname);
164 return rc; 195 return rc;
165} 196}
166 197
@@ -170,29 +201,17 @@ static int read_config(const char *path)
170 config_file_action, NULL, NULL, 1); 201 config_file_action, NULL, NULL, 1);
171} 202}
172 203
173static char *gather_options(char *opts, llist_t *o)
174{
175 int optlen;
176
177 if (opts == NULL)
178 opts = xstrdup("");
179 optlen = strlen(opts);
180
181 for (; o != NULL; o = o->link) {
182 opts = xrealloc(opts, optlen + strlen(o->data) + 2);
183 optlen += sprintf(opts + optlen, "%s ", o->data);
184 }
185 return opts;
186}
187
188static int do_modprobe(struct module_entry *m) 204static int do_modprobe(struct module_entry *m)
189{ 205{
190 struct module_entry *m2; 206 struct module_entry *m2;
191 char *fn, *options; 207 char *fn, *options;
192 int rc = -1; 208 int rc = -1;
193 209
194 if (!(m->flags & MODULE_FLAG_EXISTS)) 210 if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) {
211 DBG("skipping %s, not found in modules.dep", m->modname);
195 return -ENOENT; 212 return -ENOENT;
213 }
214 DBG("do_modprob'ing %s", m->modname);
196 215
197 if (!(option_mask32 & MODPROBE_OPT_REMOVE)) 216 if (!(option_mask32 & MODPROBE_OPT_REMOVE))
198 m->deps = llist_rev(m->deps); 217 m->deps = llist_rev(m->deps);
@@ -205,19 +224,23 @@ static int do_modprobe(struct module_entry *m)
205 if (bb_delete_module(m->modname, O_EXCL) != 0) 224 if (bb_delete_module(m->modname, O_EXCL) != 0)
206 rc = errno; 225 rc = errno;
207 } else if (!(m2->flags & MODULE_FLAG_LOADED)) { 226 } else if (!(m2->flags & MODULE_FLAG_LOADED)) {
208 options = gather_options(NULL, m2->options); 227 options = m2->options;
228 m2->options = NULL;
209 if (m == m2) 229 if (m == m2)
210 options = gather_options(options, G.cmdline_mopts); 230 options = gather_options_str(options, G.cmdline_mopts);
211//TODO: looks like G.cmdline_mopts can contain either NULL or just one string, not more?
212 rc = bb_init_module(fn, options); 231 rc = bb_init_module(fn, options);
232 DBG("loaded %s '%s', rc:%d", fn, options, rc);
213 if (rc == 0) 233 if (rc == 0)
214 m2->flags |= MODULE_FLAG_LOADED; 234 m2->flags |= MODULE_FLAG_LOADED;
215 free(options); 235 free(options);
236 } else {
237 DBG("%s is already loaded, skipping", fn);
216 } 238 }
217 239
218 free(fn); 240 free(fn);
219 } 241 }
220 242
243//FIXME: what if rc < 0?
221 if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT)) { 244 if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT)) {
222 bb_error_msg("failed to %sload module %s: %s", 245 bb_error_msg("failed to %sload module %s: %s",
223 (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "", 246 (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "",
@@ -235,17 +258,15 @@ static void load_modules_dep(void)
235 char *colon, *tokens[2]; 258 char *colon, *tokens[2];
236 parser_t *p; 259 parser_t *p;
237 260
238 p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
239//Still true?
240 /* Modprobe does not work at all without modprobe.dep, 261 /* Modprobe does not work at all without modprobe.dep,
241 * even if the full module name is given. Returning error here 262 * even if the full module name is given. Returning error here
242 * was making us later confuse user with this message: 263 * was making us later confuse user with this message:
243 * "module /full/path/to/existing/file/module.ko not found". 264 * "module /full/path/to/existing/file/module.ko not found".
244 * It's better to die immediately, with good message: */ 265 * It's better to die immediately, with good message.
245// if (p == NULL) 266 * xfopen_for_read provides that. */
246// bb_perror_msg_and_die("can't open '%s'", CONFIG_DEFAULT_DEPMOD_FILE); 267 p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
247 268
248 while (G.num_deps 269 while (G.num_unresolved_deps
249 && config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL) 270 && config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)
250 ) { 271 ) {
251 colon = last_char_is(tokens[0], ':'); 272 colon = last_char_is(tokens[0], ':');
@@ -256,11 +277,18 @@ static void load_modules_dep(void)
256 m = get_modentry(tokens[0]); 277 m = get_modentry(tokens[0]);
257 if (m == NULL) 278 if (m == NULL)
258 continue; 279 continue;
259//Can we skip it too if it is MODULE_FLAG_LOADED?
260 280
261 m->flags |= MODULE_FLAG_EXISTS; 281 /* Optimization... */
282 if ((m->flags & MODULE_FLAG_LOADED)
283 && !(option_mask32 & MODPROBE_OPT_REMOVE)
284 ) {
285 DBG("skip deps of %s, it's already loaded", tokens[0]);
286 continue;
287 }
288
289 m->flags |= MODULE_FLAG_FOUND_IN_MODDEP;
262 if ((m->flags & MODULE_FLAG_NEED_DEPS) && (m->deps == NULL)) { 290 if ((m->flags & MODULE_FLAG_NEED_DEPS) && (m->deps == NULL)) {
263 G.num_deps--; 291 G.num_unresolved_deps--;
264 llist_add_to(&m->deps, xstrdup(tokens[0])); 292 llist_add_to(&m->deps, xstrdup(tokens[0]));
265 if (tokens[1]) 293 if (tokens[1])
266 string_to_llist(tokens[1], &m->deps, " "); 294 string_to_llist(tokens[1], &m->deps, " ");
@@ -285,76 +313,84 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
285 MODPROBE_OPT_SHOW_ONLY)) 313 MODPROBE_OPT_SHOW_ONLY))
286 bb_error_msg_and_die("not supported"); 314 bb_error_msg_and_die("not supported");
287 315
288 /* Goto modules location */
289 xchdir(CONFIG_DEFAULT_MODULES_DIR);
290 uname(&uts);
291 xchdir(uts.release);
292
293 if (!argv[0]) { 316 if (!argv[0]) {
294 if (opt & MODPROBE_OPT_REMOVE) { 317 if (opt & MODPROBE_OPT_REMOVE) {
295 /* TODO: comment here */ 318 /* "modprobe -r" (w/o params).
319 * "If name is NULL, all unused modules marked
320 * autoclean will be removed".
321 */
296 if (bb_delete_module(NULL, O_NONBLOCK|O_EXCL) != 0) 322 if (bb_delete_module(NULL, O_NONBLOCK|O_EXCL) != 0)
297 bb_perror_msg_and_die("rmmod"); 323 bb_perror_msg_and_die("rmmod");
298 } 324 }
299 return EXIT_SUCCESS; 325 return EXIT_SUCCESS;
300 } 326 }
301 327
328 /* Goto modules location */
329 xchdir(CONFIG_DEFAULT_MODULES_DIR);
330 uname(&uts);
331 xchdir(uts.release);
332
333 /* Retrieve module names of already loaded modules */
334 {
335 char *s;
336 parser_t *parser = config_open2("/proc/modules", fopen_for_read);
337 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY))
338 get_or_add_modentry(s)->flags |= MODULE_FLAG_LOADED;
339 config_close(parser);
340 }
341
302 if (opt & MODPROBE_OPT_INSERT_ALL) { 342 if (opt & MODPROBE_OPT_INSERT_ALL) {
303 /* Each argument is a module name */ 343 /* Each argument is a module name */
304 do { 344 do {
305 add_probe(*argv++); 345 add_probe(*argv++);
306 } while (*argv); 346 } while (*argv);
307 G.probes = llist_rev(G.probes);
308 } else { 347 } else {
309 /* First argument is module name, rest are parameters */ 348 /* First argument is module name, rest are parameters */
310 add_probe(argv[0]); 349 add_probe(argv[0]);
311//TODO: looks like G.cmdline_mopts can contain either NULL or just one string, not more? 350 G.cmdline_mopts = parse_cmdline_module_options(argv);
312//optimize it them
313 llist_add_to(&G.cmdline_mopts, parse_cmdline_module_options(argv));
314 } 351 }
315 352
316 /* Retrieve module names of already loaded modules */ 353 /* Happens if all requested modules are already loaded */
317 { 354 if (G.probes == NULL)
318 char *s; 355 return EXIT_SUCCESS;
319 parser_t *parser = config_open2("/proc/modules", fopen_for_read);
320 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY))
321 get_or_add_modentry(s)->flags |= MODULE_FLAG_LOADED;
322 config_close(parser);
323 }
324 356
325 read_config("/etc/modprobe.conf"); 357 read_config("/etc/modprobe.conf");
326 read_config("/etc/modprobe.d"); 358 read_config("/etc/modprobe.d");
327 if (ENABLE_FEATURE_MODUTILS_SYMBOLS && G.need_symbols) 359 if (ENABLE_FEATURE_MODUTILS_SYMBOLS && G.need_symbols)
328 read_config("modules.symbols"); 360 read_config("modules.symbols");
329 load_modules_dep(); 361 load_modules_dep();
330 if (ENABLE_FEATURE_MODUTILS_ALIAS && G.num_deps) { 362 if (ENABLE_FEATURE_MODUTILS_ALIAS && G.num_unresolved_deps) {
331 read_config("modules.alias"); 363 read_config("modules.alias");
332 load_modules_dep(); 364 load_modules_dep();
333 } 365 }
334 366
335 while ((me = llist_pop(&G.probes)) != NULL) { 367 while ((me = llist_pop(&G.probes)) != NULL) {
336 if (me->aliases == NULL) { 368 if (me->realnames == NULL) {
337 /* Try if module by literal name is found; literal 369 /* This is not an alias. Literal names are blacklisted
338 * names are blacklisted only if '-b' is given. */ 370 * only if '-b' is given.
371 */
339 if (!(opt & MODPROBE_OPT_BLACKLIST) 372 if (!(opt & MODPROBE_OPT_BLACKLIST)
340 || !(me->flags & MODULE_FLAG_BLACKLISTED) 373 || !(me->flags & MODULE_FLAG_BLACKLISTED)
341 ) { 374 ) {
342 rc = do_modprobe(me); 375 rc = do_modprobe(me);
376//FIXME: what if rc > 0?
343 if (rc < 0 && !(opt & INSMOD_OPT_SILENT)) 377 if (rc < 0 && !(opt & INSMOD_OPT_SILENT))
344 bb_error_msg("module %s not found", 378 bb_error_msg("module %s not found",
345 me->probed_name); 379 me->probed_name);
346 } 380 }
347 } else { 381 } else {
348 /* Probe all aliases */ 382 /* Probe all realnames */
349 do { 383 do {
350 char *realname = llist_pop(&me->aliases); 384 char *realname = llist_pop(&me->realnames);
351 struct module_entry *m2; 385 struct module_entry *m2;
352 386
387 DBG("probing %s by realname %s", me->modname, realname);
353 m2 = get_or_add_modentry(realname); 388 m2 = get_or_add_modentry(realname);
354 if (!(m2->flags & MODULE_FLAG_BLACKLISTED)) 389 if (!(m2->flags & MODULE_FLAG_BLACKLISTED))
355 do_modprobe(m2); 390 do_modprobe(m2);
391//FIXME: error check?
356 free(realname); 392 free(realname);
357 } while (me->aliases != NULL); 393 } while (me->realnames != NULL);
358 } 394 }
359 } 395 }
360 396