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>
19 #include <sys/types.h>
28 /* Buffer for file copy : 4k seems optimal. */
39 CTL_OP_DAEMON_HYBRID_FINISH
,
43 static char *trace_name
= NULL
;
44 static char *trace_type
= "relay";
45 static char *mode_name
= NULL
;
46 static unsigned subbuf_size_low
= 0;
47 static unsigned n_subbufs_low
= 0;
48 static unsigned subbuf_size_med
= 0;
49 static unsigned n_subbufs_med
= 0;
50 static unsigned subbuf_size_high
= 0;
51 static unsigned n_subbufs_high
= 0;
52 static unsigned append_trace
= 0;
53 static enum trace_mode mode
= LTT_TRACE_NORMAL
;
54 static enum trace_ctl_op op
= CTL_OP_NONE
;
55 static char *channel_root
= NULL
;
56 static char channel_root_default
[PATH_MAX
];
57 static char *trace_root
= NULL
;
58 static char *num_threads
= "1";
63 void show_arguments(void)
65 printf("Please use the following arguments :\n");
67 printf("-n name Name of the trace.\n");
68 printf("-b Create trace channels and start tracing (no daemon).\n");
69 printf("-c Create trace channels.\n");
70 printf("-m mode Normal, flight recorder or hybrid mode.\n");
71 printf(" Mode values : normal (default), flight or hybrid.\n");
72 printf("-r Destroy trace channels.\n");
73 printf("-R Stop tracing and destroy trace channels.\n");
74 printf("-s Start tracing.\n");
75 //printf(" Note : will automatically create a normal trace if "
77 printf("-q Stop tracing.\n");
78 printf("-d Create trace, spawn a lttd daemon, start tracing.\n");
79 printf(" (optionally, you can set LTT_DAEMON\n");
80 printf(" env. var.)\n");
81 printf("-f Stop tracing, dump flight recorder trace, destroy channels\n");
82 printf(" (for hybrid traces)\n");
83 printf("-t Trace root path. (ex. /root/traces/example_trace)\n");
84 printf("-T Type of trace (ex. relay)\n");
85 printf("-l LTT channels root path. (ex. /mnt/debugfs/ltt)\n");
86 printf("-Z Size of the low data rate subbuffers (will be rounded to next page size)\n");
87 printf("-X Number of low data rate subbuffers\n");
88 printf("-V Size of the medium data rate subbuffers (will be rounded to next page size)\n");
89 printf("-B Number of medium data rate subbuffers\n");
90 printf("-z Size of the high data rate subbuffers (will be rounded to next page size)\n");
91 printf("-x Number of high data rate subbuffers\n");
92 printf("-a Append to trace\n");
93 printf("-N Number of lttd threads\n");
97 int getdebugfsmntdir(char *mntdir
)
99 char mnt_dir
[PATH_MAX
];
100 char mnt_type
[PATH_MAX
];
102 FILE *fp
= fopen("/proc/mounts", "r");
108 if (fscanf(fp
, "%*s %s %s %*s %*s %*s", mnt_dir
, mnt_type
) <= 0) {
111 if (!strcmp(mnt_type
, "debugfs")) {
112 strcpy(mntdir
, mnt_dir
);
120 * Parses the command line arguments.
122 * Returns -1 if the arguments were correct, but doesn't ask for program
123 * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
125 int parse_arguments(int argc
, char **argv
)
131 if(strcmp(argv
[1], "-h") == 0) {
138 switch(argv
[argn
][0]) {
140 switch(argv
[argn
][1]) {
143 trace_name
= argv
[argn
+1];
146 printf("Specify a trace name after -n.\n");
153 op
= CTL_OP_CREATE_START
;
160 mode_name
= argv
[argn
+1];
162 if(strcmp(mode_name
, "normal") == 0)
163 mode
= LTT_TRACE_NORMAL
;
164 else if(strcmp(mode_name
, "flight") == 0)
165 mode
= LTT_TRACE_FLIGHT
;
166 else if(strcmp(mode_name
, "hybrid") == 0)
167 mode
= LTT_TRACE_HYBRID
;
169 printf("Invalid mode '%s'.\n", argv
[argn
]);
174 printf("Specify a mode after -m.\n");
183 op
= CTL_OP_STOP_DESTROY
;
193 subbuf_size_low
= (unsigned)atoi(argv
[argn
+1]);
196 printf("Specify a number of low traffic subbuffers after -Z.\n");
203 n_subbufs_low
= (unsigned)atoi(argv
[argn
+1]);
206 printf("Specify a low traffic subbuffer size after -X.\n");
213 subbuf_size_med
= (unsigned)atoi(argv
[argn
+1]);
216 printf("Specify a number of medium traffic subbuffers after -V.\n");
223 n_subbufs_med
= (unsigned)atoi(argv
[argn
+1]);
226 printf("Specify a medium traffic subbuffer size after -B.\n");
233 subbuf_size_high
= (unsigned)atoi(argv
[argn
+1]);
236 printf("Specify a number of high traffic subbuffers after -z.\n");
243 n_subbufs_high
= (unsigned)atoi(argv
[argn
+1]);
246 printf("Specify a high traffic subbuffer size after -x.\n");
255 op
= CTL_OP_DAEMON_HYBRID_FINISH
;
259 trace_root
= argv
[argn
+1];
262 printf("Specify a trace root path after -t.\n");
269 channel_root
= argv
[argn
+1];
272 printf("Specify a channel root path after -l.\n");
282 num_threads
= argv
[argn
+1];
288 trace_type
= argv
[argn
+1];
291 printf("Specify a trace type after -T.\n");
297 printf("Invalid argument '%s'.\n", argv
[argn
]);
303 printf("Invalid argument '%s'.\n", argv
[argn
]);
310 if(trace_name
== NULL
) {
311 printf("Please specify a trace name.\n");
316 if(op
== CTL_OP_NONE
) {
317 printf("Please specify an operation.\n");
322 if(op
== CTL_OP_DAEMON
|| op
== CTL_OP_DAEMON_HYBRID_FINISH
) {
323 if(trace_root
== NULL
) {
324 printf("Please specify -t trace_root_path with the -d option.\n");
328 if(channel_root
== NULL
) {
329 if (getdebugfsmntdir(channel_root_default
) == 0) {
330 strcat(channel_root_default
, "/ltt");
331 printf("No -l ltt_root_path with the -d option, using default: %s\n", channel_root_default
);
333 channel_root
=channel_root_default
;
335 printf("Please specify -l ltt_root_path with the -d option.\n");
347 printf("Linux Trace Toolkit Trace Control " VERSION
"\n");
349 if(trace_name
!= NULL
) {
350 printf("Controlling trace : %s\n", trace_name
);
355 int lttctl_daemon(struct lttctl_handle
*handle
, char *trace_name
)
357 char channel_path
[PATH_MAX
] = "";
360 char *lttd_path
= getenv("LTT_DAEMON");
362 if(lttd_path
== NULL
) lttd_path
=
363 PACKAGE_BIN_DIR
"/lttd";
365 strcat(channel_path
, channel_root
);
366 strcat(channel_path
, "/");
367 strcat(channel_path
, trace_name
);
370 ret
= lttctl_create_trace(handle
, trace_name
, mode
, trace_type
,
371 subbuf_size_low
, n_subbufs_low
,
372 subbuf_size_med
, n_subbufs_med
,
373 subbuf_size_high
, n_subbufs_high
);
374 if(ret
!= 0) goto create_error
;
382 ret
= waitpid(pid
, &status
, 0);
385 perror("Error in waitpid");
390 if(WIFEXITED(status
))
391 ret
= WEXITSTATUS(status
);
392 if(ret
) goto start_error
;
394 } else if(pid
== 0) {
397 if(mode
!= LTT_TRACE_HYBRID
) {
399 ret
= execlp(lttd_path
, lttd_path
, "-t", trace_root
, "-c",
400 channel_path
, "-d", "-a", "-N", num_threads
, NULL
);
402 ret
= execlp(lttd_path
, lttd_path
, "-t", trace_root
, "-c",
403 channel_path
, "-d", "-N", num_threads
, NULL
);
406 ret
= execlp(lttd_path
, lttd_path
, "-t", trace_root
, "-c",
407 channel_path
, "-d", "-a", "-N", num_threads
, "-n", NULL
);
409 ret
= execlp(lttd_path
, lttd_path
, "-t", trace_root
, "-c",
410 channel_path
, "-d", "-N", num_threads
, "-n", NULL
);
414 perror("Error in executing the lttd daemon");
419 perror("Error in forking for lttd daemon");
422 ret
= lttctl_start(handle
, trace_name
);
423 if(ret
!= 0) goto start_error
;
429 printf("Trace start error\n");
430 ret
|= lttctl_destroy_trace(handle
, trace_name
);
438 int lttctl_daemon_hybrid_finish(struct lttctl_handle
*handle
, char *trace_name
)
440 char channel_path
[PATH_MAX
] = "";
443 char *lttd_path
= getenv("LTT_DAEMON");
445 if(lttd_path
== NULL
) lttd_path
=
446 PACKAGE_BIN_DIR
"/lttd";
448 strcat(channel_path
, channel_root
);
449 strcat(channel_path
, "/");
450 strcat(channel_path
, trace_name
);
453 ret
= lttctl_stop(handle
, trace_name
);
454 if(ret
!= 0) goto stop_error
;
462 ret
= waitpid(pid
, &status
, 0);
465 perror("Error in waitpid");
470 if(WIFEXITED(status
))
471 ret
= WEXITSTATUS(status
);
472 if(ret
) goto destroy_error
;
474 } else if(pid
== 0) {
478 ret
= execlp(lttd_path
, lttd_path
, "-t", trace_root
, "-c",
479 channel_path
, "-d", "-a", "-N", num_threads
, "-f", NULL
);
481 ret
= execlp(lttd_path
, lttd_path
, "-t", trace_root
, "-c",
482 channel_path
, "-d", "-N", num_threads
, "-f", NULL
);
485 perror("Error in executing the lttd daemon");
490 perror("Error in forking for lttd daemon");
493 ret
= lttctl_destroy_trace(handle
, trace_name
);
494 if(ret
!= 0) goto destroy_error
;
500 printf("Hybrid trace destroy error\n");
507 int main(int argc
, char ** argv
)
510 struct lttctl_handle
*handle
;
512 ret
= parse_arguments(argc
, argv
);
514 if(ret
!= 0) show_arguments();
515 if(ret
== EINVAL
) return EINVAL
;
516 if(ret
== -1) return 0;
520 handle
= lttctl_create_handle();
522 if(handle
== NULL
) return -1;
525 case CTL_OP_CREATE_START
:
526 ret
= lttctl_create_trace(handle
, trace_name
, mode
, trace_type
,
527 subbuf_size_low
, n_subbufs_low
,
528 subbuf_size_med
, n_subbufs_med
,
529 subbuf_size_high
, n_subbufs_high
);
531 ret
= lttctl_start(handle
, trace_name
);
534 ret
= lttctl_create_trace(handle
, trace_name
, mode
, trace_type
,
535 subbuf_size_low
, n_subbufs_low
,
536 subbuf_size_med
, n_subbufs_med
,
537 subbuf_size_high
, n_subbufs_high
);
540 ret
= lttctl_destroy_trace(handle
, trace_name
);
542 case CTL_OP_STOP_DESTROY
:
543 ret
= lttctl_stop(handle
, trace_name
);
545 ret
= lttctl_destroy_trace(handle
, trace_name
);
548 ret
= lttctl_start(handle
, trace_name
);
551 ret
= lttctl_stop(handle
, trace_name
);
554 ret
= lttctl_daemon(handle
, trace_name
);
556 case CTL_OP_DAEMON_HYBRID_FINISH
:
557 ret
= lttctl_daemon_hybrid_finish(handle
, trace_name
);
563 ret
|= lttctl_destroy_handle(handle
);