--- loader/driverdisk.c | 18 ++++++--- loader/modules.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++--- loader/modules.h | 5 +++ 3 files changed, 110 insertions(+), 11 deletions(-) diff --git a/loader/driverdisk.c b/loader/driverdisk.c index b0cd179..eb369cb 100644 --- a/loader/driverdisk.c +++ b/loader/driverdisk.c @@ -381,6 +381,7 @@ int loadDriverFromMedia(int class, struct loaderData_s *loaderData, int rc, num = 0; int dir = 1; int found = 0, before = 0; + VersionState preDDstate, postDDstate; while (stage != DEV_DONE) { switch(stage) { @@ -583,8 +584,6 @@ int loadDriverFromMedia(int class, struct loaderData_s *loaderData, } case DEV_PROBE: { - struct device ** devices; - /* if they didn't specify that we should probe, then we should * just fall out */ if (noprobe) { @@ -592,16 +591,23 @@ int loadDriverFromMedia(int class, struct loaderData_s *loaderData, break; } + /* Get info about modules before the update */ + preDDstate = mlVersions(); + /* Unload all devices and load them again to use the updated modules */ logMessage(INFO, "Trying to refresh loaded drivers"); mlRestoreModuleState(moduleState); busProbe(0); - devices = getDevices(class); - if (devices) - for(; devices[found]; found++); + /* Get info about modules after the update */ + postDDstate = mlVersions(); + found = mlDetectUpdate(preDDstate, postDDstate); + logMessage(DEBUGLVL, "mlDetectUpdate returned %d", found); + + mlFreeVersions(postDDstate); + mlFreeVersions(preDDstate); - if (found > before) { + if (found) { stage = DEV_DONE; break; } diff --git a/loader/modules.c b/loader/modules.c index 2e3e429..96c7df5 100644 --- a/loader/modules.c +++ b/loader/modules.c @@ -415,7 +415,8 @@ inline gint gcmp(gconstpointer a, gconstpointer b, gpointer userptr) return g_strcmp0(a, b); } -int processModuleLines(GTree *data, int (*f)(gchar**, GTree*)){ +int processModuleLines(int (*f)(gchar**, void*), void *data) +{ char *line = NULL; size_t linesize = 0; gchar** lineparts = NULL; @@ -449,8 +450,9 @@ int processModuleLines(GTree *data, int (*f)(gchar**, GTree*)){ return count; } -inline int cb_savestate(gchar** parts, GTree *data) +inline int cb_savestate(gchar** parts, void *data0) { + GTree *data = data0; logMessage(DEBUGLVL, "Saving module %s", parts[0]); g_tree_insert(data, g_strdup(parts[0]), (gchar*)1); return 1; @@ -464,13 +466,14 @@ GTree* mlSaveModuleState() if(!state) return NULL; - processModuleLines(state, cb_savestate); + processModuleLines(cb_savestate, state); return state; } -inline int cb_restorestate(gchar** parts, GTree *data) +inline int cb_restorestate(gchar** parts, void *data0) { + GTree *data = data0; pid_t pid; int status; @@ -516,7 +519,7 @@ void mlRestoreModuleState(GTree *state) logMessage(INFO, "Restoring module state..."); /* repeat until we can't remove anything else */ - while (processModuleLines(state, cb_restorestate) > 0) + while (processModuleLines(cb_restorestate, state) > 0) /* noop */; } @@ -527,3 +530,88 @@ void mlFreeModuleState(GTree *state) g_tree_destroy(state); } + +inline int cb_saveversions(gchar** parts, void *data0) +{ + GHashTable *ht = data0; + gchar *module = g_strdup(parts[0]); + char *versionfilename; + char *srcversionfilename; + gchar *version; + gchar *srcversion; + gchar *value, *value2; + + checked_asprintf(&versionfilename, "/sys/module/%s/version", module); + checked_asprintf(&srcversionfilename, "/sys/module/%s/srcversion", module); + + /* emty string */ + value = (gchar*) calloc(1, sizeof(char)); + + /* get possible version file */ + if (g_file_get_contents(versionfilename, &version, NULL, NULL)) { + value2 = g_strconcat(value, version, "/", NULL); + g_free(value); + g_free(version); + value = value2; + } + + /* get possible src version file */ + if (g_file_get_contents(srcversionfilename, &srcversion, NULL, NULL)) { + value2 = g_strconcat(value, srcversion, NULL); + g_free(value); + g_free(srcversion); + value = value2; + } + + free(versionfilename); + free(srcversionfilename); + + g_hash_table_insert(ht, module, value); + + return 1; +} + +VersionState mlVersions() +{ + GHashTable *ht = NULL; + + ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + if(!ht) return NULL; + + /* read version info about all modules */ + processModuleLines(cb_saveversions, ht); + + return (VersionState)ht; +} + +void mlFreeVersions(VersionState ht) +{ + g_hash_table_destroy((GHashTable*)ht); +} + +int mlDetectUpdate(VersionState a, VersionState b) +{ + int rc = 0; + + if(!a && !b) return 0; + if(!a) return 1; + if(!b) return 1; + + GList *modules = g_hash_table_get_keys(b); + if(!modules) return 0; + + GList *iter = modules; + while (iter && !rc) { + gchar *va = g_hash_table_lookup(a, iter->data); + gchar *vb = g_hash_table_lookup(b, iter->data); + + if (!va) rc = 1; // new module + else rc = strcmp(va, vb); // check versions for match + + iter = iter->next; + } + + g_list_free(modules); + + return abs(rc); +} diff --git a/loader/modules.h b/loader/modules.h index 605d01e..675dffc 100644 --- a/loader/modules.h +++ b/loader/modules.h @@ -44,4 +44,9 @@ GTree* mlSaveModuleState(); void mlRestoreModuleState(GTree *state); void mlFreeModuleState(GTree *state); +typedef GHashTable* VersionState; +VersionState mlVersions(); +int mlDetectUpdate(VersionState a, VersionState b); +void mlFreeVersions(); + #endif -- 1.6.6.1 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list