modprobe-small: make depmod compatible with kernel build.
authorDenis Vlasenko <vda.linux@googlemail.com>
Thu, 10 Jul 2008 14:16:11 +0000 (14:16 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Thu, 10 Jul 2008 14:16:11 +0000 (14:16 -0000)
 three last commits' sizes combined:

function                                             old     new   delta
find_alias                                           218     612    +394
load_dep_bb                                            -     310    +310
modprobe_main                                        289     380     +91
copy_stringbuf                                         -      40     +40
process_module                                       637     655     +18
reset_stringbuf                                        -      15     +15
parse_module                                         333     334      +1
append                                                84      85      +1
fileAction                                           832     819     -13
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 5/1 up/down: 870/-13)           Total: 857 bytes

modutils/Config.in
modutils/modprobe-small.c

index 2e7f9b6e5182e6a209b8037920692f997461d7b5..40da1ac7a679ef52fe53f050f058a6487deec91d 100644 (file)
@@ -11,23 +11,31 @@ config MODPROBE_SMALL
        help
          Simplified modutils.
 
-         With this option modprobe does not use or require
-         modules.dep or /etc/modules.conf files.
+         With this option modprobe does not require modules.dep file
+         and does not use /etc/modules.conf file.
          It scans module files in /lib/modules/`uname -r` and
          determines dependencies and module alias names on the fly.
          This may make module loading slower, most notably
          when one needs to load module by alias (this requires
          scanning through module _bodies_).
 
+         At the first attempt to load a module by alias modprobe
+         will try to generate modules.dep.bb file in order to speed up
+         future loads by alias. Failure to do so (read-only /lib/modules,
+         etc) is not reported, and future modprobes will be slow too.
+
+         NB: modules.dep.bb file format is not compatible
+         with modules.dep file as created/used by standard module tools.
+
          Additional module parameters can be stored in
          /etc/modules/$module_name files.
 
          Apart from modprobe, other utilities are also provided:
          - insmod is an alias to modprobe
          - rmmod is an alias to modprobe -r
-         - depmod is provided but does nothing
+         - depmod generates modules.dep.bb
 
-         As of 2008-07, this code is experimental. It it 15kb smaller
+         As of 2008-07, this code is experimental. It it 14kb smaller
          than "non-small" modutils.
 
 config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
index cf9be47a6a05d27bf869804e396d8320336f5f55..f28c42558f4c8002bdf47a1dcc7f1e313029dcfe 100644 (file)
@@ -44,6 +44,7 @@ struct globals {
        module_info *modinfo;
        char *module_load_options;
        smallint dep_bb_seen;
+       smallint wrote_dep_bb_ok;
        int module_count;
        int module_found_idx;
        int stringbuf_idx;
@@ -53,6 +54,7 @@ struct globals {
 #define G (*ptr_to_globals)
 #define modinfo             (G.modinfo            )
 #define dep_bb_seen         (G.dep_bb_seen        )
+#define wrote_dep_bb_ok     (G.wrote_dep_bb_ok    )
 #define module_count        (G.module_count       )
 #define module_found_idx    (G.module_found_idx   )
 #define module_load_options (G.module_load_options)
@@ -236,15 +238,16 @@ static void parse_module(module_info *info, const char *pathname)
                                break;
                        /* DOCME: __ksymtab_gpl and __ksymtab_strings occur
                         * in many modules. What do they mean? */
-                       if (strcmp(ptr, "gpl") != 0 && strcmp(ptr, "strings") != 0) {
-                               dbg2_error_msg("alias:'symbol:%s'", ptr);
-                               append("symbol:");
-                       }
+                       if (strcmp(ptr, "gpl") == 0 || strcmp(ptr, "strings") == 0)
+                               goto skip;
+                       dbg2_error_msg("alias:'symbol:%s'", ptr);
+                       append("symbol:");
                } else {
                        dbg2_error_msg("alias:'%s'", ptr);
                }
                append(ptr);
                appendc(' ');
+ skip:
                pos = (ptr - module_image);
        }
        bksp(); /* remove last ' ' */
@@ -379,6 +382,10 @@ static int start_dep_bb_writeout(void)
 {
        int fd;
 
+       /* depmod -n: write result to stdout */
+       if (applet_name[0] == 'd' && (option_mask32 & 1))
+               return STDOUT_FILENO;
+
        fd = open(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644);
        if (fd < 0) {
                if (errno == EEXIST) {
@@ -421,13 +428,19 @@ static void write_out_dep_bb(int fd)
        }
        /* Badly formatted depfile is a no-no. Be paranoid. */
        errno = 0;
-       if (ferror(fp) | fclose(fp))
+       if (ferror(fp) | fclose(fp)) /* | instead of || is intended */
                goto err;
+
+       if (fd == STDOUT_FILENO) /* it was depmod -n */
+               goto ok;
+
        if (rename(DEPFILE_BB".new", DEPFILE_BB) != 0) {
  err:
                bb_perror_msg("can't create %s", DEPFILE_BB);
                unlink(DEPFILE_BB".new");
        } else {
+ ok:
+               wrote_dep_bb_ok = 1;
                dbg1_error_msg("created "DEPFILE_BB);
        }
 }
@@ -525,8 +538,10 @@ static int already_loaded(const char *name)
 #endif
 
 /*
- Given modules definition and module name (or alias, or symbol)
- load/remove the module respecting dependencies
+ * Given modules definition and module name (or alias, or symbol)
+ * load/remove the module respecting dependencies.
+ * NB: also called by depmod with bogus name "/",
+ * just in order to force modprobe.dep.bb creation.
 */
 #if !ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
 #define process_module(a,b) process_module(a)
@@ -605,8 +620,10 @@ static void process_module(char *name, const char *cmdline_options)
                 * will try to remove them, too." */
        }
 
-       if (!info) { /* both dirscan and find_alias found nothing */
-               bb_error_msg("module '%s' not found", name);
+       if (!info) {
+               /* both dirscan and find_alias found nothing */
+               if (applet_name[0] != 'd') /* it wasn't depmod */
+                       bb_error_msg("module '%s' not found", name);
 //TODO: _and_die()?
                goto ret;
        }
@@ -644,39 +661,51 @@ static void process_module(char *name, const char *cmdline_options)
 #undef cmdline_options
 
 
-/* For reference, module-init-tools-0.9.15-pre2 options:
+/* For reference, module-init-tools v3.4 options:
 
 # insmod
 Usage: insmod filename [args]
 
 # rmmod --help
 Usage: rmmod [-fhswvV] modulename ...
- -f (or --force) forces a module unload, and may crash your machine.
+ -f (or --force) forces a module unload, and may crash your
+    machine. This requires the Forced Module Removal option
+    when the kernel was compiled.
+ -h (or --help) prints this help text
  -s (or --syslog) says use syslog, not stderr
  -v (or --verbose) enables more messages
+ -V (or --version) prints the version code
  -w (or --wait) begins a module removal even if it is used
     and will stop new users from accessing the module (so it
     should eventually fall to zero).
 
 # modprobe
-Usage: modprobe [--verbose|--version|--config|--remove] filename [options]
+Usage: modprobe [-v] [-V] [-C config-file] [-n] [-i] [-q] [-b]
+    [-o <modname>] [ --dump-modversions ] <modname> [parameters...]
+modprobe -r [-n] [-i] [-v] <modulename> ...
+modprobe -l -t <dirname> [ -a <modulename> ...]
 
 # depmod --help
-depmod 0.9.15-pre2 -- part of module-init-tools
-depmod -[aA] [-n -e -v -q -V -r -u] [-b basedirectory] [forced_version]
-depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.o module2.o ...
-If no arguments (except options) are given, "depmod -a" is assumed
-
+depmod 3.4 -- part of module-init-tools
+depmod -[aA] [-n -e -v -q -V -r -u]
+      [-b basedirectory] [forced_version]
+depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.ko module2.ko ...
+If no arguments (except options) are given, "depmod -a" is assumed.
 depmod will output a dependancy list suitable for the modprobe utility.
-
 Options:
-        -a, --all               Probe all modules
-        -n, --show              Write the dependency file on stdout only
-        -b basedirectory
-        --basedir basedirectory Use an image of a module tree.
-        -F kernelsyms
-        --filesyms kernelsyms   Use the file instead of the
-                                current kernel symbols.
+    -a, --all            Probe all modules
+    -A, --quick          Only does the work if there's a new module
+    -n, --show           Write the dependency file on stdout only
+    -e, --errsyms        Report not supplied symbols
+    -V, --version        Print the release version
+    -v, --verbose        Enable verbose mode
+    -h, --help           Print this usage message
+The following options are useful for people managing distributions:
+    -b basedirectory
+        --basedir basedirectory    Use an image of a module tree.
+    -F kernelsyms
+        --filesyms kernelsyms      Use the file instead of the
+                                   current kernel symbols.
 */
 
 int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -686,10 +715,6 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
        char applet0 = applet_name[0];
        USE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;)
 
-       /* depmod is a stub */
-       if ('d' == applet0)
-               return EXIT_SUCCESS;
-
        /* are we lsmod? -> just dump /proc/modules */
        if ('l' == applet0) {
                xprint_and_close_file(xfopen("/proc/modules", "r"));
@@ -698,6 +723,45 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
 
        INIT_G();
 
+       /* Prevent ugly corner cases with no modules at all */
+       modinfo = xzalloc(sizeof(modinfo[0]));
+
+       /* Goto modules directory */
+       xchdir(CONFIG_DEFAULT_MODULES_DIR);
+       uname(&uts); /* never fails */
+
+       /* depmod? */
+       if ('d' == applet0) {
+               /* Supported:
+                * -n: print result to stdout
+                * -a: process all modules (default)
+                * optional VERSION parameter
+                * Ignored:
+                * -A: do work only if a module is newer than depfile
+                * -e: report any symbols which a module needs
+                *  which are not supplied by other modules or the kernel
+                * -F FILE: System.map (symbols for -e)
+                * -q, -r, -u: noop?
+                * Not supported:
+                * -b BASEDIR: (TODO!) modules are in
+                *  $BASEDIR/lib/modules/$VERSION
+                * -v: human readable deps to stdout
+                * -V: version (don't want to support it - people may depend
+                *  on it as an indicator of "standard" depmod)
+                * -h: help (well duh)
+                * module1.o module2.o parameters (just ignored for now)
+                */
+               getopt32(argv, "na" "AeF:qru" /* "b:vV", NULL */, NULL);
+               argv += optind;
+               /* if (argv[0] && argv[1]) bb_show_usage(); */
+               /* Goto $VERSION directory */
+               xchdir(argv[0] ? argv[0] : uts.release);
+               /* Force full module scan by asking to find a bogus module.
+                * This will generate modules.dep.bb as a side effect. */
+               process_module((char*)"/", NULL);
+               return !wrote_dep_bb_ok;
+       }
+
        /* insmod, modprobe, rmmod require at least one argument */
        opt_complementary = "-1";
        /* only -q (quiet) and -r (rmmod),
@@ -710,9 +774,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
                option_mask32 |= OPT_r;
        }
 
-       /* goto modules directory */
-       xchdir(CONFIG_DEFAULT_MODULES_DIR);
-       uname(&uts); /* never fails */
+       /* Goto $VERSION directory */
        xchdir(uts.release);
 
 #if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
@@ -734,9 +796,6 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
                argv[1] = NULL;
 #endif
 
-       /* Prevent ugly corner cases with no modules at all */
-       modinfo = xzalloc(sizeof(modinfo[0]));
-
        /* Try to load modprobe.dep.bb */
        load_dep_bb();