When loading modules with other modules in the same linker file,
depending on each other, currently the kernel linker chokes. Example:
the uhub, uhci, ohci and usb modules are (for unrelated reasons) linked
into one big file. It is however impossible currently to preload that
file because the dependencies are not found if MODULE_DEPEND and
MODULE_VERSION are added in appropriate places.

Currently we do the following:

for all linker files
        (A) check dependencies for all modules in linker file
                against found_modules
        if resolves
                (B) add the modules to found_modules

The attached patch changes this to

for all linker files
        (B) create a list of modules in the file (file_modules)
        (A) check dependencies for all modules in linker file
                against found_modules and file_modules
        if resolves
                (C) concatenate file_modules to found_modules

Step A and B are reversed and a copy loop (C) has been added.


As a side effect it is now also possible for modules to depend on
themselves (usb_depend_on_usb):

% nm /modules/usb.ko | grep depend_on
00019bc0 d _uhub_depend_on_usb
00019e88 d _usb_depend_on_usb


Comments?

Nick

P.S.: I am aware of the people involved being at Usenix, so I'll
postpone committing this until they have had time to comment on it.
--
[EMAIL PROTECTED]
[EMAIL PROTECTED]                                          USB project
http://www.etla.net/~n_hibma/
Index: kern_linker.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_linker.c,v
retrieving revision 1.46
diff -w -u -r1.46 kern_linker.c
--- kern_linker.c       2000/05/26 02:04:34     1.46
+++ kern_linker.c       2000/06/19 23:36:24
@@ -923,11 +923,11 @@
  */
 
 static modlist_t
-modlist_lookup(const char *name)
+modlist_lookup(modlisthead_t *modules, const char *name)
 {
     modlist_t mod;
 
-    for (mod = TAILQ_FIRST(&found_modules); mod; mod = TAILQ_NEXT(mod, link)) {
+    for (mod = TAILQ_FIRST(modules); mod; mod = TAILQ_NEXT(mod, link)) {
        if (!strcmp(mod->name, name))
            return mod;
     }
@@ -960,10 +960,12 @@
     int                        i;
     int                        resolves;
     modlist_t          mod;
+    modlisthead_t      file_modules;
 
     TAILQ_INIT(&loaded_files);
     TAILQ_INIT(&depended_files);
     TAILQ_INIT(&found_modules);
+    TAILQ_INIT(&file_modules);
     error = 0;
 
     modptr = NULL;
@@ -1002,7 +1004,7 @@
            if (mp->md_type != MDT_VERSION)
                continue;
            modname = mp->md_cval;
-           if (modlist_lookup(modname) != NULL) {
+           if (modlist_lookup(&found_modules, modname) != NULL) {
                printf("module %s already present!\n", modname);
                /* XXX what can we do? this is a build error. :-( */
                continue;
@@ -1025,34 +1027,20 @@
     for (lf = TAILQ_FIRST(&loaded_files); lf; lf = TAILQ_NEXT(lf, loaded)) {
        deps = (struct linker_set*)
            linker_file_lookup_symbol(lf, MDT_SETNAME, 0);
-       /*
-        * First, look to see if we would successfully link with this stuff.
-        */
+
        resolves = 1;   /* unless we know otherwise */
+
        if (deps) {
-           for (i = 0; i < deps->ls_length; i++) {
-               mp = linker_reloc_ptr(lf, deps->ls_items[i]);
-               if (mp->md_type != MDT_DEPEND)
-                   continue;
-               modname = linker_reloc_ptr(lf, mp->md_cval);
-               if (modlist_lookup(modname) == NULL) {
-                   /* ok, the module isn't here yet, we are not finished */
-                   resolves = 0;
-               }
-           }
-       }
        /*
-        * OK, if we found our modules, we can link.  So, "provide" the
-        * modules inside and add it to the end of the link order list.
+            * First, find all the modules that are contained in the file.
         */
-       if (resolves) {
-           if (deps) {
                for (i = 0; i < deps->ls_length; i++) {
                    mp = linker_reloc_ptr(lf, deps->ls_items[i]);
                    if (mp->md_type != MDT_VERSION)
                        continue;
                    modname = linker_reloc_ptr(lf, mp->md_cval);
-                   if (modlist_lookup(modname) != NULL) {
+               if (modlist_lookup(&found_modules, modname) != NULL
+                   || modlist_lookup(&file_modules, modname) != NULL) {
                        printf("module %s already present!\n", modname);
                        linker_file_unload(lf);
                        TAILQ_REMOVE(&loaded_files, lf, loaded);
@@ -1064,9 +1052,38 @@
                    bzero(mod, sizeof(*mod));
                    mod->container = lf;
                    mod->name = modname;
-                   TAILQ_INSERT_TAIL(&found_modules, mod, link);
+               TAILQ_INSERT_TAIL(&file_modules, mod, link);
+           }
+
+           /*
+            * Then, look to see if we would successfully link with this stuff.
+            */
+           for (i = 0; i < deps->ls_length; i++) {
+               mp = linker_reloc_ptr(lf, deps->ls_items[i]);
+               if (mp->md_type != MDT_DEPEND)
+                   continue;
+               modname = linker_reloc_ptr(lf, mp->md_cval);
+               if (modlist_lookup(&found_modules, modname) == NULL
+                   && modlist_lookup(&file_modules, modname) == NULL) {
+                   /* ok, the module isn't here yet, we are not finished */
+                   resolves = 0;
                }
            }
+       }
+       /*
+        * OK, if we found our modules, we can link.  So, "provide" the
+        * modules inside and add it to the end of the link order list.
+        */
+       if (resolves) {
+           /*
+            * Copy the list of modules found in the file into the global
+            * list of modules available.
+            */
+           while ((mod = TAILQ_FIRST(&file_modules))) {
+               TAILQ_REMOVE(&file_modules, mod, link);
+               TAILQ_INSERT_TAIL(&found_modules, mod, link);
+           }
+ 
            TAILQ_REMOVE(&loaded_files, lf, loaded);
            TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
            /*
@@ -1075,6 +1092,11 @@
             * Also, we've busted the tailq next pointer with the REMOVE.
             */
            goto restart;
+       } else {
+           while ((mod = TAILQ_FIRST(&file_modules))) {
+               TAILQ_REMOVE(&file_modules, mod, link);
+               free(mod, M_LINKER);
+           }
        }
     }
 
@@ -1106,7 +1128,7 @@
                if (mp->md_type != MDT_DEPEND)
                    continue;
                modname = linker_reloc_ptr(lf, mp->md_cval);
-               mod = modlist_lookup(modname);
+               mod = modlist_lookup(&found_modules, modname);
                mod->container->refs++;
                error = linker_file_add_dependancy(lf, mod->container);
                if (error)
@@ -1311,7 +1333,7 @@
            if (mp->md_type != MDT_VERSION)
                continue;
            modname = linker_reloc_ptr(lf, mp->md_cval);
-           if (modlist_lookup(modname) != NULL) {
+           if (modlist_lookup(&found_modules, modname) != NULL) {
                printf("module %s already present!\n", modname);
                return EEXIST;
            }
@@ -1334,7 +1356,7 @@
            }
            if (j < deps->ls_length)    /* early exit, it's a self reference */
                continue;
-           mod = modlist_lookup(modname);
+           mod = modlist_lookup(&found_modules, modname);
            if (mod) {          /* woohoo, it's loaded already */
                lfdep = mod->container;
                lfdep->refs++;

Reply via email to