Fix: sessiond: make the --without-lttng-ust version of launch_application_notificatio...
[lttng-tools.git] / src / bin / lttng-sessiond / modprobe.c
1 /*
2 * Copyright (C) 2011 David Goulet <dgoulet@efficios.com>
3 * Copyright (C) 2014 Jan Glauber <jan.glauber@gmail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 */
8
9 /**
10 * @file modprobe.c
11 *
12 * @brief modprobe related functions.
13 *
14 */
15
16 #define _LGPL_SOURCE
17 #include <assert.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/wait.h>
21
22 #include <common/common.h>
23 #include <common/utils.h>
24
25 #include "modprobe.h"
26 #include "kern-modules.h"
27 #include "lttng-sessiond.h"
28
29 #define LTTNG_MOD_REQUIRED 1
30 #define LTTNG_MOD_OPTIONAL 0
31
32 /* LTTng kernel tracer mandatory core modules list */
33 struct kern_modules_param kern_modules_control_core[] = {
34 { (char *) "lttng-ring-buffer-client-discard" },
35 { (char *) "lttng-ring-buffer-client-overwrite" },
36 { (char *) "lttng-ring-buffer-metadata-client" },
37 { (char *) "lttng-ring-buffer-client-mmap-discard" },
38 { (char *) "lttng-ring-buffer-client-mmap-overwrite" },
39 { (char *) "lttng-ring-buffer-metadata-mmap-client" },
40 };
41
42 /* LTTng kernel tracer probe modules list */
43 struct kern_modules_param kern_modules_probes_default[] = {
44 { (char *) "lttng-probe-asoc" },
45 { (char *) "lttng-probe-block" },
46 { (char *) "lttng-probe-btrfs" },
47 { (char *) "lttng-probe-compaction" },
48 { (char *) "lttng-probe-ext3" },
49 { (char *) "lttng-probe-ext4" },
50 { (char *) "lttng-probe-gpio" },
51 { (char *) "lttng-probe-i2c" },
52 { (char *) "lttng-probe-irq" },
53 { (char *) "lttng-probe-jbd" },
54 { (char *) "lttng-probe-jbd2" },
55 { (char *) "lttng-probe-kmem" },
56 { (char *) "lttng-probe-kvm" },
57 { (char *) "lttng-probe-kvm-x86" },
58 { (char *) "lttng-probe-kvm-x86-mmu" },
59 { (char *) "lttng-probe-lock" },
60 { (char *) "lttng-probe-module" },
61 { (char *) "lttng-probe-napi" },
62 { (char *) "lttng-probe-net" },
63 { (char *) "lttng-probe-power" },
64 { (char *) "lttng-probe-preemptirq" },
65 { (char *) "lttng-probe-printk" },
66 { (char *) "lttng-probe-random" },
67 { (char *) "lttng-probe-rcu" },
68 { (char *) "lttng-probe-regmap" },
69 { (char *) "lttng-probe-regulator" },
70 { (char *) "lttng-probe-rpm" },
71 { (char *) "lttng-probe-sched" },
72 { (char *) "lttng-probe-scsi" },
73 { (char *) "lttng-probe-signal" },
74 { (char *) "lttng-probe-skb" },
75 { (char *) "lttng-probe-sock" },
76 { (char *) "lttng-probe-statedump" },
77 { (char *) "lttng-probe-sunrpc" },
78 { (char *) "lttng-probe-timer" },
79 { (char *) "lttng-probe-udp" },
80 { (char *) "lttng-probe-vmscan" },
81 { (char *) "lttng-probe-v4l2" },
82 { (char *) "lttng-probe-workqueue" },
83 { (char *) "lttng-probe-writeback" },
84 { (char *) "lttng-probe-x86-irq-vectors" },
85 { (char *) "lttng-probe-x86-exceptions" },
86 };
87
88 /* dynamic probe modules list */
89 static struct kern_modules_param *probes;
90 static int nr_probes;
91 static int probes_capacity;
92
93 #if HAVE_KMOD
94 #include <libkmod.h>
95
96 /**
97 * @brief Logging function for libkmod integration.
98 */
99 static void log_kmod(void *data, int priority, const char *file, int line,
100 const char *fn, const char *format, va_list args)
101 {
102 char *str;
103
104 if (vasprintf(&str, format, args) < 0) {
105 return;
106 }
107
108 DBG("libkmod: %s", str);
109 free(str);
110 }
111
112 /**
113 * @brief Setup the libkmod context.
114 *
115 * Create the context, add a custom logging function and preload the
116 * ressources for faster operation.
117 *
118 * @returns \c 0 on success
119 * \c < 0 on error
120 */
121 static int setup_kmod_ctx(struct kmod_ctx **ctx)
122 {
123 int ret = 0;
124
125 *ctx = kmod_new(NULL, NULL);
126 if (!ctx) {
127 PERROR("Unable to create kmod library context");
128 ret = -ENOMEM;
129 goto error;
130 }
131
132 kmod_set_log_fn(*ctx, log_kmod, NULL);
133 ret = kmod_load_resources(*ctx);
134 if (ret < 0) {
135 ERR("Failed to load kmod library resources");
136 goto error;
137 }
138
139 error:
140 return ret;
141 }
142
143 /**
144 * @brief Loads the kernel modules in \p modules
145 *
146 * @param modules List of modules to load
147 * @param entries Number of modules in the list
148 * @param required Are the modules required or optionnal
149 *
150 * If the modules are required, we will return with error after the
151 * first failed module load, otherwise we continue loading.
152 *
153 * @returns \c 0 on success
154 * \c < 0 on error
155 */
156 static int modprobe_lttng(struct kern_modules_param *modules,
157 int entries, int required)
158 {
159 int ret = 0, i;
160 struct kmod_ctx *ctx;
161
162 ret = setup_kmod_ctx(&ctx);
163 if (ret < 0) {
164 goto error;
165 }
166
167 for (i = 0; i < entries; i++) {
168 struct kmod_module *mod = NULL;
169
170 ret = kmod_module_new_from_name(ctx, modules[i].name, &mod);
171 if (ret < 0) {
172 PERROR("Failed to create kmod module for %s", modules[i].name);
173 goto error;
174 }
175
176 ret = kmod_module_probe_insert_module(mod, 0,
177 NULL, NULL, NULL, NULL);
178 if (ret == -EEXIST) {
179 DBG("Module %s is already loaded", modules[i].name);
180 ret = 0;
181 } else if (ret < 0) {
182 if (required) {
183 ERR("Unable to load required module %s",
184 modules[i].name);
185 goto error;
186 } else {
187 DBG("Unable to load optional module %s; continuing",
188 modules[i].name);
189 ret = 0;
190 }
191 } else {
192 DBG("Modprobe successfully %s", modules[i].name);
193 modules[i].loaded = true;
194 }
195
196 kmod_module_unref(mod);
197 }
198
199 error:
200 if (ctx) {
201 kmod_unref(ctx);
202 }
203 return ret;
204 }
205
206 /**
207 * @brief Recursively unload modules.
208 *
209 * This function implements the same modules unloading behavior as
210 * 'modprobe -r' or rmmod, it will recursevily go trought the \p module
211 * dependencies and unload modules with a refcount of 0.
212 *
213 * @param mod The module to unload
214 *
215 * @returns \c 0 on success
216 * \c < 0 on error
217 */
218 static int rmmod_recurse(struct kmod_module *mod) {
219 int ret = 0;
220 struct kmod_list *deps, *itr;
221
222 if (kmod_module_get_initstate(mod) == KMOD_MODULE_BUILTIN) {
223 DBG("Module %s is builtin", kmod_module_get_name(mod));
224 return ret;
225 }
226
227 ret = kmod_module_remove_module(mod, 0);
228
229 deps = kmod_module_get_dependencies(mod);
230 if (deps != NULL) {
231 kmod_list_foreach(itr, deps) {
232 struct kmod_module *dep = kmod_module_get_module(itr);
233 if (kmod_module_get_refcnt(dep) == 0) {
234 DBG("Recursive remove module %s",
235 kmod_module_get_name(dep));
236 rmmod_recurse(dep);
237 }
238 kmod_module_unref(dep);
239 }
240 kmod_module_unref_list(deps);
241 }
242
243 return ret;
244 }
245
246 /**
247 * @brief Unloads the kernel modules in \p modules
248 *
249 * @param modules List of modules to unload
250 * @param entries Number of modules in the list
251 * @param required Are the modules required or optionnal
252 *
253 */
254 static void modprobe_remove_lttng(const struct kern_modules_param *modules,
255 int entries, int required)
256 {
257 int ret = 0, i;
258 struct kmod_ctx *ctx;
259
260 ret = setup_kmod_ctx(&ctx);
261 if (ret < 0) {
262 goto error;
263 }
264
265 for (i = entries - 1; i >= 0; i--) {
266 struct kmod_module *mod = NULL;
267
268 if (!modules[i].loaded) {
269 continue;
270 }
271
272 ret = kmod_module_new_from_name(ctx, modules[i].name, &mod);
273 if (ret < 0) {
274 PERROR("Failed to create kmod module for %s", modules[i].name);
275 goto error;
276 }
277
278 ret = rmmod_recurse(mod);
279 if (ret == -EEXIST) {
280 DBG("Module %s is not in kernel.", modules[i].name);
281 } else if (required && ret < 0) {
282 ERR("Unable to remove module %s", modules[i].name);
283 } else {
284 DBG("Modprobe removal successful %s",
285 modules[i].name);
286 }
287
288 kmod_module_unref(mod);
289 }
290
291 error:
292 if (ctx) {
293 kmod_unref(ctx);
294 }
295 }
296
297 #else /* HAVE_KMOD */
298
299 static int modprobe_lttng(struct kern_modules_param *modules,
300 int entries, int required)
301 {
302 int ret = 0, i;
303 char modprobe[256];
304
305 for (i = 0; i < entries; i++) {
306 ret = snprintf(modprobe, sizeof(modprobe),
307 "/sbin/modprobe %s%s",
308 required ? "" : "-q ",
309 modules[i].name);
310 if (ret < 0) {
311 PERROR("snprintf modprobe");
312 goto error;
313 }
314 modprobe[sizeof(modprobe) - 1] = '\0';
315 ret = system(modprobe);
316 if (ret == -1) {
317 if (required) {
318 ERR("Unable to launch modprobe for required module %s",
319 modules[i].name);
320 goto error;
321 } else {
322 DBG("Unable to launch modprobe for optional module %s; continuing",
323 modules[i].name);
324 ret = 0;
325 }
326 } else if (WEXITSTATUS(ret) != 0) {
327 if (required) {
328 ERR("Unable to load required module %s",
329 modules[i].name);
330 goto error;
331 } else {
332 DBG("Unable to load optional module %s; continuing",
333 modules[i].name);
334 ret = 0;
335 }
336 } else {
337 DBG("Modprobe successfully %s", modules[i].name);
338 modules[i].loaded = true;
339 }
340 }
341
342 error:
343 return ret;
344 }
345
346 static void modprobe_remove_lttng(const struct kern_modules_param *modules,
347 int entries, int required)
348 {
349 int ret = 0, i;
350 char modprobe[256];
351
352 for (i = entries - 1; i >= 0; i--) {
353 if (!modules[i].loaded) {
354 continue;
355 }
356 ret = snprintf(modprobe, sizeof(modprobe),
357 "/sbin/modprobe -r -q %s",
358 modules[i].name);
359 if (ret < 0) {
360 PERROR("snprintf modprobe -r");
361 return;
362 }
363 modprobe[sizeof(modprobe) - 1] = '\0';
364 ret = system(modprobe);
365 if (ret == -1) {
366 ERR("Unable to launch modprobe -r for module %s",
367 modules[i].name);
368 } else if (required && WEXITSTATUS(ret) != 0) {
369 ERR("Unable to remove module %s",
370 modules[i].name);
371 } else {
372 DBG("Modprobe removal successful %s",
373 modules[i].name);
374 }
375 }
376 }
377
378 #endif /* HAVE_KMOD */
379
380 /*
381 * Remove control kernel module(s) in reverse load order.
382 */
383 void modprobe_remove_lttng_control(void)
384 {
385 modprobe_remove_lttng(kern_modules_control_core,
386 ARRAY_SIZE(kern_modules_control_core),
387 LTTNG_MOD_REQUIRED);
388 }
389
390 static void free_probes(void)
391 {
392 int i;
393
394 if (!probes) {
395 return;
396 }
397 for (i = 0; i < nr_probes; ++i) {
398 free(probes[i].name);
399 }
400 free(probes);
401 probes = NULL;
402 nr_probes = 0;
403 }
404
405 /*
406 * Remove data kernel modules in reverse load order.
407 */
408 void modprobe_remove_lttng_data(void)
409 {
410 if (!probes) {
411 return;
412 }
413 modprobe_remove_lttng(probes, nr_probes, LTTNG_MOD_OPTIONAL);
414 free_probes();
415 }
416
417 /*
418 * Remove all kernel modules in reverse order.
419 */
420 void modprobe_remove_lttng_all(void)
421 {
422 modprobe_remove_lttng_data();
423 modprobe_remove_lttng_control();
424 }
425
426 /*
427 * Load control kernel module(s).
428 */
429 int modprobe_lttng_control(void)
430 {
431 int ret;
432
433 ret = modprobe_lttng(kern_modules_control_core,
434 ARRAY_SIZE(kern_modules_control_core),
435 LTTNG_MOD_REQUIRED);
436 return ret;
437 }
438
439 /**
440 * Grow global list of probes (double capacity or set it to 1 if
441 * currently 0 and copy existing data).
442 */
443 static int grow_probes(void)
444 {
445 int i;
446 struct kern_modules_param *tmp_probes;
447
448 /* Initialize capacity to 1 if 0. */
449 if (probes_capacity == 0) {
450 probes = zmalloc(sizeof(*probes));
451 if (!probes) {
452 PERROR("malloc probe list");
453 return -ENOMEM;
454 }
455
456 probes_capacity = 1;
457 return 0;
458 }
459
460 /* Double size. */
461 probes_capacity *= 2;
462
463 tmp_probes = zmalloc(sizeof(*tmp_probes) * probes_capacity);
464 if (!tmp_probes) {
465 PERROR("malloc probe list");
466 return -ENOMEM;
467 }
468
469 for (i = 0; i < nr_probes; ++i) {
470 /* Move name pointer. */
471 tmp_probes[i].name = probes[i].name;
472 }
473
474 /* Replace probes with larger copy. */
475 free(probes);
476 probes = tmp_probes;
477
478 return 0;
479 }
480
481 /*
482 * Appends a comma-separated list of probes to the global list
483 * of probes.
484 */
485 static int append_list_to_probes(const char *list)
486 {
487 char *next;
488 int ret;
489 char *tmp_list, *cur_list;
490
491 assert(list);
492
493 cur_list = tmp_list = strdup(list);
494 if (!tmp_list) {
495 PERROR("strdup temp list");
496 return -ENOMEM;
497 }
498
499 for (;;) {
500 size_t name_len;
501 struct kern_modules_param *cur_mod;
502
503 next = strtok(cur_list, ",");
504 if (!next) {
505 break;
506 }
507 cur_list = NULL;
508
509 /* filter leading spaces */
510 while (*next == ' ') {
511 next++;
512 }
513
514 if (probes_capacity <= nr_probes) {
515 ret = grow_probes();
516 if (ret) {
517 goto error;
518 }
519 }
520
521 /* Length 13 is "lttng-probe-" + \0 */
522 name_len = strlen(next) + 13;
523
524 cur_mod = &probes[nr_probes];
525 cur_mod->name = zmalloc(name_len);
526 if (!cur_mod->name) {
527 PERROR("malloc probe list");
528 ret = -ENOMEM;
529 goto error;
530 }
531
532 ret = snprintf(cur_mod->name, name_len, "lttng-probe-%s", next);
533 if (ret < 0) {
534 PERROR("snprintf modprobe name");
535 ret = -ENOMEM;
536 goto error;
537 }
538
539 nr_probes++;
540 }
541
542 free(tmp_list);
543 return 0;
544
545 error:
546 free(tmp_list);
547 free_probes();
548 return ret;
549 }
550
551 /*
552 * Load data kernel module(s).
553 */
554 int modprobe_lttng_data(void)
555 {
556 int ret, i;
557 char *list;
558
559 /*
560 * Base probes: either from command line option, environment
561 * variable or default list.
562 */
563 list = config.kmod_probes_list.value;
564 if (list) {
565 /* User-specified probes. */
566 ret = append_list_to_probes(list);
567 if (ret) {
568 return ret;
569 }
570 } else {
571 /* Default probes. */
572 int def_len = ARRAY_SIZE(kern_modules_probes_default);
573
574 probes = zmalloc(sizeof(*probes) * def_len);
575 if (!probes) {
576 PERROR("malloc probe list");
577 return -ENOMEM;
578 }
579
580 nr_probes = probes_capacity = def_len;
581
582 for (i = 0; i < def_len; ++i) {
583 char* name = strdup(kern_modules_probes_default[i].name);
584
585 if (!name) {
586 PERROR("strdup probe item");
587 ret = -ENOMEM;
588 goto error;
589 }
590
591 probes[i].name = name;
592 }
593 }
594
595 /*
596 * Extra modules? Append them to current probes list.
597 */
598 list = config.kmod_extra_probes_list.value;
599 if (list) {
600 ret = append_list_to_probes(list);
601 if (ret) {
602 goto error;
603 }
604 }
605
606 /*
607 * Load probes modules now.
608 */
609 ret = modprobe_lttng(probes, nr_probes, LTTNG_MOD_OPTIONAL);
610 if (ret) {
611 goto error;
612 }
613 return ret;
614
615 error:
616 free_probes();
617 return ret;
618 }
This page took 0.0469 seconds and 4 git commands to generate.