[PATCH] Fix unloading modules in driver-updates (#1085099)

Will Woods wwoods at redhat.com
Mon Apr 21 14:31:31 UTC 2014


An unintended consequence of commit de2d663 is that driver-updates won't
unload *any* modules at all: /tmp/dd_modules (the list of "early"
modules that shouldn't be removed) is now created *after* we load all
modules.)

This patch makes driver-updates attempt to remove any driver that's in
the update disk(s) it loads.

First we make dd_extract() return a list of the firmware/module files
that were in the driver disk it extracted.

Next process_dd() builds a list of those for each extracted driver and
passes that to reload_modules().

reload_modules() maps those filenames to module names, and adds them to
the list of modules to be unloaded.

NOTE: Probably the correct behavior (and the way it worked in RHEL6)
would be to revert the change to /tmp/dd_modules and fix that bug in a
different way (e.g. by tracking driver disks by UUID instead of device
name, so they don't get loaded twice if the device name changes).

That requires a bunch of refactoring work; this is a stopgap solution.
---
 dracut/driver-updates | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/dracut/driver-updates b/dracut/driver-updates
index 5eb4cdc..373884f 100755
--- a/dracut/driver-updates
+++ b/dracut/driver-updates
@@ -252,8 +252,10 @@ def get_module_set(fname):
                     modules.update([mod_args[0]])
     return modules
 
+def to_modname(modfile):
+    return os.path.basename(modfile)[:-3].replace('-','_')
 
-def reload_modules():
+def reload_modules(newfiles):
     """ Reload new module versions from /lib/modules/<kernel>/updates/
     """
     try:
@@ -267,6 +269,12 @@ def reload_modules():
     new_modules = current_modules.difference(startup_modules)
     log.debug("new_modules = %s", " ".join(new_modules))
 
+    # And a list of modules contained in the disk we just extracted
+    dd_modules = set(to_modname(f) for f in newfiles if f.endswith(".ko"))
+    # TODO: what modules do we unload when there's new firmware?
+    log.debug("dd_modules = %s", " ".join(dd_modules))
+    new_modules.update(dd_modules)
+
     # I think we can just iterate once using modprobe -r to remove unused deps
     for module in new_modules:
         try:
@@ -369,7 +377,7 @@ def dd_extract(driver, dest_path="/updates/", kernel_ver=None):
         :type driver:     Driver object
         :param dest_path: Top directory of the destination path
         :type dest_path:  string
-        :returns:         None
+        :returns:         list of paths to extracted firmware and modules
 
         This extracts the driver's files into 'dest_path' (which defaults
         to /updates/ so that the normal live updates handling will overlay
@@ -402,12 +410,15 @@ def dd_extract(driver, dest_path="/updates/", kernel_ver=None):
         if not os.path.exists(d):
             os.makedirs(d)
 
+    filelist = []
+
     # Copy *.ko files over to /updates/lib/modules/<kernel>/updates/
     for root, _dirs, files in os.walk(dest_path+"/lib/modules/"):
         if root.endswith("/updates") and os.path.isdir(root):
             continue
         for f in (f for f in files if f.endswith(".ko")):
             src = root+"/"+f
+            filelist.append(src)
             copy_file(src, ko_updates)
             move_file(src, initrd_updates)
 
@@ -417,9 +428,13 @@ def dd_extract(driver, dest_path="/updates/", kernel_ver=None):
             continue
         for f in (f for f in files):
             src = root+"/"+f
+            filelist.append(src)
             copy_file(src, firmware_updates)
             move_file(src, initrd_firmware)
 
+    # Tell our caller about the newly-extracted stuff
+    return filelist
+
 
 # an arbitrary value to signal refreshing the menu contents
 DoRefresh = True
@@ -542,15 +557,17 @@ def process_dd(dd_path):
     # Copy the repository for Anaconda to use during install
     copy_repo(dd_path, "/updates/run/install/DD-")
 
+    extracted = []
+
     for driver in filter(lambda d: d.selected, drivers):
-        dd_extract(driver, "/updates/")
+        extracted += dd_extract(driver, "/updates/")
 
         # Write the package names for all modules and firmware for Anaconda
         if "modules" in driver.flags or "firmwares" in driver.flags:
             with open("/run/install/dd_packages", "a") as f:
                 f.write("%s\n" % driver.name)
 
-    reload_modules()
+    reload_modules(extracted)
 
 
 def select_dd(device):
-- 
1.9.0



More information about the anaconda-patches mailing list