summaryrefslogtreecommitdiffstats
path: root/loader2/modules.c
diff options
context:
space:
mode:
authorJeremy Katz <katzj@redhat.com>2003-01-09 17:56:52 +0000
committerJeremy Katz <katzj@redhat.com>2003-01-09 17:56:52 +0000
commit1c1ed698648d17b0d4f1bdb6faa1d7f46188e9a4 (patch)
treef3fd89917a31ba67e542b1d0e2a32161086d1461 /loader2/modules.c
parent913a448d7286c5e5d1f5104b46c1087b8c41f690 (diff)
downloadanaconda-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.c156
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;
+}
+