Browse Source

Check all modalias files in /sys/devices for modules

and add the corresponding kernel modules to the host module list

https://bugzilla.redhat.com/show_bug.cgi?id=1467427
master
Harald Hoyer 8 years ago
parent
commit
3ad12c7be8
  1. 17
      dracut-init.sh
  2. 171
      install/dracut-install.c

17
dracut-init.sh

@ -52,13 +52,6 @@ if ! [[ -d $initdir ]]; then
mkdir -p "$initdir" mkdir -p "$initdir"
fi fi


if [[ $DRACUT_KERNEL_LAZY ]] && ! [[ $DRACUT_KERNEL_LAZY_HASHDIR ]]; then
if ! [[ -d "$initdir/.kernelmodseen" ]]; then
mkdir -p "$initdir/.kernelmodseen"
fi
DRACUT_KERNEL_LAZY_HASHDIR="$initdir/.kernelmodseen"
fi

if ! [[ $kernel ]]; then if ! [[ $kernel ]]; then
kernel=$(uname -r) kernel=$(uname -r)
export kernel export kernel
@ -172,6 +165,13 @@ if ! [[ -x $DRACUT_INSTALL ]]; then
exit 10 exit 10
fi fi


if [[ $hostonly == "-h" ]]; then
if ! [[ $DRACUT_KERNEL_MODALIASES ]] || ! [[ -d "$DRACUT_KERNEL_MODALIASES" ]]; then
export DRACUT_KERNEL_MODALIASES="${DRACUT_TMPDIR}/modaliases"
$DRACUT_INSTALL --modalias > "$DRACUT_KERNEL_MODALIASES"
fi
fi

[[ $DRACUT_RESOLVE_LAZY ]] || export DRACUT_RESOLVE_DEPS=1 [[ $DRACUT_RESOLVE_LAZY ]] || export DRACUT_RESOLVE_DEPS=1
inst_dir() { inst_dir() {
[[ -e ${initdir}/"$1" ]] && return 0 # already there [[ -e ${initdir}/"$1" ]] && return 0 # already there
@ -935,9 +935,6 @@ for_each_kmod_dep() {
} }


dracut_kernel_post() { dracut_kernel_post() {
local _moddirname=${srcmods%%/lib/modules/*}
local _pid

for _f in modules.builtin.bin modules.builtin modules.order; do for _f in modules.builtin.bin modules.builtin modules.order; do
[[ $srcmods/$_f ]] && inst_simple "$srcmods/$_f" "/lib/modules/$kernel/$_f" [[ $srcmods/$_f ]] && inst_simple "$srcmods/$_f" "/lib/modules/$kernel/$_f"
done done

171
install/dracut-install.c

@ -41,6 +41,7 @@
#include <libkmod.h> #include <libkmod.h>
#include <fts.h> #include <fts.h>
#include <regex.h> #include <regex.h>
#include <sys/utsname.h>


#include "log.h" #include "log.h"
#include "hashmap.h" #include "hashmap.h"
@ -54,6 +55,7 @@ static bool arg_optional = false;
static bool arg_silent = false; static bool arg_silent = false;
static bool arg_all = false; static bool arg_all = false;
static bool arg_module = false; static bool arg_module = false;
static bool arg_modalias = false;
static bool arg_resolvelazy = false; static bool arg_resolvelazy = false;
static bool arg_resolvedeps = false; static bool arg_resolvedeps = false;
static bool arg_hostonly = false; static bool arg_hostonly = false;
@ -794,6 +796,7 @@ static void usage(int status)
" --kerneldir Specify the kernel module directory\n" " --kerneldir Specify the kernel module directory\n"
" --firmwaredirs Specify the firmware directory search path with : separation\n" " --firmwaredirs Specify the firmware directory search path with : separation\n"
" --silent Don't display error messages for kernel module install\n" " --silent Don't display error messages for kernel module install\n"
" --modalias Only generate module list from /sys/devices modalias list\n"
" -o --optional If kernel module does not exist, do not fail\n" " -o --optional If kernel module does not exist, do not fail\n"
" -p --mod-filter-path Filter kernel modules by path regexp\n" " -p --mod-filter-path Filter kernel modules by path regexp\n"
" -P --mod-filter-nopath Exclude kernel modules by path regexp\n" " -P --mod-filter-nopath Exclude kernel modules by path regexp\n"
@ -818,6 +821,7 @@ static int parse_argv(int argc, char *argv[])
enum { enum {
ARG_VERSION = 0x100, ARG_VERSION = 0x100,
ARG_SILENT, ARG_SILENT,
ARG_MODALIAS,
ARG_KERNELDIR, ARG_KERNELDIR,
ARG_FIRMWAREDIRS, ARG_FIRMWAREDIRS,
ARG_DEBUG ARG_DEBUG
@ -843,6 +847,7 @@ static int parse_argv(int argc, char *argv[])
{"mod-filter-symbol", required_argument, NULL, 's'}, {"mod-filter-symbol", required_argument, NULL, 's'},
{"mod-filter-nosymbol", required_argument, NULL, 'S'}, {"mod-filter-nosymbol", required_argument, NULL, 'S'},
{"mod-filter-noname", required_argument, NULL, 'N'}, {"mod-filter-noname", required_argument, NULL, 'N'},
{"modalias", no_argument, NULL, ARG_MODALIAS},
{"silent", no_argument, NULL, ARG_SILENT}, {"silent", no_argument, NULL, ARG_SILENT},
{"kerneldir", required_argument, NULL, ARG_KERNELDIR}, {"kerneldir", required_argument, NULL, ARG_KERNELDIR},
{"firmwaredirs", required_argument, NULL, ARG_FIRMWAREDIRS}, {"firmwaredirs", required_argument, NULL, ARG_FIRMWAREDIRS},
@ -863,6 +868,10 @@ static int parse_argv(int argc, char *argv[])
case ARG_SILENT: case ARG_SILENT:
arg_silent = true; arg_silent = true;
break; break;
case ARG_MODALIAS:
arg_modalias = true;
return 1;
break;
case 'v': case 'v':
arg_loglevel = LOG_INFO; arg_loglevel = LOG_INFO;
break; break;
@ -949,6 +958,16 @@ static int parse_argv(int argc, char *argv[])
} }
} }


if (!kerneldir) {
struct utsname buf;
uname(&buf);
kerneldir = strdup(buf.version);
}

if (arg_modalias) {
return 1;
}

if (arg_module) { if (arg_module) {
if (!firmwaredirs) { if (!firmwaredirs) {
char *path = NULL; char *path = NULL;
@ -965,6 +984,7 @@ static int parse_argv(int argc, char *argv[])
firmwaredirs = strv_split(path, ":"); firmwaredirs = strv_split(path, ":");
} }
} }

if (!optind || optind == argc) { if (!optind || optind == argc) {
log_error("No SOURCE argument given"); log_error("No SOURCE argument given");
usage(EXIT_FAILURE); usage(EXIT_FAILURE);
@ -1297,12 +1317,94 @@ static int install_module(struct kmod_module *mod)
return ret; return ret;
} }


static int install_modules(int argc, char **argv) static int modalias_list(struct kmod_ctx *ctx)
{ {
_cleanup_kmod_unref_ struct kmod_ctx *ctx = NULL; int err;
struct kmod_list *loaded_list = NULL; struct kmod_list *loaded_list = NULL;
struct kmod_list *itr, *l; struct kmod_list *itr, *l;
int err; _cleanup_fts_close_ FTS *fts = NULL;

{
char *paths[] = { "/sys/devices", NULL };
fts = fts_open(paths, FTS_NOCHDIR|FTS_NOSTAT, NULL);
}
for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_kmod_module_unref_list_ struct kmod_list *list = NULL;
struct kmod_list *l;

int err;

char alias[2048];
size_t len;

if (strncmp("modalias", ftsent->fts_name, 8) != 0)
continue;
if (!(f = fopen(ftsent->fts_accpath, "r")))
continue;

if(!fgets(alias, sizeof(alias), f))
continue;

len = strlen(alias);

if (len == 0)
continue;

if (alias[len-1] == '\n')
alias[len-1] = 0;

err = kmod_module_new_from_lookup(ctx, alias, &list);
if (err < 0)
continue;

kmod_list_foreach(l, list) {
struct kmod_module *mod = kmod_module_get_module(l);
char *name = strdup(kmod_module_get_name(mod));
kmod_module_unref(mod);
hashmap_put(modules_loaded, name, name);
}
}

err = kmod_module_new_from_loaded(ctx, &loaded_list);
if (err < 0) {
errno = err;
log_error("Could not get list of loaded modules: %m. Switching to non-hostonly mode.");
arg_hostonly = false;
} else {
kmod_list_foreach(itr, loaded_list) {
_cleanup_kmod_module_unref_list_ struct kmod_list *modlist = NULL;

struct kmod_module *mod = kmod_module_get_module(itr);
char *name = strdup(kmod_module_get_name(mod));
hashmap_put(modules_loaded, name, name);
kmod_module_unref(mod);

/* also put the modules from the new kernel in the hashmap,
* which resolve the name as an alias, in case a kernel module is
* renamed.
*/
err = kmod_module_new_from_lookup(ctx, name, &modlist);
if (err < 0)
continue;
if (!modlist)
continue;
kmod_list_foreach(l, modlist) {
mod = kmod_module_get_module(l);
char *name = strdup(kmod_module_get_name(mod));
hashmap_put(modules_loaded, name, name);
kmod_module_unref(mod);
}
}
kmod_module_unref_list(loaded_list);
}
return 0;
}

static int install_modules(int argc, char **argv)
{
_cleanup_kmod_unref_ struct kmod_ctx *ctx = NULL;
struct kmod_list *itr;


struct kmod_module *mod = NULL, *mod_o = NULL; struct kmod_module *mod = NULL, *mod_o = NULL;


@ -1311,38 +1413,34 @@ static int install_modules(int argc, char **argv)


ctx = kmod_new(kerneldir, NULL); ctx = kmod_new(kerneldir, NULL);
if (arg_hostonly) { if (arg_hostonly) {
err = kmod_module_new_from_loaded(ctx, &loaded_list); char *modalias_file;
if (err < 0) { modalias_file = getenv("DRACUT_KERNEL_MODALIASES");
errno = err;
log_error("Could not get list of loaded modules: %m. Switching to non-hostonly mode."); if (modalias_file == NULL) {
arg_hostonly = false; modalias_list(ctx);
} else { } else {
kmod_list_foreach(itr, loaded_list) { _cleanup_fclose_ FILE *f = NULL;
_cleanup_kmod_module_unref_list_ struct kmod_list *modlist = NULL; if ((f = fopen(modalias_file, "r"))) {
char name[2048];


struct kmod_module *mod = kmod_module_get_module(itr); while (!feof(f)) {
char *name = strdup(kmod_module_get_name(mod)); size_t len;
hashmap_put(modules_loaded, name, name);
kmod_module_unref(mod);


/* also put the modules from the new kernel in the hashmap, if(!(fgets(name, sizeof(name), f)))
* which resolve the name as an alias, in case a kernel module is continue;
* renamed. len = strlen(name);
*/
err = kmod_module_new_from_lookup(ctx, name, &modlist); if (len == 0)
if (err < 0) continue;
continue;
if (!modlist) if (name[len-1] == '\n')
continue; name[len-1] = 0;
kmod_list_foreach(l, modlist) {
mod = kmod_module_get_module(l); hashmap_put(modules_loaded, name, strdup(name));
char *name = strdup(kmod_module_get_name(mod));
hashmap_put(modules_loaded, name, name);
kmod_module_unref(mod);
} }
} }
kmod_module_unref_list(loaded_list);
} }

} }


for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
@ -1576,6 +1674,20 @@ int main(int argc, char **argv)


log_open(); log_open();


modules_loaded = hashmap_new(string_hash_func, string_compare_func);
if (arg_modalias) {
Iterator i;
char *name;
_cleanup_kmod_unref_ struct kmod_ctx *ctx = NULL;
ctx = kmod_new(kerneldir, NULL);

modalias_list(ctx);
HASHMAP_FOREACH(name, modules_loaded, i) {
printf("%s\n", name);
}
exit(0);
}

path = getenv("PATH"); path = getenv("PATH");


if (path == NULL) { if (path == NULL) {
@ -1614,7 +1726,6 @@ int main(int argc, char **argv)


items = hashmap_new(string_hash_func, string_compare_func); items = hashmap_new(string_hash_func, string_compare_func);
items_failed = hashmap_new(string_hash_func, string_compare_func); items_failed = hashmap_new(string_hash_func, string_compare_func);
modules_loaded = hashmap_new(string_hash_func, string_compare_func);


if (!items || !items_failed || !modules_loaded) { if (!items || !items_failed || !modules_loaded) {
log_error("Out of memory"); log_error("Out of memory");

Loading…
Cancel
Save