Commit | Line | Data |
---|---|---|
096102bd DG |
1 | /* |
2 | * Copyright (C) 2011 - David Goulet <dgoulet@efficios.com> | |
3 | * | |
d14d33bf AM |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License, version 2 only, | |
6 | * as published by the Free Software Foundation. | |
096102bd | 7 | * |
d14d33bf AM |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
096102bd | 12 | * |
d14d33bf AM |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., | |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
096102bd DG |
16 | */ |
17 | ||
18 | #define _GNU_SOURCE | |
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <sys/wait.h> | |
22 | ||
23 | #include <common/common.h> | |
24 | ||
25 | #include "modprobe.h" | |
26 | #include "kern-modules.h" | |
27 | ||
ab57d7d3 JG |
28 | #define LTTNG_MOD_REQUIRED 1 |
29 | #define LTTNG_MOD_OPTIONAL 0 | |
30 | ||
31 | /* LTTng kernel tracer mandatory core modules list */ | |
32 | struct kern_modules_param kern_modules_control_core[] = { | |
33 | { "lttng-tracer" }, /* MUST be loaded first so keep at top */ | |
34 | { "lttng-lib-ring-buffer" }, | |
35 | { "lttng-ring-buffer-client-discard" }, | |
36 | { "lttng-ring-buffer-client-overwrite" }, | |
37 | { "lttng-ring-buffer-metadata-client" }, | |
38 | { "lttng-ring-buffer-client-mmap-discard" }, | |
39 | { "lttng-ring-buffer-client-mmap-overwrite" }, | |
40 | { "lttng-ring-buffer-metadata-mmap-client" }, | |
41 | }; | |
42 | ||
43 | /* LTTng kernel tracer optional base modules list */ | |
44 | struct kern_modules_param kern_modules_control_opt[] = { | |
45 | { "lttng-types" }, | |
46 | { "lttng-ftrace" }, | |
47 | { "lttng-kprobes" }, | |
48 | { "lttng-kretprobes" }, | |
3fa9646c JG |
49 | }; |
50 | ||
51 | /* LTTng kernel tracer probe modules list */ | |
52 | const struct kern_modules_param kern_modules_probes[] = { | |
ab57d7d3 JG |
53 | { "lttng-probe-asoc" }, |
54 | { "lttng-probe-block" }, | |
55 | { "lttng-probe-btrfs" }, | |
56 | { "lttng-probe-compaction" }, | |
57 | { "lttng-probe-ext3" }, | |
58 | { "lttng-probe-ext4" }, | |
59 | { "lttng-probe-gpio" }, | |
60 | { "lttng-probe-irq" }, | |
61 | { "lttng-probe-jbd" }, | |
62 | { "lttng-probe-jbd2" }, | |
63 | { "lttng-probe-kmem" }, | |
64 | { "lttng-probe-kvm" }, | |
65 | { "lttng-probe-kvm-x86" }, | |
66 | { "lttng-probe-kvm-x86-mmu" }, | |
67 | { "lttng-probe-lock" }, | |
68 | { "lttng-probe-module" }, | |
69 | { "lttng-probe-napi" }, | |
70 | { "lttng-probe-net" }, | |
71 | { "lttng-probe-power" }, | |
72 | { "lttng-probe-printk" }, | |
73 | { "lttng-probe-random" }, | |
74 | { "lttng-probe-rcu" }, | |
75 | { "lttng-probe-regmap" }, | |
76 | { "lttng-probe-regulator" }, | |
77 | { "lttng-probe-rpm" }, | |
78 | { "lttng-probe-sched" }, | |
79 | { "lttng-probe-scsi" }, | |
80 | { "lttng-probe-signal" }, | |
81 | { "lttng-probe-skb" }, | |
82 | { "lttng-probe-sock" }, | |
83 | { "lttng-probe-statedump" }, | |
84 | { "lttng-probe-sunrpc" }, | |
85 | { "lttng-probe-timer" }, | |
86 | { "lttng-probe-udp" }, | |
87 | { "lttng-probe-vmscan" }, | |
88 | { "lttng-probe-v4l2" }, | |
89 | { "lttng-probe-workqueue" }, | |
90 | { "lttng-probe-writeback" }, | |
096102bd DG |
91 | }; |
92 | ||
e23b81ed | 93 | void modprobe_remove_lttng(const struct kern_modules_param *modules, |
ab57d7d3 | 94 | int entries, int required) |
096102bd DG |
95 | { |
96 | int ret = 0, i; | |
97 | char modprobe[256]; | |
98 | ||
e23b81ed | 99 | for (i = entries - 1; i >= 0; i--) { |
096102bd DG |
100 | ret = snprintf(modprobe, sizeof(modprobe), |
101 | "/sbin/modprobe -r -q %s", | |
e23b81ed | 102 | modules[i].name); |
096102bd DG |
103 | if (ret < 0) { |
104 | PERROR("snprintf modprobe -r"); | |
ab57d7d3 | 105 | return; |
096102bd DG |
106 | } |
107 | modprobe[sizeof(modprobe) - 1] = '\0'; | |
108 | ret = system(modprobe); | |
109 | if (ret == -1) { | |
110 | ERR("Unable to launch modprobe -r for module %s", | |
ab57d7d3 JG |
111 | modules[i].name); |
112 | } else if (required && WEXITSTATUS(ret) != 0) { | |
096102bd | 113 | ERR("Unable to remove module %s", |
ab57d7d3 | 114 | modules[i].name); |
096102bd DG |
115 | } else { |
116 | DBG("Modprobe removal successful %s", | |
ab57d7d3 | 117 | modules[i].name); |
096102bd DG |
118 | } |
119 | } | |
e23b81ed JG |
120 | } |
121 | ||
122 | /* | |
123 | * Remove control kernel module(s) in reverse load order. | |
124 | */ | |
125 | void modprobe_remove_lttng_control(void) | |
126 | { | |
ab57d7d3 JG |
127 | modprobe_remove_lttng(kern_modules_control_opt, |
128 | ARRAY_SIZE(kern_modules_control_opt), | |
129 | LTTNG_MOD_OPTIONAL); | |
130 | modprobe_remove_lttng(kern_modules_control_core, | |
131 | ARRAY_SIZE(kern_modules_control_core), | |
132 | LTTNG_MOD_REQUIRED); | |
096102bd DG |
133 | } |
134 | ||
135 | /* | |
136 | * Remove data kernel modules in reverse load order. | |
137 | */ | |
138 | void modprobe_remove_lttng_data(void) | |
139 | { | |
3fa9646c | 140 | return modprobe_remove_lttng(kern_modules_probes, |
ab57d7d3 JG |
141 | ARRAY_SIZE(kern_modules_probes), |
142 | LTTNG_MOD_OPTIONAL); | |
096102bd DG |
143 | } |
144 | ||
145 | /* | |
146 | * Remove all kernel modules in reverse order. | |
147 | */ | |
148 | void modprobe_remove_lttng_all(void) | |
149 | { | |
150 | modprobe_remove_lttng_data(); | |
151 | modprobe_remove_lttng_control(); | |
152 | } | |
153 | ||
ab57d7d3 JG |
154 | static int modprobe_lttng(const struct kern_modules_param *modules, |
155 | int entries, int required) | |
096102bd DG |
156 | { |
157 | int ret = 0, i; | |
158 | char modprobe[256]; | |
159 | ||
e23b81ed | 160 | for (i = 0; i < entries; i++) { |
096102bd DG |
161 | ret = snprintf(modprobe, sizeof(modprobe), |
162 | "/sbin/modprobe %s%s", | |
ab57d7d3 | 163 | required ? "" : "-q ", |
e23b81ed | 164 | modules[i].name); |
096102bd DG |
165 | if (ret < 0) { |
166 | PERROR("snprintf modprobe"); | |
167 | goto error; | |
168 | } | |
169 | modprobe[sizeof(modprobe) - 1] = '\0'; | |
170 | ret = system(modprobe); | |
171 | if (ret == -1) { | |
172 | ERR("Unable to launch modprobe for module %s", | |
e23b81ed | 173 | modules[i].name); |
ab57d7d3 JG |
174 | } else if (required && WEXITSTATUS(ret) != 0) { |
175 | ERR("Unable to load module %s", modules[i].name); | |
096102bd | 176 | } else { |
ab57d7d3 | 177 | DBG("Modprobe successfully %s", modules[i].name); |
096102bd DG |
178 | } |
179 | } | |
180 | ||
181 | error: | |
182 | return ret; | |
183 | } | |
184 | ||
e23b81ed JG |
185 | /* |
186 | * Load control kernel module(s). | |
187 | */ | |
188 | int modprobe_lttng_control(void) | |
189 | { | |
ab57d7d3 JG |
190 | int ret; |
191 | ||
192 | ret = modprobe_lttng(kern_modules_control_core, | |
193 | ARRAY_SIZE(kern_modules_control_core), | |
194 | LTTNG_MOD_REQUIRED); | |
195 | if (ret != 0) | |
196 | return ret; | |
197 | ret = modprobe_lttng(kern_modules_control_opt, | |
198 | ARRAY_SIZE(kern_modules_control_opt), | |
199 | LTTNG_MOD_OPTIONAL); | |
200 | return ret; | |
e23b81ed | 201 | } |
ab57d7d3 | 202 | |
096102bd DG |
203 | /* |
204 | * Load data kernel module(s). | |
205 | */ | |
206 | int modprobe_lttng_data(void) | |
207 | { | |
3fa9646c | 208 | return modprobe_lttng(kern_modules_probes, |
ab57d7d3 JG |
209 | ARRAY_SIZE(kern_modules_probes), |
210 | LTTNG_MOD_OPTIONAL); | |
096102bd | 211 | } |