3 * Linux Trace Toolkit Control
5 * Small program that controls LTT through libltt.
8 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
15 #include <liblttctl/lttctl.h>
26 #define OPT_MAX (1024)
27 #define OPT_NAMELEN (256)
28 #define OPT_VALSTRINGLEN (256)
30 enum lttcrl_option_type
{
39 struct lttctl_option
{
40 char name1
[OPT_NAMELEN
];
41 char name2
[OPT_NAMELEN
];
42 char name3
[OPT_NAMELEN
];
44 char v_string
[OPT_VALSTRINGLEN
];
51 static int opt_create
;
52 static int opt_destroy
;
56 static const char *opt_transport
;
57 static struct lttctl_option opt_options
[OPT_MAX
];
58 static unsigned int opt_option_n
;
59 static const char *opt_write
;
60 static int opt_append
;
61 static unsigned int opt_dump_threads
;
62 static char channel_root_default
[PATH_MAX
];
63 static const char *opt_channel_root
;
64 static const char *opt_tracename
;
69 static void show_arguments(void)
71 printf("Linux Trace Toolkit Trace Control " VERSION
"\n");
73 printf("Usage: lttctl [OPTION]... [TRACENAME]\n");
75 printf("Examples:\n");
76 printf(" lttctl -c trace1 "
77 "# Create a trace named trace1.\n");
78 printf(" lttctl -s trace1 "
79 "# start a trace named trace1.\n");
80 printf(" lttctl -p trace1 "
81 "# pause a trace named trace1.\n");
82 printf(" lttctl -d trace1 "
83 "# Destroy a trace named trace1.\n");
84 printf(" lttctl -C -w /tmp/trace1 trace1 "
85 "# Create a trace named trace1, start it and\n"
87 "# write non-overwrite channels' data to\n"
89 "# /tmp/trace1, debugfs must be mounted for\n"
92 printf(" lttctl -D -w /tmp/trace1 trace1 "
93 "# Pause and destroy a trace named trace1 and\n"
95 "# write overwrite channels' data to\n"
97 "# /tmp/trace1, debugfs must be mounted for\n"
101 printf(" Basic options:\n");
102 printf(" -c, --create\n");
103 printf(" Create a trace.\n");
104 printf(" -d, --destroy\n");
105 printf(" Destroy a trace.\n");
106 printf(" -s, --start\n");
107 printf(" Start a trace.\n");
108 printf(" -p, --pause\n");
109 printf(" Pause a trace.\n");
110 printf(" -h, --help\n");
111 printf(" Show this help.\n");
113 printf(" Advanced options:\n");
114 printf(" --transport TRANSPORT\n");
115 printf(" Set trace's transport. (ex. relay)\n");
116 printf(" -o, --option OPTION\n");
117 printf(" Set options, following operations are supported:\n");
118 printf(" channel.<channelname>.enable=\n");
119 printf(" channel.<channelname>.overwrite=\n");
120 printf(" channel.<channelname>.bufnum=\n");
121 printf(" channel.<channelname>.bufsize=\n");
122 printf(" <channelname> can be set to all for all channels\n");
124 printf(" Integration options:\n");
125 printf(" -C, --create_start\n");
126 printf(" Create and start a trace.\n");
127 printf(" -D, --pause_destroy\n");
128 printf(" Pause and destroy a trace.\n");
129 printf(" -w, --write PATH\n");
130 printf(" Path for write trace datas.\n");
131 printf(" For -c, -C, -d, -D options\n");
132 printf(" -a, --append\n");
133 printf(" Append to trace, For -w option\n");
134 printf(" -n, --dump_threads NUMBER\n");
135 printf(" Number of lttd threads, For -w option\n");
136 printf(" --channel_root PATH\n");
137 printf(" Set channels root path, For -w option."
138 " (ex. /mnt/debugfs/ltt)\n");
142 static int getdebugfsmntdir(char *mntdir
)
144 char mnt_dir
[PATH_MAX
];
145 char mnt_type
[PATH_MAX
];
147 FILE *fp
= fopen("/proc/mounts", "r");
152 if (fscanf(fp
, "%*s %s %s %*s %*s %*s", mnt_dir
, mnt_type
) <= 0)
155 if (!strcmp(mnt_type
, "debugfs")) {
156 strcpy(mntdir
, mnt_dir
);
163 * Separate option name to 3 fields
165 * Input: name = channel.cpu.bufsize
166 * Output: name1 = channel
173 * Make sure that name1~3 longer than OPT_NAMELEN.
174 * name1~3 can be NULL to discard value
177 static int separate_opt(const char *name
, char *name1
, char *name2
, char *name3
)
185 p
= strchr(name
, '.');
188 if (p
- name
>= OPT_NAMELEN
)
191 memcpy(name1
, name
, p
- name
);
197 p
= strchr(name
, '.');
200 if (p
- name
>= OPT_NAMELEN
)
203 memcpy(name2
, name
, p
- name
);
209 if (strlen(name
) >= OPT_NAMELEN
)
218 * get option's type by its name,
219 * can also be used to check is option exists
220 * (return option_type_unknown when not exist)
222 static enum lttcrl_option_type
opt_type(const char *name1
, const char *name2
,
225 if (!name1
|| !name2
|| !name3
)
226 return option_type_unknown
;
228 if (strlen(name1
) >= OPT_NAMELEN
229 || strlen(name2
) >= OPT_NAMELEN
230 || strlen(name3
) >= OPT_NAMELEN
)
231 return option_type_unknown
;
233 if (strcmp(name1
, "channel") == 0) {
234 /* Option is channel class */
235 if (strcmp(name3
, "enable") == 0)
236 return option_type_bool
;
237 if (strcmp(name3
, "overwrite") == 0)
238 return option_type_bool
;
239 if (strcmp(name3
, "bufnum") == 0)
240 return option_type_uint
;
241 if (strcmp(name3
, "bufsize") == 0)
242 return option_type_uint
;
243 return option_type_unknown
;
247 * Now we only support channel options
248 * other option class' will used in future
251 return option_type_unknown
;
254 static struct lttctl_option
*find_opt(const char *name1
, const char *name2
,
259 if (!name1
|| !name2
|| !name3
)
262 for (i
= 0; i
< opt_option_n
; i
++) {
263 if (strcmp(opt_options
[i
].name1
, name1
) == 0
264 && strcmp(opt_options
[i
].name2
, name2
) == 0
265 && strcmp(opt_options
[i
].name3
, name3
) == 0)
266 return opt_options
+ i
;
272 static struct lttctl_option
*get_opt(const char *name1
, const char *name2
,
275 struct lttctl_option
*opt
;
277 if (!name1
|| !name2
|| !name3
)
280 opt
= find_opt(name1
, name2
, name3
);
284 if (opt_option_n
>= OPT_MAX
) {
285 fprintf(stderr
, "Option number out of range\n");
289 if (strlen(name1
) >= OPT_NAMELEN
290 || strlen(name2
) >= OPT_NAMELEN
291 || strlen(name3
) >= OPT_NAMELEN
) {
292 fprintf(stderr
, "Option name too long: %s.%s.%s\n",
293 name1
, name2
, name3
);
297 opt
= &opt_options
[opt_option_n
];
298 strcpy(opt
->name1
, name1
);
299 strcpy(opt
->name2
, name2
);
300 strcpy(opt
->name3
, name3
);
306 static int parst_opt(const char *optarg
)
309 char opt_name
[OPT_NAMELEN
* 3];
310 char opt_valstr
[OPT_VALSTRINGLEN
];
313 char name1
[OPT_NAMELEN
];
314 char name2
[OPT_NAMELEN
];
315 char name3
[OPT_NAMELEN
];
317 enum lttcrl_option_type opttype
;
319 unsigned int opt_uintval
;
320 struct lttctl_option
*newopt
;
323 fprintf(stderr
, "Option empty\n");
327 /* Get option name and val_str */
328 p
= strchr(optarg
, '=');
330 fprintf(stderr
, "Option format error: %s\n", optarg
);
334 if (p
- optarg
>= sizeof(opt_name
)/sizeof(opt_name
[0])) {
335 fprintf(stderr
, "Option name too long: %s\n", optarg
);
339 if (strlen(p
+1) >= OPT_VALSTRINGLEN
) {
340 fprintf(stderr
, "Option value too long: %s\n", optarg
);
344 memcpy(opt_name
, optarg
, p
- optarg
);
345 opt_name
[p
- optarg
] = 0;
346 strcpy(opt_valstr
, p
+1);
348 /* separate option name into 3 fields */
349 ret
= separate_opt(opt_name
, name1
, name2
, name3
);
351 fprintf(stderr
, "Option name error: %s\n", optarg
);
356 * check and add option
358 opttype
= opt_type(name1
, name2
, name3
);
360 case option_type_unknown
:
361 fprintf(stderr
, "Option not supported: %s\n", optarg
);
363 case option_type_string
:
364 newopt
= get_opt(name1
, name2
, name3
);
367 strcpy(newopt
->value
.v_string
, opt_valstr
);
369 case option_type_int
:
370 ret
= sscanf(opt_valstr
, "%d", &opt_intval
);
372 fprintf(stderr
, "Option format error: %s\n", optarg
);
375 newopt
= get_opt(name1
, name2
, name3
);
378 newopt
->value
.v_int
= opt_intval
;
380 case option_type_uint
:
381 ret
= sscanf(opt_valstr
, "%u", &opt_uintval
);
383 fprintf(stderr
, "Option format error: %s\n", optarg
);
386 newopt
= get_opt(name1
, name2
, name3
);
389 newopt
->value
.v_uint
= opt_uintval
;
391 case option_type_positive
:
392 ret
= sscanf(opt_valstr
, "%u", &opt_uintval
);
393 if (ret
!= 1 || opt_uintval
== 0) {
394 fprintf(stderr
, "Option format error: %s\n", optarg
);
397 newopt
= get_opt(name1
, name2
, name3
);
400 newopt
->value
.v_uint
= opt_uintval
;
402 case option_type_bool
:
403 if (opt_valstr
[1] != 0) {
404 fprintf(stderr
, "Option format error: %s\n", optarg
);
407 if (opt_valstr
[0] == 'Y' || opt_valstr
[0] == 'y'
408 || opt_valstr
[0] == '1')
410 else if (opt_valstr
[0] == 'N' || opt_valstr
[0] == 'n'
411 || opt_valstr
[0] == '0')
414 fprintf(stderr
, "Option format error: %s\n", optarg
);
418 newopt
= get_opt(name1
, name2
, name3
);
421 newopt
->value
.v_bool
= opt_intval
;
424 fprintf(stderr
, "Internal error on opt %s\n", optarg
);
428 return 0; /* should not run to here */
433 * Parses the command line arguments.
435 * Returns -1 if the arguments were correct, but doesn't ask for program
436 * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
438 static int parse_arguments(int argc
, char **argv
)
442 static struct option longopts
[] = {
443 {"create", no_argument
, NULL
, 'c'},
444 {"destroy", no_argument
, NULL
, 'd'},
445 {"start", no_argument
, NULL
, 's'},
446 {"pause", no_argument
, NULL
, 'p'},
447 {"help", no_argument
, NULL
, 'h'},
448 {"transport", required_argument
, NULL
, 2},
449 {"option", required_argument
, NULL
, 'o'},
450 {"create_start", no_argument
, NULL
, 'C'},
451 {"pause_destroy", no_argument
, NULL
, 'D'},
452 {"write", required_argument
, NULL
, 'w'},
453 {"append", no_argument
, NULL
, 'a'},
454 {"dump_threads", required_argument
, NULL
, 'n'},
455 {"channel_root", required_argument
, NULL
, 3},
456 { NULL
, 0, NULL
, 0 },
460 * Enable all channels in default
461 * To make novice users happy
463 parst_opt("channel.all.enable=1");
465 opterr
= 1; /* Print error message on getopt_long */
468 c
= getopt_long(argc
, argv
, "cdspho:CDw:an:", longopts
, NULL
);
490 if (!opt_transport
) {
491 opt_transport
= optarg
;
494 "Please specify only 1 transport\n");
499 ret
= parst_opt(optarg
);
516 "Please specify only 1 write dir\n");
524 if (opt_dump_threads
) {
526 "Please specify only 1 dump threads\n");
530 ret
= sscanf(optarg
, "%u", &opt_dump_threads
);
533 "Dump threads not positive number\n");
538 if (!opt_channel_root
) {
539 opt_channel_root
= optarg
;
542 "Please specify only 1 channel root\n");
553 /* Don't check args when user needs help */
558 if (optind
< argc
- 1) {
559 fprintf(stderr
, "Please specify only 1 trace name\n");
562 if (optind
> argc
- 1) {
563 fprintf(stderr
, "Please specify trace name\n");
566 opt_tracename
= argv
[optind
];
571 if (!opt_create
&& !opt_start
&& !opt_destroy
&& !opt_pause
) {
573 "Please specify a option of "
574 "create, destroy, start, or pause\n");
578 if ((opt_create
|| opt_start
) && (opt_destroy
|| opt_pause
)) {
580 "Create and start conflict with destroy and pause\n");
586 opt_transport
= "relay";
592 "Transport option must be combine with create"
599 if (!opt_create
&& !opt_destroy
) {
601 "Write option must be combine with create or"
602 " destroy option\n");
606 if (!opt_channel_root
)
607 if (getdebugfsmntdir(channel_root_default
) == 0) {
608 strcat(channel_root_default
, "/ltt");
609 opt_channel_root
= channel_root_default
;
612 * if (!opt_channel_root)
613 * if (auto_mount_debugfs_dir(channel_root_default) == 0)
614 * opt_channel_root = debugfs_dir_mnt_point;
616 if (!opt_channel_root
) {
618 "Channel_root is necessary for -w option,"
619 " but neither --channel_root option\n"
620 "specified, nor debugfs's mount dir found.\n");
624 if (opt_dump_threads
== 0)
625 opt_dump_threads
= 1;
631 "Append option must be combine with write"
637 if (opt_dump_threads
) {
640 "Dump_threads option must be combine with write"
646 if (opt_channel_root
) {
649 "Channel_root option must be combine with write"
658 static void show_info(void)
660 printf("Linux Trace Toolkit Trace Control " VERSION
"\n");
662 if (opt_tracename
!= NULL
) {
663 printf("Controlling trace : %s\n", opt_tracename
);
668 static int lttctl_create_trace(void)
673 ret
= lttctl_setup_trace(opt_tracename
);
675 goto setup_trace_fail
;
677 for (i
= 0; i
< opt_option_n
; i
++) {
678 if (strcmp(opt_options
[i
].name1
, "channel") != 0)
681 if (strcmp(opt_options
[i
].name3
, "enable") == 0) {
682 ret
= lttctl_set_channel_enable(opt_tracename
,
683 opt_options
[i
].name2
,
684 opt_options
[i
].value
.v_bool
);
686 goto set_option_fail
;
689 if (strcmp(opt_options
[i
].name3
, "overwrite") == 0) {
690 ret
= lttctl_set_channel_overwrite(opt_tracename
,
691 opt_options
[i
].name2
,
692 opt_options
[i
].value
.v_bool
);
694 goto set_option_fail
;
697 if (strcmp(opt_options
[i
].name3
, "bufnum") == 0) {
698 ret
= lttctl_set_channel_subbuf_num(opt_tracename
,
699 opt_options
[i
].name2
,
700 opt_options
[i
].value
.v_uint
);
702 goto set_option_fail
;
705 if (strcmp(opt_options
[i
].name3
, "bufsize") == 0) {
706 ret
= lttctl_set_channel_subbuf_size(opt_tracename
,
707 opt_options
[i
].name2
,
708 opt_options
[i
].value
.v_uint
);
710 goto set_option_fail
;
714 ret
= lttctl_set_trans(opt_tracename
, opt_transport
);
716 goto set_option_fail
;
718 ret
= lttctl_alloc_trace(opt_tracename
);
720 goto alloc_trace_fail
;
726 lttctl_destroy_trace(opt_tracename
);
732 * Start a lttd daemon to write trace datas
733 * Dump overwrite channels on overwrite!=0
734 * Dump normal(non-overwrite) channels on overwrite=0
739 static int lttctl_daemon(int overwrite
)
746 perror("Error in forking for lttd daemon");
754 char channel_path
[PATH_MAX
];
758 argv
[argc
] = getenv("LTT_DAEMON");
759 if (argv
[argc
] == NULL
)
760 argv
[argc
] = PACKAGE_BIN_DIR
"/lttd";
767 * we allow modify of opt_write's content in new process
768 * for get rid of warning of assign char * to const char *
770 argv
[argc
] = (char *)opt_write
;
774 strcpy(channel_path
, opt_channel_root
);
775 strcat(channel_path
, "/");
776 strcat(channel_path
, opt_tracename
);
779 argv
[argc
] = channel_path
;
783 sprintf(thread_num
, "%u", opt_dump_threads
);
786 argv
[argc
] = thread_num
;
799 /* overwrite option */
810 execvp(argv
[0], argv
);
812 perror("Error in executing the lttd daemon");
817 if (waitpid(pid
, &status
, 0) == -1) {
818 perror("Error in waitpid\n");
822 if (!WIFEXITED(status
)) {
823 fprintf(stderr
, "lttd process interrupted\n");
827 if (WEXITSTATUS(status
))
828 fprintf(stderr
, "lttd process running failed\n");
830 return WEXITSTATUS(status
);
833 int main(int argc
, char **argv
)
837 ret
= parse_arguments(argc
, argv
);
838 /* If user needs show help, we disregard other options */
844 /* exit program if arguments wrong */
855 printf("lttctl: Creating trace\n");
856 ret
= lttctl_create_trace();
861 printf("lttctl: Forking lttd\n");
862 ret
= lttctl_daemon(0);
869 printf("lttctl: Starting trace\n");
870 ret
= lttctl_start(opt_tracename
);
876 printf("lttctl: Pausing trace\n");
877 ret
= lttctl_pause(opt_tracename
);
884 printf("lttctl: Forking lttd\n");
885 ret
= lttctl_daemon(1);
890 printf("lttctl: Destroying trace\n");
891 ret
= lttctl_destroy_trace(opt_tracename
);