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