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