diff options
author | Jeremy Katz <katzj@redhat.com> | 2003-01-09 17:56:52 +0000 |
---|---|---|
committer | Jeremy Katz <katzj@redhat.com> | 2003-01-09 17:56:52 +0000 |
commit | 1c1ed698648d17b0d4f1bdb6faa1d7f46188e9a4 (patch) | |
tree | f3fd89917a31ba67e542b1d0e2a32161086d1461 /loader2/modules.c | |
parent | 913a448d7286c5e5d1f5104b46c1087b8c41f690 (diff) | |
download | anaconda-1c1ed698648d17b0d4f1bdb6faa1d7f46188e9a4.tar.gz anaconda-1c1ed698648d17b0d4f1bdb6faa1d7f46188e9a4.tar.xz anaconda-1c1ed698648d17b0d4f1bdb6faa1d7f46188e9a4.zip |
basic module reload support for the usb-storage nonsense. this brings us back
to 8.0 level at least.
Diffstat (limited to 'loader2/modules.c')
-rw-r--r-- | loader2/modules.c | 156 |
1 files changed, 151 insertions, 5 deletions
diff --git a/loader2/modules.c b/loader2/modules.c index e82d02fca..1f40e336f 100644 --- a/loader2/modules.c +++ b/loader2/modules.c @@ -43,6 +43,13 @@ static struct extractedModule * extractModules (char * const * modNames, struct extractedModule * oldPaths, struct moduleBallLocation * location); + +static int simpleRemoveLoadedModule(const char * modName, moduleList modLoaded, + int flags); +static int reloadUnloadedModule(char * modName, moduleList modLoaded, + int flags); + + /* pass in the type of device (eth or tr) that you're looking for */ static int ethCount(const char * type) { int fd; @@ -92,10 +99,16 @@ static int scsiDiskCount(void) { int i = 0; devices = probeDevices(CLASS_HD, BUS_SCSI, PROBE_ALL); - if (!devices) - return 0; - - for (i = 0; devices[i]; i++); + if (devices) { + for (i; devices[i]; i++); + free(devices); + } + /* have to probe for usb floppies too */ + devices = probeDevices(CLASS_FLOPPY, BUS_SCSI, PROBE_ALL); + if (devices) { + for (i; devices[i]; i++); + free(devices); + } return i; } @@ -419,7 +432,8 @@ static int doLoadModules(const char * origModNames, moduleList modLoaded, location = mi->locationID; } - if (mi && mi->major == DRIVER_SCSI) { + if (mi && (mi->major == DRIVER_SCSI) && + mlModuleInList("usb-storage", modLoaded)) { reloadUsbStorage = 1; } } @@ -449,6 +463,23 @@ static int doLoadModules(const char * origModNames, moduleList modLoaded, if (*items) logMessage("module(s) %s not found", items); if (reloadUsbStorage) { + for (i = 0; i < modLoaded->numModules; i++) + if (!strcmp(modLoaded->mods[i].name, "usb-storage")) + break; + + if (i >= modLoaded->numModules) { + logMessage("usb-storage loaded, but can't find it. ick."); + /* JKFIXME: return? */ + } + + if (modLoaded->mods[i].lastDevNum != (scsiDiskCount() - 1)) { + logMessage("usb-storage isn't claiming the last scsi dev (%d vs %d)", modLoaded->mods[i].lastDevNum, scsiDiskCount() - 1); + /* JKFIXME: return? or not, because of firewire */ + } + + /* here we need to save the state of stage2 */ + simpleRemoveLoadedModule("usb-storage", modLoaded, flags); + /* JKFIXME: here are the big hacks... for now, just described. * 1) figure out which scsi devs are claimed by usb-storage. * if lastScsiDev == usb-storage->lastDev, @@ -474,6 +505,7 @@ static int doLoadModules(const char * origModNames, moduleList modLoaded, } if (reloadUsbStorage) { + reloadUnloadedModule("usb-storage", modLoaded, flags); /* JKFIXME: here's the rest of the hacks. basically do the reverse * of what we did before. */ @@ -746,3 +778,117 @@ static struct extractedModule * extractModules (char * const * modNames, free(ballPath); return oldPaths; } + + + +/* simple removal of a loaded module which is going to be reloaded. + * Note that this doesn't remove the module from the modLoaded struct + * but we do update the loadedModuleInfo to reflect the fact that its using + * no devices anymore. + */ +static int simpleRemoveLoadedModule(const char * modName, moduleList modLoaded, + int flags) { + int i, status, rc = 0; + pid_t child; + + for (i = 0; i < modLoaded->numModules; i++) + if (!strcmp(modLoaded->mods[i].name, modName)) + break; + + if (i >= modLoaded->numModules) + return 0; + + /* since we're unloading, set the devs to 0. this should hopefully only + * ever happen with things at the end */ + modLoaded->mods[i].firstDevNum = 0; + modLoaded->mods[i].lastDevNum = 0; + + if (FL_TESTING(flags)) { + logMessage("would have rmmod %s", modName); + rc = 0; + } else { + logMessage("going to rmmod %s", modName); + if (!(child = fork())) { + int fd = open("/dev/tty3", O_RDWR); + + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + + execl("/sbin/rmmod", "/sbin/rmmod", modName, NULL); + _exit(rc); + } + + waitpid(child, &status, 0); + + if (!WIFEXITED(status) || WEXITSTATUS(status)) { + rc = 1; + } else { + rc = 0; + } + } + return rc; +} + +/* simple reinsertion of a module; just looks for the module and reloads it + * if we think it was already loaded. we also update firstDevNum and + * lastDevNum to be current + */ +static int reloadUnloadedModule(char * modName, moduleList modLoaded, + int flags) { + char fileName[200]; + int rc, status; + pid_t child; + struct extractedModule * path = NULL; + char * list[2]; + int i; + + for (i = 0; i < modLoaded->numModules; i++) + if (!strcmp(modLoaded->mods[i].name, modName)) + break; + + if (i >= modLoaded->numModules) + return 0; + + modLoaded->mods[i].firstDevNum = scsiCount(); + + list[0] = modName; + list[1] = NULL; + + path = extractModules(list, path, NULL); + + sprintf(fileName, "%s.o", modName); + + if (FL_TESTING(flags)) { + logMessage("would have insmod %s", fileName); + rc = 0; + } else { + logMessage("going to insmod %s", fileName); + + if (!(child = fork())) { + int fd = open("/dev/tty3", O_RDWR); + + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + + rc = insmod(fileName, NULL, NULL); + _exit(rc); + } + + waitpid(child, &status, 0); + + if (!WIFEXITED(status) || WEXITSTATUS(status)) { + rc = 1; + } else { + rc = 0; + } + } + + modLoaded->mods[i].lastDevNum = scsiCount(); + logMessage("reloadModule returning %d", rc); + return rc; +} + |