c1a49cd4f8dff16179e6ad03436cc98376885ed8
3 * Linux Trace Toolkit Control
5 * Small program that controls LTT through libltt.
8 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
10 * Copyright 2008 FUJITSU
11 * Zhao Lei <zhaolei@cn.fujitsu.com>
12 * Gui Jianfeng <guijianfeng@cn.fujitsu.com>
19 #include <liblttctl/lttctl.h>
30 #define OPT_MAX (1024)
31 #define OPT_NAMELEN (256)
32 #define OPT_VALSTRINGLEN (256)
38 struct channel_option
{
39 char chan_name
[OPT_NAMELEN
];
46 struct lttctl_option
{
48 struct channel_option chan_opt
;
51 struct lttctl_option
*next
;
54 struct lttctl_option
*opt_head
, *last_opt
;
56 static int opt_create
;
57 static int opt_destroy
;
61 static const char *opt_transport
;
62 static const char *opt_write
;
63 static int opt_append
;
64 static unsigned int opt_dump_threads
;
65 static char channel_root_default
[PATH_MAX
];
66 static const char *opt_channel_root
;
67 static const char *opt_tracename
;
72 static void show_arguments(void)
74 printf("Linux Trace Toolkit Trace Control " VERSION
"\n");
76 printf("Usage: lttctl [OPTION]... [TRACENAME]\n");
78 printf("Examples:\n");
79 printf(" lttctl -c trace1 "
80 "# Create a trace named trace1.\n");
81 printf(" lttctl -s trace1 "
82 "# start a trace named trace1.\n");
83 printf(" lttctl -p trace1 "
84 "# pause a trace named trace1.\n");
85 printf(" lttctl -d trace1 "
86 "# Destroy a trace named trace1.\n");
87 printf(" lttctl -C -w /tmp/trace1 trace1 "
88 "# Create a trace named trace1, start it and\n"
90 "# write non-overwrite channels' data to\n"
92 "# /tmp/trace1, debugfs must be mounted for\n"
95 printf(" lttctl -D -w /tmp/trace1 trace1 "
96 "# Pause and destroy a trace named trace1 and\n"
98 "# write overwrite channels' data to\n"
100 "# /tmp/trace1, debugfs must be mounted for\n"
104 printf(" Basic options:\n");
105 printf(" -c, --create\n");
106 printf(" Create a trace.\n");
107 printf(" -d, --destroy\n");
108 printf(" Destroy a trace.\n");
109 printf(" -s, --start\n");
110 printf(" Start a trace.\n");
111 printf(" -p, --pause\n");
112 printf(" Pause a trace.\n");
113 printf(" -h, --help\n");
114 printf(" Show this help.\n");
116 printf(" Advanced options:\n");
117 printf(" --transport TRANSPORT\n");
118 printf(" Set trace's transport. (ex. relay)\n");
119 printf(" -o, --option OPTION\n");
120 printf(" Set options, following operations are supported:\n");
121 printf(" channel.<channelname>.enable=\n");
122 printf(" channel.<channelname>.overwrite=\n");
123 printf(" channel.<channelname>.bufnum=\n");
124 printf(" channel.<channelname>.bufsize=\n");
125 printf(" <channelname> can be set to all for all channels\n");
127 printf(" Integration options:\n");
128 printf(" -C, --create_start\n");
129 printf(" Create and start a trace.\n");
130 printf(" -D, --pause_destroy\n");
131 printf(" Pause and destroy a trace.\n");
132 printf(" -w, --write PATH\n");
133 printf(" Path for write trace datas.\n");
134 printf(" For -c, -C, -d, -D options\n");
135 printf(" -a, --append\n");
136 printf(" Append to trace, For -w option\n");
137 printf(" -n, --dump_threads NUMBER\n");
138 printf(" Number of lttd threads, For -w option\n");
139 printf(" --channel_root PATH\n");
140 printf(" Set channels root path, For -w option."
141 " (ex. /mnt/debugfs/ltt)\n");
145 static int getdebugfsmntdir(char *mntdir
)
147 char mnt_dir
[PATH_MAX
];
148 char mnt_type
[PATH_MAX
];
150 FILE *fp
= fopen("/proc/mounts", "r");
155 if (fscanf(fp
, "%*s %s %s %*s %*s %*s", mnt_dir
, mnt_type
) <= 0)
158 if (!strcmp(mnt_type
, "debugfs")) {
159 strcpy(mntdir
, mnt_dir
);
166 * Separate option name to 3 fields
168 * Input: name = channel.cpu.bufsize
169 * Output: name1 = channel
176 * Make sure that name1~3 longer than OPT_NAMELEN.
177 * name1~3 can be NULL to discard value
180 static int separate_opt(const char *name
, char *name1
, char *name2
, char *name3
)
188 p
= strchr(name
, '.');
191 if (p
- name
>= OPT_NAMELEN
)
194 memcpy(name1
, name
, p
- name
);
200 p
= strchr(name
, '.');
203 if (p
- name
>= OPT_NAMELEN
)
206 memcpy(name2
, name
, p
- name
);
212 if (strlen(name
) >= OPT_NAMELEN
)
220 static void init_channel_opt(struct channel_option
*opt
, char *opt_name
)
222 if (opt
&& opt_name
) {
227 strcpy(opt
->chan_name
, opt_name
);
231 static struct lttctl_option
*find_insert_channel_opt(char *opt_name
)
233 struct lttctl_option
*iter
, *new_opt
;
236 opt_head
= (struct lttctl_option
*)malloc(sizeof(struct lttctl_option
));
237 init_channel_opt(&opt_head
->opt_mode
.chan_opt
, opt_name
);
238 opt_head
->type
= CHANNEL
;
239 opt_head
->next
= NULL
;
244 for (iter
= opt_head
; iter
; iter
= iter
->next
) {
245 if (iter
->type
!= CHANNEL
)
247 if (!strcmp(iter
->opt_mode
.chan_opt
.chan_name
, opt_name
))
251 new_opt
= (struct lttctl_option
*)malloc(sizeof(struct lttctl_option
));
252 init_channel_opt(&new_opt
->opt_mode
.chan_opt
, opt_name
);
253 new_opt
->type
= CHANNEL
;
254 new_opt
->next
= NULL
;
255 last_opt
->next
= new_opt
;
260 int set_channel_opt(struct channel_option
*opt
, char *opt_name
, char *opt_valstr
)
264 if (!strcmp("enable", opt_name
)) {
265 if (opt_valstr
[1] != 0) {
268 if (opt_valstr
[0] == 'Y' || opt_valstr
[0] == 'y'
269 || opt_valstr
[0] == '1')
271 else if (opt_valstr
[0] == 'N' || opt_valstr
[0] == 'n'
272 || opt_valstr
[0] == '0')
278 opt
->enable
= opt_val
;
280 } else if (!strcmp("overwrite", opt_name
)) {
281 if (opt_valstr
[1] != 0) {
284 if (opt_valstr
[0] == 'Y' || opt_valstr
[0] == 'y'
285 || opt_valstr
[0] == '1')
287 else if (opt_valstr
[0] == 'N' || opt_valstr
[0] == 'n'
288 || opt_valstr
[0] == '0')
294 opt
->overwrite
= opt_val
;
297 } else if (!strcmp("bufnum", opt_name
)) {
298 ret
= sscanf(opt_valstr
, "%d", &opt_val
);
299 if (ret
!= 1 || opt_val
< 0) {
303 opt
->bufnum
= opt_val
;
305 } else if (!strcmp("bufsize", opt_name
)) {
306 ret
= sscanf(opt_valstr
, "%d", &opt_val
);
307 if (ret
!= 1 || opt_val
< 0) {
311 opt
->bufsize
= opt_val
;
319 static int parst_opt(const char *optarg
)
322 char opt_name
[OPT_NAMELEN
* 3];
323 char opt_valstr
[OPT_VALSTRINGLEN
];
326 char name1
[OPT_NAMELEN
];
327 char name2
[OPT_NAMELEN
];
328 char name3
[OPT_NAMELEN
];
332 unsigned int opt_uintval
;
333 struct lttctl_option
*opt
;
336 fprintf(stderr
, "Option empty\n");
340 /* Get option name and val_str */
341 p
= strchr(optarg
, '=');
343 fprintf(stderr
, "Option format error: %s\n", optarg
);
347 if (p
- optarg
>= sizeof(opt_name
)/sizeof(opt_name
[0])) {
348 fprintf(stderr
, "Option name too long: %s\n", optarg
);
352 if (strlen(p
+1) >= OPT_VALSTRINGLEN
) {
353 fprintf(stderr
, "Option value too long: %s\n", optarg
);
357 memcpy(opt_name
, optarg
, p
- optarg
);
358 opt_name
[p
- optarg
] = 0;
359 strcpy(opt_valstr
, p
+1);
361 /* separate option name into 3 fields */
362 ret
= separate_opt(opt_name
, name1
, name2
, name3
);
364 fprintf(stderr
, "Option name error1: %s\n", optarg
);
368 if (!strcmp("channel", name1
)) {
369 opt
= find_insert_channel_opt(name2
);
370 if ((ret
= set_channel_opt(&opt
->opt_mode
.chan_opt
,
371 name3
, opt_valstr
) != 0)) {
372 fprintf(stderr
, "Option name error2: %s\n", optarg
);
376 fprintf(stderr
, "Option name error3: %s\n", optarg
);
385 * Parses the command line arguments.
387 * Returns -1 if the arguments were correct, but doesn't ask for program
388 * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
390 static int parse_arguments(int argc
, char **argv
)
394 static struct option longopts
[] = {
395 {"create", no_argument
, NULL
, 'c'},
396 {"destroy", no_argument
, NULL
, 'd'},
397 {"start", no_argument
, NULL
, 's'},
398 {"pause", no_argument
, NULL
, 'p'},
399 {"help", no_argument
, NULL
, 'h'},
400 {"transport", required_argument
, NULL
, 2},
401 {"option", required_argument
, NULL
, 'o'},
402 {"create_start", no_argument
, NULL
, 'C'},
403 {"pause_destroy", no_argument
, NULL
, 'D'},
404 {"write", required_argument
, NULL
, 'w'},
405 {"append", no_argument
, NULL
, 'a'},
406 {"dump_threads", required_argument
, NULL
, 'n'},
407 {"channel_root", required_argument
, NULL
, 3},
408 { NULL
, 0, NULL
, 0 },
412 * Enable all channels in default
413 * To make novice users happy
415 parst_opt("channel.all.enable=1");
417 opterr
= 1; /* Print error message on getopt_long */
420 c
= getopt_long(argc
, argv
, "cdspho:CDw:an:", longopts
, NULL
);
442 if (!opt_transport
) {
443 opt_transport
= optarg
;
446 "Please specify only 1 transport\n");
451 ret
= parst_opt(optarg
);
468 "Please specify only 1 write dir\n");
476 if (opt_dump_threads
) {
478 "Please specify only 1 dump threads\n");
482 ret
= sscanf(optarg
, "%u", &opt_dump_threads
);
485 "Dump threads not positive number\n");
490 if (!opt_channel_root
) {
491 opt_channel_root
= optarg
;
494 "Please specify only 1 channel root\n");
505 /* Don't check args when user needs help */
510 if (optind
< argc
- 1) {
511 fprintf(stderr
, "Please specify only 1 trace name\n");
514 if (optind
> argc
- 1) {
515 fprintf(stderr
, "Please specify trace name\n");
518 opt_tracename
= argv
[optind
];
523 if (!opt_create
&& !opt_start
&& !opt_destroy
&& !opt_pause
) {
525 "Please specify a option of "
526 "create, destroy, start, or pause\n");
530 if ((opt_create
|| opt_start
) && (opt_destroy
|| opt_pause
)) {
532 "Create and start conflict with destroy and pause\n");
538 opt_transport
= "relay";
544 "Transport option must be combine with create"
551 if (!opt_create
&& !opt_destroy
) {
553 "Write option must be combine with create or"
554 " destroy option\n");
558 if (!opt_channel_root
)
559 if (getdebugfsmntdir(channel_root_default
) == 0) {
560 strcat(channel_root_default
, "/ltt");
561 opt_channel_root
= channel_root_default
;
564 * if (!opt_channel_root)
565 * if (auto_mount_debugfs_dir(channel_root_default) == 0)
566 * opt_channel_root = debugfs_dir_mnt_point;
568 if (!opt_channel_root
) {
570 "Channel_root is necessary for -w option,"
571 " but neither --channel_root option\n"
572 "specified, nor debugfs's mount dir found.\n");
576 if (opt_dump_threads
== 0)
577 opt_dump_threads
= 1;
583 "Append option must be combine with write"
589 if (opt_dump_threads
) {
592 "Dump_threads option must be combine with write"
598 if (opt_channel_root
) {
601 "Channel_root option must be combine with write"
610 static void show_info(void)
612 printf("Linux Trace Toolkit Trace Control " VERSION
"\n");
614 if (opt_tracename
!= NULL
) {
615 printf("Controlling trace : %s\n", opt_tracename
);
620 static int lttctl_channel_setup(struct channel_option
*opt
)
624 if (opt
->enable
!= -1) {
625 if ((ret
= lttctl_set_channel_enable(opt_tracename
,
630 if (opt
->overwrite
!= -1) {
631 if ((ret
= lttctl_set_channel_overwrite(opt_tracename
,
633 opt
->overwrite
)) != 0)
636 if (opt
->bufnum
!= -1) {
637 if ((ret
= lttctl_set_channel_subbuf_num(opt_tracename
,
642 if (opt
->bufsize
!= -1) {
643 if ((ret
= lttctl_set_channel_subbuf_size(opt_tracename
,
652 static int lttctl_create_trace(void)
656 struct lttctl_option
*opt
;
658 ret
= lttctl_setup_trace(opt_tracename
);
660 goto setup_trace_fail
;
662 for (opt
= opt_head
; opt
; opt
= opt
->next
) {
663 if (opt
->type
!= CHANNEL
)
665 ret
= lttctl_channel_setup(&opt
->opt_mode
.chan_opt
);
667 goto set_option_fail
;;
670 ret
= lttctl_set_trans(opt_tracename
, opt_transport
);
672 goto set_option_fail
;
674 ret
= lttctl_alloc_trace(opt_tracename
);
676 goto alloc_trace_fail
;
682 lttctl_destroy_trace(opt_tracename
);
688 * Start a lttd daemon to write trace datas
689 * Dump overwrite channels on overwrite!=0
690 * Dump normal(non-overwrite) channels on overwrite=0
695 static int lttctl_daemon(int overwrite
)
702 perror("Error in forking for lttd daemon");
710 char channel_path
[PATH_MAX
];
714 argv
[argc
] = getenv("LTT_DAEMON");
715 if (argv
[argc
] == NULL
)
716 argv
[argc
] = PACKAGE_BIN_DIR
"/lttd";
723 * we allow modify of opt_write's content in new process
724 * for get rid of warning of assign char * to const char *
726 argv
[argc
] = (char *)opt_write
;
730 strcpy(channel_path
, opt_channel_root
);
731 strcat(channel_path
, "/");
732 strcat(channel_path
, opt_tracename
);
735 argv
[argc
] = channel_path
;
739 sprintf(thread_num
, "%u", opt_dump_threads
);
742 argv
[argc
] = thread_num
;
755 /* overwrite option */
766 execvp(argv
[0], argv
);
768 perror("Error in executing the lttd daemon");
773 if (waitpid(pid
, &status
, 0) == -1) {
774 perror("Error in waitpid\n");
778 if (!WIFEXITED(status
)) {
779 fprintf(stderr
, "lttd process interrupted\n");
783 if (WEXITSTATUS(status
))
784 fprintf(stderr
, "lttd process running failed\n");
786 return WEXITSTATUS(status
);
789 int main(int argc
, char **argv
)
793 ret
= parse_arguments(argc
, argv
);
794 /* If user needs show help, we disregard other options */
800 /* exit program if arguments wrong */
811 printf("lttctl: Creating trace\n");
812 ret
= lttctl_create_trace();
817 printf("lttctl: Forking lttd\n");
818 ret
= lttctl_daemon(0);
825 printf("lttctl: Starting trace\n");
826 ret
= lttctl_start(opt_tracename
);
832 printf("lttctl: Pausing trace\n");
833 ret
= lttctl_pause(opt_tracename
);
840 printf("lttctl: Forking lttd\n");
841 ret
= lttctl_daemon(1);
846 printf("lttctl: Destroying trace\n");
847 ret
= lttctl_destroy_trace(opt_tracename
);
This page took 0.056723 seconds and 4 git commands to generate.