diff options
-rw-r--r-- | modutils/modprobe-small.c | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 6b0a4400c..598965968 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
@@ -536,17 +536,49 @@ static module_info** find_alias(const char *alias) | |||
536 | // TODO: open only once, invent config_rewind() | 536 | // TODO: open only once, invent config_rewind() |
537 | static int already_loaded(const char *name) | 537 | static int already_loaded(const char *name) |
538 | { | 538 | { |
539 | int ret = 0; | 539 | int ret, namelen; |
540 | char *s; | 540 | char *line; |
541 | parser_t *parser = config_open2("/proc/modules", xfopen_for_read); | 541 | FILE *fp; |
542 | while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) { | 542 | |
543 | if (strcmp(s, name) == 0) { | 543 | ret = 5 * 2; |
544 | ret = 1; | 544 | again: |
545 | break; | 545 | fp = fopen_for_read("/proc/modules"); |
546 | if (!fp) | ||
547 | return 0; | ||
548 | namelen = strlen(name); | ||
549 | while ((line = xmalloc_fgetline(fp)) != NULL) { | ||
550 | char *live; | ||
551 | |||
552 | // Examples from kernel 3.14.6: | ||
553 | //pcspkr 12718 0 - Live 0xffffffffa017e000 | ||
554 | //snd_timer 28690 2 snd_seq,snd_pcm, Live 0xffffffffa025e000 | ||
555 | //i915 801405 2 - Live 0xffffffffa0096000 | ||
556 | if (strncmp(line, name, namelen) != 0 || line[namelen] != ' ') { | ||
557 | free(line); | ||
558 | continue; | ||
546 | } | 559 | } |
560 | live = strstr(line, " Live"); | ||
561 | free(line); | ||
562 | if (!live) { | ||
563 | /* State can be Unloading, Loading, or Live. | ||
564 | * modprobe must not return prematurely if we see "Loading": | ||
565 | * it can cause further programs to assume load completed, | ||
566 | * but it did not (yet)! | ||
567 | * Wait up to 5*20 ms for it to resolve. | ||
568 | */ | ||
569 | ret -= 2; | ||
570 | if (ret == 0) | ||
571 | break; /* huh? report as "not loaded" */ | ||
572 | fclose(fp); | ||
573 | usleep(20*1000); | ||
574 | goto again; | ||
575 | } | ||
576 | ret = 1; | ||
577 | break; | ||
547 | } | 578 | } |
548 | config_close(parser); | 579 | fclose(fp); |
549 | return ret; | 580 | |
581 | return ret | 1; | ||
550 | } | 582 | } |
551 | #else | 583 | #else |
552 | #define already_loaded(name) 0 | 584 | #define already_loaded(name) 0 |