From 8c1051918e1aaf7610ddb0e6ef5cb6d97abe3d82 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 29 Oct 2019 08:38:55 -0700 Subject: [PATCH] libmodprobe: Do not reload modules previously instantiated For modprobe operation. For an interlocking driver set of about 50 modules, the impact of their dependencies resulted in a 30 second impact in boot time trying to load previously loaded modules. This impact is handily eliminated by keeping a list of modules paths that have been loaded and skipping them proactively. Test: Confirmed device boot and 50 module set of drivers functions. Test: libmodprobe_tests Bug: 142938937 Bug: 140827934 Change-Id: Iccd11399d6043b38cbd5f93578ee202022e7770c --- libmodprobe/include/modprobe/modprobe.h | 2 ++ libmodprobe/libmodprobe.cpp | 8 +++++++- libmodprobe/libmodprobe_ext.cpp | 9 +++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h index dcb4ffbef..421d82644 100644 --- a/libmodprobe/include/modprobe/modprobe.h +++ b/libmodprobe/include/modprobe/modprobe.h @@ -19,6 +19,7 @@ #include #include #include +#include #include class Modprobe { @@ -59,5 +60,6 @@ class Modprobe { std::vector module_load_; std::unordered_map module_options_; std::set module_blacklist_; + std::unordered_set module_loaded_; bool blacklist_enabled = false; }; diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp index 73ae15b07..3c78ec999 100644 --- a/libmodprobe/libmodprobe.cpp +++ b/libmodprobe/libmodprobe.cpp @@ -330,7 +330,12 @@ bool Modprobe::InsmodWithDeps(const std::string& module_name, const std::string& bool Modprobe::LoadWithAliases(const std::string& module_name, bool strict, const std::string& parameters) { - std::set modules_to_load = {MakeCanonical(module_name)}; + auto canonical_name = MakeCanonical(module_name); + if (module_loaded_.count(canonical_name)) { + return true; + } + + std::set modules_to_load = {canonical_name}; bool module_loaded = false; // use aliases to expand list of modules to load (multiple modules @@ -338,6 +343,7 @@ bool Modprobe::LoadWithAliases(const std::string& module_name, bool strict, for (const auto& [alias, aliased_module] : module_aliases_) { if (fnmatch(alias.c_str(), module_name.c_str(), 0) != 0) continue; LOG(VERBOSE) << "Found alias for '" << module_name << "': '" << aliased_module; + if (module_loaded_.count(MakeCanonical(aliased_module))) continue; modules_to_load.emplace(aliased_module); } diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp index 2efcac290..8bebe4c9f 100644 --- a/libmodprobe/libmodprobe_ext.cpp +++ b/libmodprobe/libmodprobe_ext.cpp @@ -30,8 +30,9 @@ bool Modprobe::Insmod(const std::string& path_name, const std::string& parameter return false; } + auto canonical_name = MakeCanonical(path_name); std::string options = ""; - auto options_iter = module_options_.find(MakeCanonical(path_name)); + auto options_iter = module_options_.find(canonical_name); if (options_iter != module_options_.end()) { options = options_iter->second; } @@ -44,6 +45,7 @@ bool Modprobe::Insmod(const std::string& path_name, const std::string& parameter if (ret != 0) { if (errno == EEXIST) { // Module already loaded + module_loaded_.emplace(canonical_name); return true; } LOG(ERROR) << "Failed to insmod '" << path_name << "' with args '" << options << "'"; @@ -51,15 +53,18 @@ bool Modprobe::Insmod(const std::string& path_name, const std::string& parameter } LOG(INFO) << "Loaded kernel module " << path_name; + module_loaded_.emplace(canonical_name); return true; } bool Modprobe::Rmmod(const std::string& module_name) { - int ret = syscall(__NR_delete_module, MakeCanonical(module_name).c_str(), O_NONBLOCK); + auto canonical_name = MakeCanonical(module_name); + int ret = syscall(__NR_delete_module, canonical_name.c_str(), O_NONBLOCK); if (ret != 0) { PLOG(ERROR) << "Failed to remove module '" << module_name << "'"; return false; } + module_loaded_.erase(canonical_name); return true; }