3 * Linux Trace Toolkit Control
5 * Small program that controls LTTng through liblttctl.
7 * Copyright 2008 FUJITSU
8 * Zhao Lei <zhaolei@cn.fujitsu.com>
9 * Gui Jianfeng <guijianfeng@cn.fujitsu.com>
10 * Copyright 2009-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <liblttctl/lttctl.h>
42 #define OPT_MAX (1024)
43 #define OPT_NAMELEN (256)
44 #define OPT_VALSTRINGLEN (256)
50 struct channel_option
{
51 char chan_name
[OPT_NAMELEN
];
59 struct lttctl_option
{
61 struct channel_option chan_opt
;
64 struct lttctl_option
*next
;
67 struct lttctl_option
*opt_head
, *last_opt
;
69 static int opt_create
;
70 static int opt_destroy
;
74 static const char *opt_transport
;
75 static const char *opt_write
;
76 static int opt_append
;
77 static unsigned int opt_dump_threads
;
78 static char channel_root_default
[PATH_MAX
];
79 static const char *opt_channel_root
;
80 static const char *opt_tracename
;
85 static void show_arguments(void)
87 printf("Linux Trace Toolkit Trace Control " VERSION
"\n");
89 printf("Usage: lttctl [OPTION]... [TRACENAME]\n");
91 printf("Examples:\n");
92 printf(" lttctl -c trace1 "
93 "# Create a trace named trace1.\n");
94 printf(" lttctl -s trace1 "
95 "# start a trace named trace1.\n");
96 printf(" lttctl -p trace1 "
97 "# pause a trace named trace1.\n");
98 printf(" lttctl -d trace1 "
99 "# Destroy a trace named trace1.\n");
100 printf(" lttctl -C -w /tmp/trace1 trace1 "
101 "# Create a trace named trace1, start it and\n"
103 "# write non-overwrite channels' data to\n"
105 "# /tmp/trace1, debugfs must be mounted for\n"
108 printf(" lttctl -D -w /tmp/trace1 trace1 "
109 "# Pause and destroy a trace named trace1 and\n"
111 "# write overwrite channels' data to\n"
113 "# /tmp/trace1, debugfs must be mounted for\n"
117 printf(" Basic options:\n");
118 printf(" -c, --create\n");
119 printf(" Create a trace.\n");
120 printf(" -d, --destroy\n");
121 printf(" Destroy a trace.\n");
122 printf(" -s, --start\n");
123 printf(" Start a trace.\n");
124 printf(" -p, --pause\n");
125 printf(" Pause a trace.\n");
126 printf(" -h, --help\n");
127 printf(" Show this help.\n");
129 printf(" Advanced options:\n");
130 printf(" --transport TRANSPORT\n");
131 printf(" Set trace's transport. (ex. relay-locked or relay)\n");
132 printf(" -o, --option OPTION\n");
133 printf(" Set options, following operations are supported:\n");
134 printf(" channel.<channelname>.enable=\n");
135 printf(" channel.<channelname>.overwrite=\n");
136 printf(" channel.<channelname>.bufnum=\n");
137 printf(" channel.<channelname>.bufsize= (in bytes, rounded to "
138 "next power of 2)\n");
139 printf(" <channelname> can be set to all for all channels\n");
140 printf(" channel.<channelname>.switch_timer= (timer interval in "
143 printf(" Integration options:\n");
144 printf(" -C, --create_start\n");
145 printf(" Create and start a trace.\n");
146 printf(" -D, --pause_destroy\n");
147 printf(" Pause and destroy a trace.\n");
148 printf(" -w, --write PATH\n");
149 printf(" Path for write trace datas.\n");
150 printf(" For -c, -C, -d, -D options\n");
151 printf(" -a, --append\n");
152 printf(" Append to trace, For -w option\n");
153 printf(" -n, --dump_threads NUMBER\n");
154 printf(" Number of lttd threads, For -w option\n");
155 printf(" --channel_root PATH\n");
156 printf(" Set channels root path, For -w option."
157 " (ex. /mnt/debugfs/ltt)\n");
159 printf(" Environment variables:\n");
160 printf(" LTT_DAEMON\n");
161 printf(" Complete path to the lttd binary (needs to be\n");
162 printf(" specified if different than package build prefix).\n");
167 * Separate option name to 3 fields
169 * Input: name = channel.cpu.bufsize
170 * Output: name1 = channel
177 * Make sure that name1~3 longer than OPT_NAMELEN.
178 * name1~3 can be NULL to discard value
181 static int separate_opt(const char *name
, char *name1
, char *name2
, char *name3
)
189 p
= strchr(name
, '.');
192 if (p
- name
>= OPT_NAMELEN
)
195 memcpy(name1
, name
, p
- name
);
201 p
= strchr(name
, '.');
204 if (p
- name
>= OPT_NAMELEN
)
207 memcpy(name2
, name
, p
- name
);
213 if (strlen(name
) >= OPT_NAMELEN
)
221 static void init_channel_opt(struct channel_option
*opt
, char *opt_name
)
223 if (opt
&& opt_name
) {
228 opt
->switch_timer
= -1;
229 strcpy(opt
->chan_name
, opt_name
);
233 static struct lttctl_option
*find_insert_channel_opt(char *opt_name
)
235 struct lttctl_option
*iter
, *new_opt
;
238 opt_head
= (struct lttctl_option
*)malloc(sizeof(struct lttctl_option
));
239 init_channel_opt(&opt_head
->opt_mode
.chan_opt
, opt_name
);
240 opt_head
->type
= CHANNEL
;
241 opt_head
->next
= NULL
;
246 for (iter
= opt_head
; iter
; iter
= iter
->next
) {
247 if (iter
->type
!= CHANNEL
)
249 if (!strcmp(iter
->opt_mode
.chan_opt
.chan_name
, opt_name
))
253 new_opt
= (struct lttctl_option
*)malloc(sizeof(struct lttctl_option
));
254 init_channel_opt(&new_opt
->opt_mode
.chan_opt
, opt_name
);
255 new_opt
->type
= CHANNEL
;
256 new_opt
->next
= NULL
;
257 last_opt
->next
= new_opt
;
262 int set_channel_opt(struct channel_option
*opt
, char *opt_name
, char *opt_valstr
)
266 if (!strcmp("enable", opt_name
)) {
267 if (opt_valstr
[1] != 0) {
270 if (opt_valstr
[0] == 'Y' || opt_valstr
[0] == 'y'
271 || opt_valstr
[0] == '1')
273 else if (opt_valstr
[0] == 'N' || opt_valstr
[0] == 'n'
274 || opt_valstr
[0] == '0')
280 opt
->enable
= opt_val
;
282 } else if (!strcmp("overwrite", opt_name
)) {
283 if (opt_valstr
[1] != 0) {
286 if (opt_valstr
[0] == 'Y' || opt_valstr
[0] == 'y'
287 || opt_valstr
[0] == '1')
289 else if (opt_valstr
[0] == 'N' || opt_valstr
[0] == 'n'
290 || opt_valstr
[0] == '0')
296 opt
->overwrite
= opt_val
;
299 } else if (!strcmp("bufnum", opt_name
)) {
300 ret
= sscanf(opt_valstr
, "%d", &opt_val
);
301 if (ret
!= 1 || opt_val
< 0) {
305 opt
->bufnum
= opt_val
;
307 } else if (!strcmp("bufsize", opt_name
)) {
308 ret
= sscanf(opt_valstr
, "%d", &opt_val
);
309 if (ret
!= 1 || opt_val
< 0) {
313 opt
->bufsize
= opt_val
;
315 } else if (!strcmp("switch_timer", opt_name
)) {
316 ret
= sscanf(opt_valstr
, "%d", &opt_val
);
317 if (ret
!= 1 || opt_val
< 0) {
321 opt
->switch_timer
= opt_val
;
329 static int parst_opt(const char *optarg
)
332 char opt_name
[OPT_NAMELEN
* 3];
333 char opt_valstr
[OPT_VALSTRINGLEN
];
336 char name1
[OPT_NAMELEN
];
337 char name2
[OPT_NAMELEN
];
338 char name3
[OPT_NAMELEN
];
342 unsigned int opt_uintval
;
343 struct lttctl_option
*opt
;
346 fprintf(stderr
, "Option empty\n");
350 /* Get option name and val_str */
351 p
= strchr(optarg
, '=');
353 fprintf(stderr
, "Option format error: %s\n", optarg
);
357 if (p
- optarg
>= sizeof(opt_name
)/sizeof(opt_name
[0])) {
358 fprintf(stderr
, "Option name too long: %s\n", optarg
);
362 if (strlen(p
+1) >= OPT_VALSTRINGLEN
) {
363 fprintf(stderr
, "Option value too long: %s\n", optarg
);
367 memcpy(opt_name
, optarg
, p
- optarg
);
368 opt_name
[p
- optarg
] = 0;
369 strcpy(opt_valstr
, p
+1);
371 /* separate option name into 3 fields */
372 ret
= separate_opt(opt_name
, name1
, name2
, name3
);
374 fprintf(stderr
, "Option name error1: %s\n", optarg
);
378 if (!strcmp("channel", name1
)) {
379 opt
= find_insert_channel_opt(name2
);
380 if ((ret
= set_channel_opt(&opt
->opt_mode
.chan_opt
,
381 name3
, opt_valstr
) != 0)) {
382 fprintf(stderr
, "Option name error2: %s\n", optarg
);
386 fprintf(stderr
, "Option name error3: %s\n", optarg
);
395 * Parses the command line arguments.
397 * Returns -1 if the arguments were correct, but doesn't ask for program
398 * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
400 static int parse_arguments(int argc
, char **argv
)
404 static struct option longopts
[] = {
405 {"create", no_argument
, NULL
, 'c'},
406 {"destroy", no_argument
, NULL
, 'd'},
407 {"start", no_argument
, NULL
, 's'},
408 {"pause", no_argument
, NULL
, 'p'},
409 {"help", no_argument
, NULL
, 'h'},
410 {"transport", required_argument
, NULL
, 2},
411 {"option", required_argument
, NULL
, 'o'},
412 {"create_start", no_argument
, NULL
, 'C'},
413 {"pause_destroy", no_argument
, NULL
, 'D'},
414 {"write", required_argument
, NULL
, 'w'},
415 {"append", no_argument
, NULL
, 'a'},
416 {"dump_threads", required_argument
, NULL
, 'n'},
417 {"channel_root", required_argument
, NULL
, 3},
418 { NULL
, 0, NULL
, 0 },
422 * Enable all channels in default
423 * To make novice users happy
425 parst_opt("channel.all.enable=1");
427 opterr
= 1; /* Print error message on getopt_long */
430 c
= getopt_long(argc
, argv
, "cdspho:CDw:an:", longopts
, NULL
);
452 if (!opt_transport
) {
453 opt_transport
= optarg
;
456 "Please specify only 1 transport\n");
461 ret
= parst_opt(optarg
);
478 "Please specify only 1 write dir\n");
486 if (opt_dump_threads
) {
488 "Please specify only 1 dump threads\n");
492 ret
= sscanf(optarg
, "%u", &opt_dump_threads
);
495 "Dump threads not positive number\n");
500 if (!opt_channel_root
) {
501 opt_channel_root
= optarg
;
504 "Please specify only 1 channel root\n");
515 /* Don't check args when user needs help */
520 if (optind
< argc
- 1) {
521 fprintf(stderr
, "Please specify only 1 trace name\n");
524 if (optind
> argc
- 1) {
525 fprintf(stderr
, "Please specify trace name\n");
528 opt_tracename
= argv
[optind
];
533 if (!opt_create
&& !opt_start
&& !opt_destroy
&& !opt_pause
) {
535 "Please specify a option of "
536 "create, destroy, start, or pause\n");
540 if ((opt_create
|| opt_start
) && (opt_destroy
|| opt_pause
)) {
542 "Create and start conflict with destroy and pause\n");
548 opt_transport
= "relay";
554 "Transport option must be combine with create"
561 if (!opt_create
&& !opt_destroy
) {
563 "Write option must be combine with create or"
564 " destroy option\n");
568 if (!opt_channel_root
)
569 if (getdebugfsmntdir(channel_root_default
) == 0) {
570 strcat(channel_root_default
, "/ltt");
571 opt_channel_root
= channel_root_default
;
574 "Channel_root is necessary for -w"
575 " option, but neither --channel_root"
577 "specified, nor debugfs's mount dir"
578 " found, mount debugfs also failed\n");
582 if (opt_dump_threads
== 0)
583 opt_dump_threads
= 1;
589 "Append option must be combine with write"
595 if (opt_dump_threads
) {
598 "Dump_threads option must be combine with write"
604 if (opt_channel_root
) {
607 "Channel_root option must be combine with write"
616 static void show_info(void)
618 printf("Linux Trace Toolkit Trace Control " VERSION
"\n");
620 if (opt_tracename
!= NULL
) {
621 printf("Controlling trace : %s\n", opt_tracename
);
626 static int lttctl_channel_setup(struct channel_option
*opt
)
630 if (opt
->enable
!= -1) {
631 if ((ret
= lttctl_set_channel_enable(opt_tracename
,
636 if (opt
->overwrite
!= -1) {
637 if ((ret
= lttctl_set_channel_overwrite(opt_tracename
,
639 opt
->overwrite
)) != 0)
642 if (opt
->bufnum
!= -1) {
643 if ((ret
= lttctl_set_channel_subbuf_num(opt_tracename
,
648 if (opt
->bufsize
!= -1) {
649 if ((ret
= lttctl_set_channel_subbuf_size(opt_tracename
,
654 if (opt
->switch_timer
!= -1) {
655 if ((ret
= lttctl_set_channel_switch_timer(opt_tracename
,
656 opt
->chan_name
, opt
->switch_timer
)) != 0)
663 static int lttctl_create_trace(void)
667 struct lttctl_option
*opt
;
669 ret
= lttctl_setup_trace(opt_tracename
);
671 goto setup_trace_fail
;
673 for (opt
= opt_head
; opt
; opt
= opt
->next
) {
674 if (opt
->type
!= CHANNEL
)
676 ret
= lttctl_channel_setup(&opt
->opt_mode
.chan_opt
);
678 goto set_option_fail
;;
681 ret
= lttctl_set_trans(opt_tracename
, opt_transport
);
683 goto set_option_fail
;
685 ret
= lttctl_alloc_trace(opt_tracename
);
687 goto alloc_trace_fail
;
693 lttctl_destroy_trace(opt_tracename
);
699 * Start a lttd daemon to write trace data
700 * Dump overwrite channels on overwrite!=0
701 * Dump normal(non-overwrite) channels on overwrite=0
703 * When called for overwrite mode, wait for lttd to return, so we are sure that
704 * trace session teardown is not executed before lttd can grab the buffer data.
709 static int lttctl_daemon(int overwrite
)
716 perror("Error in forking for lttd daemon");
724 char channel_path
[PATH_MAX
];
728 argv
[argc
] = getenv("LTT_DAEMON");
729 if (argv
[argc
] == NULL
)
730 argv
[argc
] = PACKAGE_BIN_DIR
"/lttd";
737 * we allow modify of opt_write's content in new process
738 * for get rid of warning of assign char * to const char *
740 argv
[argc
] = (char *)opt_write
;
744 strcpy(channel_path
, opt_channel_root
);
745 strcat(channel_path
, "/");
746 strcat(channel_path
, opt_tracename
);
749 argv
[argc
] = channel_path
;
753 sprintf(thread_num
, "%u", opt_dump_threads
);
756 argv
[argc
] = thread_num
;
769 /* overwrite option */
780 execvp(argv
[0], argv
);
782 perror("Error in executing the lttd daemon");
787 if (waitpid(pid
, &status
, 0) == -1) {
788 perror("Error in waitpid\n");
792 if (!WIFEXITED(status
)) {
793 fprintf(stderr
, "lttd process interrupted\n");
797 if (WEXITSTATUS(status
))
798 fprintf(stderr
, "lttd process running failed\n");
802 * This is a temporary hack to ensure that the lttd daemon grabs
803 * handles on the debugfs buffer files before we destroy the trace
804 * session. Properly handling this will imply separating the "flush"
805 * from the "destroy" operation at kernel-level in LTTng.
810 return WEXITSTATUS(status
);
813 int main(int argc
, char **argv
)
817 ret
= parse_arguments(argc
, argv
);
818 /* If user needs show help, we disregard other options */
824 /* exit program if arguments wrong */
835 printf("lttctl: Creating trace\n");
836 ret
= lttctl_create_trace();
841 printf("lttctl: Forking lttd\n");
842 ret
= lttctl_daemon(0);
849 printf("lttctl: Starting trace\n");
850 ret
= lttctl_start(opt_tracename
);
856 printf("lttctl: Pausing trace\n");
857 ret
= lttctl_pause(opt_tracename
);
864 printf("lttctl: Forking lttd\n");
865 ret
= lttctl_daemon(1);
870 printf("lttctl: Destroying trace\n");
871 ret
= lttctl_destroy_trace(opt_tracename
);
This page took 0.09401 seconds and 4 git commands to generate.