aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2015-02-12 16:18:39 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2015-02-12 17:05:14 +0100
commit1fd844267c3ad60e9122e141768e823e6ad74a28 (patch)
tree2a02a15313320bcb3a7d53f02743603a79a4333e
parent622a7aab2c4a918c0e71931505f5c38d66d81ad9 (diff)
downloadbusybox-w32-1fd844267c3ad60e9122e141768e823e6ad74a28.tar.gz
busybox-w32-1fd844267c3ad60e9122e141768e823e6ad74a28.tar.bz2
busybox-w32-1fd844267c3ad60e9122e141768e823e6ad74a28.zip
modprobe-small: if concurrent module load did not succeed, wait
usecase: two sd cards are being mounted in parallel at same time on dual core. example modules which are getting loaded is nls_cp437. While one module is being loaded , it makes state in /proc/modules as 'coming' and then starts doing its module init function (in our case - registering nls). meanwhile on other core, if modprobe returns that is has already been loaded, then it will continue and search for the nls list which is not yet finished from first module init. This fails resulting in not mounting sd card. function old new delta process_module 667 746 +79 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--modutils/modprobe-small.c50
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()
537static int already_loaded(const char *name) 537static 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