remove unneeded dir attic/
[ltt-control.git] / trunk / ltt-control / liblttctl / liblttctl.c
CommitLineData
2727692a 1/* libltt
2 *
3 * Linux Trace Toolkit Netlink Control Library
4 *
c928825d 5 * Controls the ltt-control kernel module through debugfs.
2727692a 6 *
7 * Copyright 2005 -
8 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10e8a188 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2727692a 19 * GNU General Public License for more details.
c928825d 20 *
2727692a 21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <liblttctl/lttctl.h>
28#include <errno.h>
29#include <stdio.h>
2727692a 30#include <string.h>
c928825d 31#include <dirent.h>
32#include <limits.h>
33#include <fcntl.h>
34#include <stdlib.h>
2727692a 35
c928825d 36#define MAX_CHANNEL (256)
2727692a 37
c928825d 38static char debugfsmntdir[PATH_MAX];
2727692a 39
c928825d 40static int initdebugfsmntdir(void)
2727692a 41{
354b34fd 42 return getdebugfsmntdir(debugfsmntdir);
43}
2727692a 44
354b34fd 45/*
46 * This function must called posterior to initdebugfsmntdir(),
47 * because it need to use debugfsmntdir[] which is inited in initdebugfsmntdir()
48 */
49static int initmodule(void)
50{
51 char controldirname[PATH_MAX];
52 DIR *dir;
53 int tryload_done = 0;
54
55 sprintf(controldirname, "%s/ltt/control/", debugfsmntdir);
56
57check_again:
58 /*
59 * Check ltt control's debugfs dir
60 *
61 * We don't check is ltt-trace-control module exist, because it maybe
62 * compiled into kernel.
63 */
64 dir = opendir(controldirname);
65 if (dir) {
66 closedir(dir);
67 return 0;
c928825d 68 }
2727692a 69
354b34fd 70 if (!tryload_done) {
71 system("modprobe ltt-trace-control");
72 tryload_done = 1;
73 goto check_again;
2727692a 74 }
354b34fd 75
76 return -ENOENT;
c928825d 77}
78
79int lttctl_init(void)
80{
81 int ret;
354b34fd 82
c928825d 83
84 ret = initdebugfsmntdir();
85 if (ret) {
354b34fd 86 fprintf(stderr, "Get debugfs mount point failed\n");
4015ea80 87 return ret;
2727692a 88 }
2727692a 89
354b34fd 90 ret = initmodule();
91 if (ret) {
92 fprintf(stderr, "Control module seems not work\n");
4015ea80 93 return ret;
c928825d 94 }
2727692a 95
c928825d 96 return 0;
97}
2727692a 98
c928825d 99int lttctl_destroy(void)
2727692a 100{
c928825d 101 return 0;
2727692a 102}
103
c928825d 104static int lttctl_sendop(const char *fname, const char *op)
2727692a 105{
c928825d 106 int fd;
107
108 if (!fname) {
109 fprintf(stderr, "%s: args invalid\n", __func__);
110 return 1;
111 }
112
113 fd = open(fname, O_WRONLY);
114 if (fd == -1) {
115 fprintf(stderr, "%s: open %s failed: %s\n", __func__, fname,
116 strerror(errno));
117 return errno;
118 }
119
120 if (write(fd, op, strlen(op)) == -1) {
4015ea80 121 int ret = errno;
c928825d 122 fprintf(stderr, "%s: write %s to %s failed: %s\n", __func__, op,
123 fname, strerror(errno));
124 close(fd);
4015ea80 125 return ret;
c928825d 126 }
2727692a 127
c928825d 128 close(fd);
129
130 return 0;
131}
2727692a 132
133/*
c928825d 134 * check is trace exist(check debugfsmntdir too)
135 * expect:
136 * 0: expect that trace not exist
137 * !0: expect that trace exist
138 *
139 * ret:
140 * 0: check pass
4015ea80 141 * -(EEXIST | ENOENT): check failed
c928825d 142 * -ERRNO: error happened (no check)
2727692a 143 */
c928825d 144static int lttctl_check_trace(const char *name, int expect)
2727692a 145{
c928825d 146 char tracedirname[PATH_MAX];
147 DIR *dir;
148 int exist;
2727692a 149
c928825d 150 if (!name) {
151 fprintf(stderr, "%s: args invalid\n", __func__);
152 return -EINVAL;
2727692a 153 }
c928825d 154
155 if (!debugfsmntdir[0]) {
156 fprintf(stderr, "%s: debugfsmntdir not valid\n", __func__);
157 return -EINVAL;
158 }
159
160 sprintf(tracedirname, "%s/ltt/control/%s", debugfsmntdir, name);
161
162 dir = opendir(tracedirname);
163 if (dir) {
164 exist = 1;
165 } else {
166 if (errno != ENOENT) {
167 fprintf(stderr, "%s: %s\n", __func__, strerror(errno));
168 return -EINVAL;
169 }
170 exist = 0;
171 }
172
173 closedir(dir);
174
175 if (!expect != !exist) {
176 if (exist)
4015ea80 177 {
c928825d 178 fprintf(stderr, "Trace %s already exist\n", name);
4015ea80 179 return -EEXIST;
180 }
c928825d 181 else
4015ea80 182 {
c928825d 183 fprintf(stderr, "Trace %s not exist\n", name);
4015ea80 184 return -ENOENT;
185 }
186
c928825d 187 }
188
189 return 0;
2727692a 190}
191
192/*
c928825d 193 * get channel list of a trace
194 * don't include metadata channel when metadata is 0
195 *
196 * return number of channel on success
197 * return negative number on fail
198 * Caller must free channellist.
2727692a 199 */
c928825d 200static int lttctl_get_channellist(const char *tracename,
201 char ***channellist, int metadata)
2727692a 202{
c928825d 203 char tracedirname[PATH_MAX];
204 struct dirent *dirent;
205 DIR *dir;
206 char **list = NULL, **old_list;
207 int nr_chan = 0;
208
209 sprintf(tracedirname, "%s/ltt/control/%s/channel", debugfsmntdir,
210 tracename);
211
212 dir = opendir(tracedirname);
213 if (!dir) {
214 nr_chan = -ENOENT;
215 goto error;
216 }
217
218 for (;;) {
219 dirent = readdir(dir);
220 if (!dirent)
221 break;
222 if (!strcmp(dirent->d_name, ".")
223 || !strcmp(dirent->d_name, ".."))
224 continue;
225 if (!metadata && !strcmp(dirent->d_name, "metadata"))
226 continue;
227 old_list = list;
228 list = malloc(sizeof(char *) * ++nr_chan);
229 memcpy(list, old_list, sizeof(*list) * (nr_chan - 1));
230 free(old_list);
231 list[nr_chan - 1] = strdup(dirent->d_name);
232 }
233
234 closedir(dir);
235
236 *channellist = list;
237 return nr_chan;
238error:
239 free(list);
240 *channellist = NULL;
241 return nr_chan;
242}
243
4015ea80 244static void lttctl_free_channellist(char **channellist, int n_channel)
245{
246 int i = 0;
247 for(; i < n_channel; ++i)
248 free(channellist[i]);
249 free(channellist);
250}
251
c928825d 252int lttctl_setup_trace(const char *name)
253{
254 int ret;
255 char ctlfname[PATH_MAX];
256
257 if (!name) {
258 fprintf(stderr, "%s: args invalid\n", __func__);
259 ret = -EINVAL;
260 goto arg_error;
261 }
262
263 ret = lttctl_check_trace(name, 0);
264 if (ret)
265 goto arg_error;
266
267 sprintf(ctlfname, "%s/ltt/setup_trace", debugfsmntdir);
268
269 ret = lttctl_sendop(ctlfname, name);
270 if (ret) {
271 fprintf(stderr, "Setup trace failed\n");
272 goto op_err;
2727692a 273 }
c928825d 274
2727692a 275 return 0;
c928825d 276
277op_err:
278arg_error:
279 return ret;
2727692a 280}
281
c928825d 282int lttctl_destroy_trace(const char *name)
283{
284 int ret;
285 char ctlfname[PATH_MAX];
286
287 if (!name) {
288 fprintf(stderr, "%s: args invalid\n", __func__);
289 ret = -EINVAL;
290 goto arg_error;
291 }
292
293 ret = lttctl_check_trace(name, 1);
294 if (ret)
295 goto arg_error;
296
297 sprintf(ctlfname, "%s/ltt/destroy_trace", debugfsmntdir);
298
299 ret = lttctl_sendop(ctlfname, name);
300 if (ret) {
301 fprintf(stderr, "Destroy trace failed\n");
302 goto op_err;
303 }
304
305 return 0;
306
307op_err:
308arg_error:
309 return ret;
310}
2727692a 311
c928825d 312int lttctl_alloc_trace(const char *name)
2727692a 313{
c928825d 314 int ret;
315 char ctlfname[PATH_MAX];
316
317 if (!name) {
318 fprintf(stderr, "%s: args invalid\n", __func__);
319 ret = -EINVAL;
320 goto arg_error;
321 }
322
323 ret = lttctl_check_trace(name, 1);
324 if (ret)
325 goto arg_error;
326
327 sprintf(ctlfname, "%s/ltt/control/%s/alloc", debugfsmntdir, name);
328
329 ret = lttctl_sendop(ctlfname, "1");
330 if (ret) {
331 fprintf(stderr, "Allocate trace failed\n");
332 goto op_err;
333 }
334
335 return 0;
336
337op_err:
338arg_error:
339 return ret;
340}
341
342int lttctl_start(const char *name)
343{
344 int ret;
345 char ctlfname[PATH_MAX];
346
347 if (!name) {
348 fprintf(stderr, "%s: args invalid\n", __func__);
349 ret = -EINVAL;
350 goto arg_error;
351 }
352
353 ret = lttctl_check_trace(name, 1);
354 if (ret)
355 goto arg_error;
356
357 sprintf(ctlfname, "%s/ltt/control/%s/enabled", debugfsmntdir, name);
358
359 ret = lttctl_sendop(ctlfname, "1");
360 if (ret) {
361 fprintf(stderr, "Start trace failed\n");
362 goto op_err;
2727692a 363 }
364
365 return 0;
366
c928825d 367op_err:
368arg_error:
369 return ret;
2727692a 370}
371
c928825d 372int lttctl_pause(const char *name)
2727692a 373{
c928825d 374 int ret;
375 char ctlfname[PATH_MAX];
376
377 if (!name) {
378 fprintf(stderr, "%s: args invalid\n", __func__);
379 ret = -EINVAL;
380 goto arg_error;
381 }
382
383 ret = lttctl_check_trace(name, 1);
384 if (ret)
385 goto arg_error;
386
387 sprintf(ctlfname, "%s/ltt/control/%s/enabled", debugfsmntdir, name);
388
389 ret = lttctl_sendop(ctlfname, "0");
390 if (ret) {
391 fprintf(stderr, "Pause trace failed\n");
392 goto op_err;
2727692a 393 }
394
395 return 0;
396
c928825d 397op_err:
398arg_error:
399 return ret;
400}
401
402int lttctl_set_trans(const char *name, const char *trans)
403{
404 int ret;
405 char ctlfname[PATH_MAX];
406
407 if (!name) {
408 fprintf(stderr, "%s: args invalid\n", __func__);
409 ret = -EINVAL;
410 goto arg_error;
411 }
412
413 ret = lttctl_check_trace(name, 1);
414 if (ret)
415 goto arg_error;
416
417 sprintf(ctlfname, "%s/ltt/control/%s/trans", debugfsmntdir, name);
2727692a 418
c928825d 419 ret = lttctl_sendop(ctlfname, trans);
420 if (ret) {
421 fprintf(stderr, "Set transport failed\n");
422 goto op_err;
423 }
424
425 return 0;
426
427op_err:
428arg_error:
429 return ret;
2727692a 430}
431
c928825d 432static int __lttctl_set_channel_enable(const char *name, const char *channel,
433 int enable)
2727692a 434{
c928825d 435 int ret;
436 char ctlfname[PATH_MAX];
2727692a 437
c928825d 438 sprintf(ctlfname, "%s/ltt/control/%s/channel/%s/enable", debugfsmntdir,
439 name, channel);
2727692a 440
c928825d 441 ret = lttctl_sendop(ctlfname, enable ? "1" : "0");
442 if (ret)
443 fprintf(stderr, "Set channel's enable mode failed\n");
2727692a 444
c928825d 445 return ret;
446}
447int lttctl_set_channel_enable(const char *name, const char *channel,
448 int enable)
449{
450 int ret;
4015ea80 451 char **channellist;
452 int n_channel;
2727692a 453
c928825d 454 if (!name || !channel) {
455 fprintf(stderr, "%s: args invalid\n", __func__);
456 ret = -EINVAL;
457 goto arg_error;
458 }
2727692a 459
c928825d 460 ret = lttctl_check_trace(name, 1);
461 if (ret)
462 goto arg_error;
463
464 if (strcmp(channel, "all")) {
465 ret = __lttctl_set_channel_enable(name, channel, enable);
466 if (ret)
467 goto op_err;
468 } else {
c928825d 469 /* Don't allow set enable state for metadata channel */
470 n_channel = lttctl_get_channellist(name, &channellist, 0);
471 if (n_channel < 0) {
472 fprintf(stderr, "%s: lttctl_get_channellist failed\n",
473 __func__);
474 ret = -ENOENT;
475 goto op_err;
476 }
2727692a 477
c928825d 478 for (; n_channel > 0; n_channel--) {
479 ret = __lttctl_set_channel_enable(name,
480 channellist[n_channel - 1], enable);
481 if (ret)
4015ea80 482 goto op_err_clean;
c928825d 483 }
4015ea80 484 lttctl_free_channellist(channellist, n_channel);
2727692a 485 }
486
487 return 0;
488
4015ea80 489op_err_clean:
490 lttctl_free_channellist(channellist, n_channel);
c928825d 491op_err:
492arg_error:
493 return ret;
494}
495
496static int __lttctl_set_channel_overwrite(const char *name, const char *channel,
497 int overwrite)
498{
499 int ret;
500 char ctlfname[PATH_MAX];
501
502 sprintf(ctlfname, "%s/ltt/control/%s/channel/%s/overwrite",
503 debugfsmntdir, name, channel);
504
505 ret = lttctl_sendop(ctlfname, overwrite ? "1" : "0");
506 if (ret)
507 fprintf(stderr, "Set channel's overwrite mode failed\n");
508
509 return ret;
510}
511int lttctl_set_channel_overwrite(const char *name, const char *channel,
512 int overwrite)
513{
514 int ret;
4015ea80 515 char **channellist;
516 int n_channel;
c928825d 517
518 if (!name || !channel) {
519 fprintf(stderr, "%s: args invalid\n", __func__);
520 ret = -EINVAL;
521 goto arg_error;
522 }
523
524 ret = lttctl_check_trace(name, 1);
525 if (ret)
526 goto arg_error;
527
528 if (strcmp(channel, "all")) {
529 ret = __lttctl_set_channel_overwrite(name, channel, overwrite);
530 if (ret)
531 goto op_err;
532 } else {
c928825d 533 /* Don't allow set overwrite for metadata channel */
534 n_channel = lttctl_get_channellist(name, &channellist, 0);
535 if (n_channel < 0) {
536 fprintf(stderr, "%s: lttctl_get_channellist failed\n",
537 __func__);
538 ret = -ENOENT;
539 goto op_err;
540 }
541
542 for (; n_channel > 0; n_channel--) {
543 ret = __lttctl_set_channel_overwrite(name,
544 channellist[n_channel - 1], overwrite);
545 if (ret)
4015ea80 546 goto op_err_clean;
c928825d 547 }
4015ea80 548 lttctl_free_channellist(channellist, n_channel);
c928825d 549 }
550
551 return 0;
2727692a 552
4015ea80 553op_err_clean:
554 lttctl_free_channellist(channellist, n_channel);
c928825d 555op_err:
556arg_error:
557 return ret;
2727692a 558}
559
c928825d 560static int __lttctl_set_channel_subbuf_num(const char *name,
561 const char *channel, unsigned subbuf_num)
562{
563 int ret;
564 char ctlfname[PATH_MAX];
565 char opstr[32];
566
567 sprintf(ctlfname, "%s/ltt/control/%s/channel/%s/subbuf_num",
568 debugfsmntdir, name, channel);
569
570 sprintf(opstr, "%u", subbuf_num);
571
572 ret = lttctl_sendop(ctlfname, opstr);
573 if (ret)
574 fprintf(stderr, "Set channel's subbuf number failed\n");
575
576 return ret;
577}
578int lttctl_set_channel_subbuf_num(const char *name, const char *channel,
579 unsigned subbuf_num)
2727692a 580{
c928825d 581 int ret;
4015ea80 582 char **channellist;
583 int n_channel;
c928825d 584
585 if (!name || !channel) {
586 fprintf(stderr, "%s: args invalid\n", __func__);
587 ret = -EINVAL;
588 goto arg_error;
589 }
590
591 ret = lttctl_check_trace(name, 1);
592 if (ret)
593 goto arg_error;
594
595 if (strcmp(channel, "all")) {
596 ret = __lttctl_set_channel_subbuf_num(name, channel,
597 subbuf_num);
598 if (ret)
599 goto op_err;
600 } else {
c928825d 601 /* allow set subbuf_num for metadata channel */
602 n_channel = lttctl_get_channellist(name, &channellist, 1);
603 if (n_channel < 0) {
604 fprintf(stderr, "%s: lttctl_get_channellist failed\n",
605 __func__);
606 ret = -ENOENT;
607 goto op_err;
608 }
609
610 for (; n_channel > 0; n_channel--) {
611 ret = __lttctl_set_channel_subbuf_num(name,
612 channellist[n_channel - 1], subbuf_num);
613 if (ret)
4015ea80 614 goto op_err_clean;
c928825d 615 }
4015ea80 616 lttctl_free_channellist(channellist, n_channel);
2727692a 617 }
618
619 return 0;
620
4015ea80 621op_err_clean:
622 lttctl_free_channellist(channellist, n_channel);
c928825d 623op_err:
624arg_error:
625 return ret;
626}
627
628static int __lttctl_set_channel_subbuf_size(const char *name,
629 const char *channel, unsigned subbuf_size)
630{
631 int ret;
632 char ctlfname[PATH_MAX];
633 char opstr[32];
634
635 sprintf(ctlfname, "%s/ltt/control/%s/channel/%s/subbuf_size",
636 debugfsmntdir, name, channel);
637
638 sprintf(opstr, "%u", subbuf_size);
639
640 ret = lttctl_sendop(ctlfname, opstr);
641 if (ret)
642 fprintf(stderr, "Set channel's subbuf size failed\n");
2727692a 643}
c928825d 644int lttctl_set_channel_subbuf_size(const char *name, const char *channel,
645 unsigned subbuf_size)
646{
647 int ret;
4015ea80 648 char **channellist;
649 int n_channel;
2727692a 650
c928825d 651 if (!name || !channel) {
652 fprintf(stderr, "%s: args invalid\n", __func__);
653 ret = -EINVAL;
654 goto arg_error;
655 }
656
657 ret = lttctl_check_trace(name, 1);
658 if (ret)
659 goto arg_error;
660
661 if (strcmp(channel, "all")) {
662 ret = __lttctl_set_channel_subbuf_size(name, channel,
663 subbuf_size);
664 if (ret)
665 goto op_err;
666 } else {
c928825d 667 /* allow set subbuf_size for metadata channel */
668 n_channel = lttctl_get_channellist(name, &channellist, 1);
669 if (n_channel < 0) {
670 fprintf(stderr, "%s: lttctl_get_channellist failed\n",
671 __func__);
672 ret = -ENOENT;
673 goto op_err;
674 }
675
676 for (; n_channel > 0; n_channel--) {
677 ret = __lttctl_set_channel_subbuf_size(name,
678 channellist[n_channel - 1], subbuf_size);
679 if (ret)
4015ea80 680 goto op_err_clean;
c928825d 681 }
4015ea80 682 lttctl_free_channellist(channellist, n_channel);
c928825d 683 }
684
685 return 0;
686
4015ea80 687op_err_clean:
688 lttctl_free_channellist(channellist, n_channel);
c928825d 689op_err:
690arg_error:
691 return ret;
692}
354b34fd 693
694int getdebugfsmntdir(char *mntdir)
695{
696 char mnt_dir[PATH_MAX];
697 char mnt_type[PATH_MAX];
698 int trymount_done = 0;
699
700 FILE *fp = fopen("/proc/mounts", "r");
701 if (!fp)
702 return -EINVAL;
703
704find_again:
705 while (1) {
706 if (fscanf(fp, "%*s %s %s %*s %*s %*s", mnt_dir, mnt_type) <= 0)
707 break;
708
709 if (!strcmp(mnt_type, "debugfs")) {
710 strcpy(mntdir, mnt_dir);
711 return 0;
712 }
713 }
714
715 if (!trymount_done) {
716 mount("debugfs", "/sys/kernel/debug/", "debugfs", 0, NULL);
717 trymount_done = 1;
718 goto find_again;
719 }
720
721 return -ENOENT;
722}
This page took 0.052283 seconds and 4 git commands to generate.