Android-x86
Fork
Faire un don

  • R/O
  • HTTP
  • SSH
  • HTTPS

system-core: Commit

system/core


Commit MetaInfo

Révision0cb6bfa5a77734efdb6bb1027298e8566b56d260 (tree)
l'heure2017-12-26 19:43:19
AuteurChih-Wei Huang <cwhuang@linu...>
CommiterChih-Wei Huang

Message de Log

ueventd: auto load modules on uevents

This is an almost rewritten patch which implements the auto modules
loading function for oreo-x86.

The commits from nougat-x86 are squashed:

* ueventd: defer modules loading if explicitly listed

* ueventd: auto load modules on uevents

Change Summary

Modification

--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -32,7 +32,6 @@
3232 #include <sys/resource.h>
3333 #include <sys/socket.h>
3434 #include <sys/stat.h>
35-#include <sys/syscall.h>
3635 #include <sys/system_properties.h>
3736 #include <sys/time.h>
3837 #include <sys/types.h>
@@ -47,6 +46,7 @@
4746 #include <android-base/strings.h>
4847 #include <bootloader_message/bootloader_message.h>
4948 #include <cutils/android_reboot.h>
49+#include <cutils/probe_module.h>
5050 #include <ext4_utils/ext4_crypt.h>
5151 #include <ext4_utils/ext4_crypt_init_extensions.h>
5252 #include <fs_mgr.h>
@@ -73,20 +73,6 @@ namespace init {
7373
7474 static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
7575
76-static int insmod(const char *filename, const char *options, int flags) {
77- int fd = open(filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
78- if (fd == -1) {
79- PLOG(ERROR) << "insmod: open(\"" << filename << "\") failed";
80- return -1;
81- }
82- int rc = syscall(__NR_finit_module, fd, options, flags);
83- if (rc == -1) {
84- PLOG(ERROR) << "finit_module for \"" << filename << "\" failed";
85- }
86- close(fd);
87- return rc;
88-}
89-
9076 static int __ifupdown(const char *interface, int up) {
9177 struct ifreq ifr;
9278 int s, ret;
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -22,6 +22,8 @@
2222 #include <unistd.h>
2323
2424 #include <memory>
25+#include <set>
26+#include <thread>
2527
2628 #include <android-base/logging.h>
2729 #include <android-base/stringprintf.h>
@@ -29,9 +31,11 @@
2931 #include <private/android_filesystem_config.h>
3032 #include <selinux/android.h>
3133 #include <selinux/selinux.h>
34+#include <cutils/probe_module.h>
3235
3336 #include "ueventd.h"
3437 #include "util.h"
38+#include "init_parser.h"
3539
3640 #ifdef _INIT_INIT_H
3741 #error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals"
@@ -374,6 +378,7 @@ void DeviceHandler::HandleDevice(const std::string& action, const std::string& d
374378
375379 void DeviceHandler::HandleDeviceEvent(const Uevent& uevent) {
376380 if (uevent.action == "add" || uevent.action == "change" || uevent.action == "online") {
381+ LoadModule(uevent);
377382 FixupSysPermissions(uevent.path, uevent.subsystem);
378383 }
379384
@@ -420,6 +425,88 @@ void DeviceHandler::HandleDeviceEvent(const Uevent& uevent) {
420425 HandleDevice(uevent.action, devpath, block, uevent.major, uevent.minor, links);
421426 }
422427
428+void DeviceHandler::HandleModuleEvent(const Uevent& uevent, std::vector<std::string>& mod_queue)
429+{
430+ if (!uevent.modalias.empty() && uevent.action == "add") {
431+ if (mod_aliases_.empty()) {
432+ ReadModulesDescFiles();
433+ }
434+ for (auto& entry : deferred_mod_aliases_) {
435+ if (!fnmatch(entry.first.c_str(), uevent.modalias.c_str(), 0)) {
436+ mod_queue.emplace_back(entry.second);
437+ }
438+ }
439+ }
440+}
441+
442+bool DeviceHandler::LoadModule(const Uevent& uevent) const
443+{
444+ bool ret = false;
445+ if (!uevent.modalias.empty()) {
446+ for (auto& entry : mod_aliases_) {
447+ if (!fnmatch(entry.first.c_str(), uevent.modalias.c_str(), 0)) {
448+ ret |= LoadModule(entry.second);
449+ }
450+ }
451+ }
452+ return ret;
453+}
454+
455+bool DeviceHandler::LoadModule(const std::string& mod) const
456+{
457+ bool ret = !insmod_by_dep(mod.c_str(), "", NULL, 0, NULL);
458+ if (!ret) {
459+ PLOG(WARNING) << "failed to load " << mod;
460+ }
461+ return ret;
462+}
463+
464+void DeviceHandler::ReadModulesDescFiles()
465+{
466+ auto line_parser = [] (auto args, auto err, std::set<std::string>* set_) -> bool {
467+ if (args.size() < 2) {
468+ *err = "must have 2 entries";
469+ return false;
470+ }
471+
472+ set_->emplace(args[1]);
473+ return true;
474+ };
475+ using namespace std::placeholders;
476+ std::set<std::string> blacklist, deferred;
477+
478+ Parser parser;
479+ parser.AddSingleLineParser("blacklist", std::bind(line_parser, _1, _2, &blacklist));
480+ parser.AddSingleLineParser("deferred", std::bind(line_parser, _1, _2, &deferred));
481+
482+ // wait until the file is ready
483+ while (!parser.ParseConfig("/system/etc/modules.blacklist")) {
484+ std::this_thread::sleep_for(100ms);
485+ }
486+
487+ parser.AddSingleLineParser("alias", [&] (auto args, auto err) {
488+ if (args.size() < 3) {
489+ *err = "must have 3 entries";
490+ return false;
491+ }
492+ if (deferred.find(args[2]) != deferred.end()) {
493+ deferred_mod_aliases_.emplace(args[1], args[2]);
494+ } else if (blacklist.find(args[2]) == blacklist.end()) {
495+ mod_aliases_.emplace(args[1], args[2]);
496+ }
497+ return true;
498+ });
499+ char alias[PATH_MAX];
500+ strlcat(get_default_mod_path(alias), "modules.alias", PATH_MAX);
501+ parser.ParseConfig(alias);
502+}
503+
504+void DeviceHandler::OnColdBootDone()
505+{
506+ mod_aliases_.insert(deferred_mod_aliases_.begin(), deferred_mod_aliases_.end());
507+ deferred_mod_aliases_.clear();
508+}
509+
423510 DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
424511 std::vector<SysfsPermissions> sysfs_permissions,
425512 std::vector<Subsystem> subsystems, bool skip_restorecon)
--- a/init/devices.h
+++ b/init/devices.h
@@ -22,6 +22,7 @@
2222
2323 #include <algorithm>
2424 #include <string>
25+#include <map>
2526 #include <vector>
2627
2728 #include <android-base/file.h>
@@ -107,6 +108,11 @@ class DeviceHandler {
107108 ~DeviceHandler(){};
108109
109110 void HandleDeviceEvent(const Uevent& uevent);
111+ void HandleModuleEvent(const Uevent& uevent, std::vector<std::string>& mod_queue);
112+ bool LoadModule(const Uevent& uevent) const;
113+ bool LoadModule(const std::string& mod) const;
114+ void ReadModulesDescFiles();
115+ void OnColdBootDone();
110116
111117 std::vector<std::string> GetBlockDeviceSymlinks(const Uevent& uevent) const;
112118 void set_skip_restorecon(bool value) { skip_restorecon_ = value; }
@@ -124,6 +130,8 @@ class DeviceHandler {
124130 std::vector<Permissions> dev_permissions_;
125131 std::vector<SysfsPermissions> sysfs_permissions_;
126132 std::vector<Subsystem> subsystems_;
133+ std::multimap<std::string, std::string> mod_aliases_;
134+ std::multimap<std::string, std::string> deferred_mod_aliases_;
127135 selabel_handle* sehandle_;
128136 bool skip_restorecon_;
129137 std::string sysfs_mount_point_;
--- a/init/uevent.h
+++ b/init/uevent.h
@@ -29,6 +29,7 @@ struct Uevent {
2929 std::string firmware;
3030 std::string partition_name;
3131 std::string device_name;
32+ std::string modalias;
3233 int partition_num;
3334 int major;
3435 int minor;
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -39,6 +39,7 @@ static void ParseEvent(const char* msg, Uevent* uevent) {
3939 uevent->firmware.clear();
4040 uevent->partition_name.clear();
4141 uevent->device_name.clear();
42+ uevent->modalias.clear();
4243 // currently ignoring SEQNUM
4344 while (*msg) {
4445 if (!strncmp(msg, "ACTION=", 7)) {
@@ -68,6 +69,9 @@ static void ParseEvent(const char* msg, Uevent* uevent) {
6869 } else if (!strncmp(msg, "DEVNAME=", 8)) {
6970 msg += 8;
7071 uevent->device_name = msg;
72+ } else if (!strncmp(msg, "MODALIAS=", 9)) {
73+ msg += 9;
74+ uevent->modalias = msg;
7175 }
7276
7377 // advance to after the next \0
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -125,6 +125,7 @@ class ColdBoot {
125125
126126 unsigned int num_handler_subprocesses_;
127127 std::vector<Uevent> uevent_queue_;
128+ std::vector<std::string> mod_queue_;
128129
129130 std::set<pid_t> subprocess_pids_;
130131 };
@@ -140,7 +141,7 @@ void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_pr
140141 void ColdBoot::RegenerateUevents() {
141142 uevent_listener_.RegenerateUevents([this](const Uevent& uevent) {
142143 HandleFirmwareEvent(uevent);
143-
144+ device_handler_.HandleModuleEvent(uevent, mod_queue_);
144145 uevent_queue_.emplace_back(std::move(uevent));
145146 return ListenerAction::kContinue;
146147 });
@@ -210,6 +211,11 @@ void ColdBoot::Run() {
210211
211212 WaitForSubProcesses();
212213
214+ device_handler_.OnColdBootDone();
215+ for (auto& mod : mod_queue_) {
216+ device_handler_.LoadModule(mod);
217+ }
218+
213219 close(open(COLDBOOT_DONE, O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
214220 KLOG_NOTICE("Coldboot", "took %f seconds", cold_boot_timer.duration().count() / 1000.0f);
215221 }
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -109,6 +109,7 @@ cc_library {
109109 "ashmem-dev.c",
110110 "klog.cpp",
111111 "partition_utils.c",
112+ "probe_module.c",
112113 "properties.cpp",
113114 "qtaguid.c",
114115 "trace-dev.c",
--- /dev/null
+++ b/libcutils/include/cutils/probe_module.h
@@ -0,0 +1,106 @@
1+/*
2+ * Copyright (C) 2012 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+#ifndef _LIBS_CUTILS_PROBEMODULE_H
18+#define _LIBS_CUTILS_PROBEMODULE_H
19+
20+#ifdef __cplusplus
21+extern "C" {
22+#endif
23+
24+/* get_default_mod_path() - get the default modules path
25+ * It checks /system/lib/modules/$(uname -r)/ first. If it doesn't exist,
26+ * fall back to /system/lib/modules/.
27+ *
28+ * def_mod_path: The buffer to be filled
29+ *
30+ * return : def_mod_path
31+ */
32+extern char *get_default_mod_path(char *def_mod_path);
33+
34+/* insmod() - load a kernel module (target) from a file
35+ *
36+ * filename : Filename of the target module.
37+ *
38+ * args : A string of target module's parameters. NOTE: we only
39+ * support parameters of the target module.
40+ *
41+ * flags : MODULE_INIT_* flags defined in module.h
42+ *
43+ * return : 0 for success; -1 indicates an error
44+ */
45+extern int insmod(const char *filename, const char *options, int flags);
46+
47+/* insmod_by_dep() - load a kernel module (target) with its dependency
48+ * The module's dependency must be described in the provided dependency file.
49+ * other modules in the dependency chain will be loaded prior to the target.
50+ *
51+ * module_name: Name of the target module. e.g. name "MyModule" is for
52+ * module file MyModule.ko.
53+ *
54+ * args : A string of target module's parameters. NOTE: we only
55+ * support parameters of the target module.
56+ *
57+ * dep_name : Name of dependency file. If it is NULL, we will look
58+ * up /system/lib/modules/modules.dep by default.
59+ *
60+ * strip : Non-zero values remove paths of modules in dependency.
61+ * before loading them. The final path of a module will be
62+ * base/MyModule.ko. This is for devices which put every
63+ * modules into a single directory.
64+ *
65+ * Passing 0 to strip keeps module paths in dependency file.
66+ * e.g. "kernel/drivers/.../MyModule.ko" in dep file will
67+ * be loaded as base/kernel/drivers/.../MyModule.ko .
68+ *
69+ * base : Base dir, a prefix to be added to module's path prior to
70+ * loading. The last character prior to base string's terminator
71+ * must be a '/'. If it is NULL, we will take
72+ * /system/lib/modules/modules.dep by default.
73+ *
74+ * return : 0 for success; non-zero for any errors.
75+ *
76+ * Note:
77+ * When loading modules, function will not fail for any modules which are
78+ * already in kernel. The module parameters passed to function will not be
79+ * effective in this case if target module is already loaded into kernel.
80+ */
81+extern int insmod_by_dep(
82+ const char *module_name,
83+ const char *args,
84+ const char *dep_name,
85+ int strip,
86+ const char * base);
87+
88+/* rmmod_by_dep() - remove a module (target) from kernel with its dependency
89+ * The module's dependency must be described in the provided dependency file.
90+ * This function will try to remove other modules in the dependency chain too
91+ *
92+ * module_name: Name of the target module. e.g. name "MyModule" is for
93+ * module file MyModule.ko.
94+ *
95+ * dep_name : Name of dependency file. If it is NULL, we will look
96+ * up /system/lib/modules/modules.dep by default.
97+ *
98+ * return : 0 for success; non-zero for any errors.
99+ */
100+extern int rmmod_by_dep(const char *module_name, const char *dep_name);
101+
102+#ifdef __cplusplus
103+}
104+#endif
105+
106+#endif /*_LIBS_CUTILS_PROBEMODULE_H*/
--- /dev/null
+++ b/libcutils/probe_module.c
@@ -0,0 +1,386 @@
1+/*
2+ * Copyright (C) 2012 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+#include <stdio.h>
18+#include <stdlib.h>
19+#include <string.h>
20+#include <limits.h>
21+#include <errno.h>
22+#include <fcntl.h>
23+#include <cutils/misc.h>
24+#include <sys/syscall.h>
25+#include <sys/utsname.h>
26+
27+#define LOG_TAG "ProbeModule"
28+#include <cutils/log.h>
29+
30+#define LDM_DEFAULT_MOD_PATH "/system/lib/modules/"
31+
32+extern int delete_module(const char *, unsigned int);
33+
34+/* get_default_mod_path() interface to outside,
35+ * refer to its description in probe_module.h
36+ */
37+char *get_default_mod_path(char *def_mod_path)
38+{
39+ int len;
40+ struct utsname buf;
41+ uname(&buf);
42+ len = snprintf(def_mod_path, PATH_MAX, "%s", LDM_DEFAULT_MOD_PATH);
43+ strcpy(def_mod_path + len, buf.release);
44+ if (access(def_mod_path, F_OK))
45+ def_mod_path[len] = '\0';
46+ else
47+ strcat(def_mod_path, "/");
48+ return def_mod_path;
49+}
50+
51+int insmod(const char *filename, const char *options, int flags)
52+{
53+ int fd = open(filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
54+ if (fd == -1) {
55+ ALOGE("insmod: open(\"%s\") failed: %s", filename, strerror(errno));
56+ return -1;
57+ }
58+ int rc = syscall(__NR_finit_module, fd, options, flags);
59+ if (rc == -1) {
60+ if (errno == EEXIST) {
61+ rc = 0;
62+ } else {
63+ ALOGE("finit_module for \"%s\" failed: %s", filename, strerror(errno));
64+ }
65+ }
66+ close(fd);
67+ return rc;
68+}
69+
70+static char *strip_path(char *str)
71+{
72+ char *ptr = strrchr(str, '/');
73+ return ptr ? ptr + 1 : str;
74+}
75+
76+static void hyphen_to_underscore(char *str)
77+{
78+ while (str && *str != '\0') {
79+ if (*str == '-')
80+ *str = '_';
81+ str++;
82+ }
83+}
84+
85+/* Compare module names, but don't differentiate '_' and '-'.
86+ * return: 0 when s1 is matched to s2 or size is zero.
87+ * non-zero in any other cases.
88+ */
89+static int match_name(const char *s1, const char *s2, const size_t size)
90+{
91+ size_t i;
92+
93+ if (!size)
94+ return 0;
95+
96+ for (i = 0; i < size; i++, s1++, s2++) {
97+
98+ if ((*s1 == '_' || *s1 == '-') && (*s2 == '_' || *s2 == '-'))
99+ continue;
100+
101+ if (*s1 != *s2)
102+ return -1;
103+
104+ if (*s1 == '\0')
105+ return 0;
106+ }
107+
108+ return 0;
109+}
110+
111+/* check if a line in dep file is target module's dependency.
112+ * return 1 when it is, otherwise 0 in any other cases.
113+ */
114+static int is_target_module(char *line, const char *target)
115+{
116+ char *token;
117+ char name[PATH_MAX];
118+ const char *delimiter = ":";
119+ int ret = 0;
120+
121+ /* search token */
122+ token = strstr(line, delimiter);
123+
124+ if (!token) {
125+ ALOGE("invalid line: no token");
126+ return 0;
127+ }
128+
129+ /* only take stuff before the token */
130+ *token = '\0';
131+
132+ /* use "module.ko" in comparision */
133+ strcat(strcpy(name, target), ".ko");
134+
135+ ret = !match_name(strip_path(line), name, strlen(name));
136+
137+ /* restore [single] token, keep line unchanged until we parse it later */
138+ *token = *delimiter;
139+
140+ return ret;
141+
142+}
143+
144+/* turn a single string into an array of dependency.
145+ *
146+ * return: dependency array's address if it succeeded. Caller
147+ * is responsible to free the array's memory.
148+ * NULL when any error happens.
149+ */
150+static char **setup_dep(char *line)
151+{
152+ char *tmp = line;
153+ char *brk;
154+ int i;
155+ char **dep;
156+
157+ for (i = 2; (tmp = strchr(tmp, ' ')); i++)
158+ tmp++;
159+
160+ dep = malloc(sizeof(char *) * i);
161+ if (dep) {
162+ i = 0;
163+ do {
164+ tmp = strtok_r(i ? NULL : line, ": ", &brk);
165+ } while ((dep[i++] = tmp));
166+ }
167+
168+ return dep;
169+}
170+
171+/* install all modules in the dependency chain
172+ * deps : A array of module file names, must be terminated by a NULL pointer
173+ * args : The module parameters for target module.
174+ * strip : Non-zero to strip out path info in the file name;
175+ * 0 to keep path info when loading modules.
176+ * base : a prefix to module path, it will NOT be affected by strip flag.
177+ * return : 0 for success or nothing to do; non-zero when any error occurs.
178+ */
179+static int insmod_s(char *dep[], const char *args, int strip, const char *base)
180+{
181+ char *name;
182+ int cnt;
183+ size_t len;
184+ int ret = 0;
185+ char path_name[PATH_MAX];
186+ char def_mod_path[PATH_MAX];
187+ const char *base_dir;
188+
189+ if (base && strlen(base))
190+ base_dir = base;
191+ else
192+ base_dir = get_default_mod_path(def_mod_path);
193+
194+ /* load modules in reversed order */
195+ for (cnt = 0; dep[cnt]; cnt++)
196+ ;
197+
198+ len = strlen(strcpy(path_name, base_dir));
199+
200+ while (!ret && cnt--) {
201+
202+ name = strip ? strip_path(dep[cnt]) : dep[cnt];
203+
204+ strcpy(path_name + len, name);
205+
206+ ret = insmod(path_name, cnt ? "" : args, 0);
207+ }
208+
209+ return ret;
210+}
211+
212+/* remove all modules in a dependency chain
213+ * NOTE: We assume module name in kernel is same as the file name without .ko
214+ */
215+static int rmmod_s(char *dep[], int flags)
216+{
217+ int i;
218+ int ret = 0;
219+
220+ for (i = 0; dep[i]; i++) {
221+ char *mod_name = strip_path(dep[i]);
222+ size_t len = strlen(mod_name);
223+
224+ if (len > 3 && strstr(mod_name, ".ko") == (mod_name + len - 3)) {
225+ mod_name[len - 3] = '\0';
226+
227+ hyphen_to_underscore(mod_name);
228+
229+ ret = delete_module(mod_name, flags);
230+
231+ if (ret) {
232+ ALOGE("%s: Failed to remove module [%s] error (%s)",
233+ __FUNCTION__, mod_name, strerror(errno));
234+ break;
235+
236+ }
237+ }
238+ }
239+
240+ return ret;
241+}
242+
243+/* look_up_dep() find and setup target module's dependency in modules.dep
244+ *
245+ * dep_file: a pointer to module's dep file loaded in memory, its content
246+ * will be CHANGED during parsing.
247+ *
248+ * return: a pointer to an array which holds the dependency strings and
249+ * terminated by a NULL pointer. Caller is responsible to free the
250+ * array's memory.
251+ *
252+ * non-zero in any other cases. Content of dep array is invalid.
253+ */
254+static char **look_up_dep(const char *module_name, void *dep_file)
255+{
256+ char *line;
257+ char *saved_pos;
258+ char *start;
259+ char **dep = NULL;
260+
261+ if (!dep_file || !module_name || *module_name == '\0')
262+ return NULL;
263+
264+ start = (char *)dep_file;
265+
266+ /* We expect modules.dep file has a new line char before EOF. */
267+ while ((line = strtok_r(start, "\n", &saved_pos)) != NULL) {
268+
269+ start = NULL;
270+
271+ if (is_target_module(line, module_name)) {
272+
273+ dep = setup_dep(line);
274+ /* job done */
275+ break;
276+ }
277+ }
278+
279+ return dep;
280+}
281+
282+/* load_dep_file() load a dep file (usually it is modules.dep)
283+ * into memory. Caller is responsible to free the memory.
284+ *
285+ * file_name: dep file's name, if it is NULL or an empty string,
286+ * This function will try to load a dep file in the
287+ * default path defined in LDM_DEFAULT_DEP_FILE
288+ *
289+ * return: a pointer to the allocated mem which holds all
290+ * content of the depfile. a zero pointer will be
291+ * returned for any errors.
292+ * */
293+static void *load_dep_file(const char *file_name)
294+{
295+ unsigned int len;
296+ char def_mod_path[PATH_MAX];
297+ if (!file_name || *file_name == '\0') {
298+ file_name = get_default_mod_path(def_mod_path);
299+ strcat(def_mod_path, "modules.dep");
300+ }
301+
302+ return load_file(file_name, &len);
303+}
304+
305+/* insmod_by_dep() interface to outside,
306+ * refer to its description in probe_module.h
307+ */
308+int insmod_by_dep(const char *module_name,
309+ const char *args,
310+ const char *dep_name,
311+ int strip,
312+ const char *base)
313+{
314+ void *dep_file;
315+ char **dep = NULL;
316+ int ret = -1;
317+
318+ if (!module_name || *module_name == '\0') {
319+ ALOGE("need valid module name");
320+ return ret;
321+ }
322+
323+ dep_file = load_dep_file(dep_name);
324+
325+ if (!dep_file) {
326+ ALOGE("cannot load dep file : %s", dep_name);
327+ return ret;
328+ }
329+
330+ dep = look_up_dep(module_name, dep_file);
331+
332+ if (!dep) {
333+ ALOGE("%s: cannot load module: [%s]", __FUNCTION__, module_name);
334+ goto free_file;
335+ }
336+
337+ ret = insmod_s(dep, args, strip, base);
338+
339+ free(dep);
340+
341+free_file:
342+ free(dep_file);
343+
344+ return ret;
345+
346+}
347+
348+/* rmmod_by_dep() interface to outside,
349+ * refer to its description in probe_module.h
350+ */
351+int rmmod_by_dep(const char *module_name, const char *dep_name)
352+{
353+ void *dep_file;
354+ char **dep = NULL;
355+ int ret = -1;
356+
357+ if (!module_name || *module_name == '\0') {
358+ ALOGE("need valid module name");
359+ return ret;
360+ }
361+
362+ dep_file = load_dep_file(dep_name);
363+
364+ if (!dep_file) {
365+ ALOGE("cannot load dep file : %s", dep_name);
366+ return ret;
367+ }
368+
369+ dep = look_up_dep(module_name, dep_file);
370+
371+ if (!dep) {
372+ ALOGE("%s: cannot remove module: [%s]", __FUNCTION__, module_name);
373+ goto free_file;
374+ }
375+
376+ ret = rmmod_s(dep, O_NONBLOCK);
377+
378+ free(dep);
379+
380+free_file:
381+ free(dep_file);
382+
383+ return ret;
384+}
385+
386+/* end of file */
Afficher sur ancien navigateur de dépôt.