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>
27 /* Buffer for file copy : 4k seems optimal. */
42 static char *trace_name
= NULL
;
43 static char *trace_type
= "relay";
44 static char *mode_name
= NULL
;
45 static unsigned subbuf_size
= 0;
46 static unsigned n_subbufs
= 0;
47 static unsigned append_trace
= 0;
48 static enum trace_mode mode
= LTT_TRACE_NORMAL
;
49 static enum trace_ctl_op op
= CTL_OP_NONE
;
50 static char *channel_root
= NULL
;
51 static char *trace_root
= NULL
;
52 static char *num_threads
= "1";
54 static int sigchld_received
= 0;
56 void sigchld_handler(int signo
)
58 printf("signal %d received\n", signo
);
66 void show_arguments(void)
68 printf("Please use the following arguments :\n");
70 printf("-n name Name of the trace.\n");
71 printf("-b Create trace channels and start tracing (no daemon).\n");
72 printf("-c Create trace channels.\n");
73 printf("-m mode Normal or flight recorder mode.\n");
74 printf(" Mode values : normal (default) or flight.\n");
75 printf("-r Destroy trace channels.\n");
76 printf("-R Stop tracing and destroy trace channels.\n");
77 printf("-s Start tracing.\n");
78 //printf(" Note : will automatically create a normal trace if "
80 printf("-q Stop tracing.\n");
81 printf("-d Create trace, spawn a lttd daemon, start tracing.\n");
82 printf(" (optionnaly, you can set LTT_DAEMON\n");
83 printf(" and the LTT_FACILITIES env. vars.)\n");
84 printf("-t Trace root path. (ex. /root/traces/example_trace)\n");
85 printf("-T Type of trace (ex. relay)\n");
86 printf("-l LTT channels root path. (ex. /mnt/relayfs/ltt)\n");
87 printf("-z Size of the subbuffers (will be rounded to next page size)\n");
88 printf("-x Number of subbuffers\n");
89 printf("-e Get XML facilities description\n");
90 printf("-a Append to trace\n");
91 printf("-N Number of lttd threads\n");
98 * Parses the command line arguments.
100 * Returns -1 if the arguments were correct, but doesn't ask for program
101 * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
103 int parse_arguments(int argc
, char **argv
)
109 if(strcmp(argv
[1], "-h") == 0) {
116 switch(argv
[argn
][0]) {
118 switch(argv
[argn
][1]) {
121 trace_name
= argv
[argn
+1];
124 printf("Specify a trace name after -n.\n");
131 op
= CTL_OP_CREATE_START
;
138 mode_name
= argv
[argn
+1];
140 if(strcmp(mode_name
, "normal") == 0)
141 mode
= LTT_TRACE_NORMAL
;
142 else if(strcmp(mode_name
, "flight") == 0)
143 mode
= LTT_TRACE_FLIGHT
;
145 printf("Invalid mode '%s'.\n", argv
[argn
]);
150 printf("Specify a mode after -m.\n");
159 op
= CTL_OP_STOP_DESTROY
;
169 subbuf_size
= (unsigned)atoi(argv
[argn
+1]);
172 printf("Specify a number of subbuffers after -z.\n");
179 n_subbufs
= (unsigned)atoi(argv
[argn
+1]);
182 printf("Specify a subbuffer size after -x.\n");
191 op
= CTL_OP_DESCRIPTION
;
195 trace_root
= argv
[argn
+1];
198 printf("Specify a trace root path after -t.\n");
205 channel_root
= argv
[argn
+1];
208 printf("Specify a channel root path after -l.\n");
218 num_threads
= argv
[argn
+1];
224 trace_type
= argv
[argn
+1];
227 printf("Specify a trace type after -T.\n");
233 printf("Invalid argument '%s'.\n", argv
[argn
]);
239 printf("Invalid argument '%s'.\n", argv
[argn
]);
246 if(op
!= CTL_OP_DESCRIPTION
&& trace_name
== NULL
) {
247 printf("Please specify a trace name.\n");
252 if(op
== CTL_OP_NONE
) {
253 printf("Please specify an operation.\n");
258 if(op
== CTL_OP_DAEMON
) {
259 if(trace_root
== NULL
) {
260 printf("Please specify -t trace_root_path with the -d option.\n");
264 if(channel_root
== NULL
) {
265 printf("Please specify -l ltt_root_path with the -d option.\n");
271 if(op
== CTL_OP_DESCRIPTION
) {
272 if(trace_root
== NULL
) {
273 printf("Please specify -t trace_root_path with the -e option.\n");
284 printf("Linux Trace Toolkit Trace Control\n");
286 if(trace_name
!= NULL
) {
287 printf("Controlling trace : %s\n", trace_name
);
292 int create_eventdefs(void)
295 char eventdefs_path
[PATH_MAX
];
296 char eventdefs_file
[PATH_MAX
];
297 char facilities_file
[PATH_MAX
];
298 char read_buf
[BUF_SIZE
];
299 struct dirent
*entry
;
300 char *facilities_path
= getenv("LTT_FACILITIES");
301 if(facilities_path
== NULL
) facilities_path
=
302 PACKAGE_DATA_DIR
"/" PACKAGE
"/facilities";
304 ret
= mkdir(trace_root
, S_IRWXU
|S_IRWXG
|S_IRWXO
);
305 if(ret
== -1 && errno
!= EEXIST
) {
307 perror("Cannot create trace_root directory");
308 printf("trace_root is %s\n", trace_root
);
313 size_t trace_root_len
= strlen(trace_root
);
314 strncpy(eventdefs_path
, trace_root
, PATH_MAX
);
315 strncat(eventdefs_path
, "/eventdefs/", PATH_MAX
- trace_root_len
);
316 size_t eventdefs_path_len
= strlen(eventdefs_path
);
317 ret
= mkdir(eventdefs_path
, S_IRWXU
|S_IRWXG
|S_IRWXO
);
318 if(ret
== -1 && (!append_trace
|| errno
!= EEXIST
)) {
320 perror("Cannot create eventdefs directory");
325 DIR *facilities_dir
= opendir(facilities_path
);
327 if(facilities_dir
== NULL
) {
328 perror("Cannot open facilities directory");
333 while((entry
= readdir(facilities_dir
)) != NULL
) {
334 if(entry
->d_name
[0] == '.') continue;
336 printf("Appending facility file %s\n", entry
->d_name
);
337 strncpy(eventdefs_file
, eventdefs_path
, PATH_MAX
);
338 strncat(eventdefs_file
, entry
->d_name
, PATH_MAX
- eventdefs_path_len
);
339 /* Append to the file */
340 FILE *dest
= fopen(eventdefs_file
, "a");
342 perror("Cannot create eventdefs file");
345 strncpy(facilities_file
, facilities_path
, PATH_MAX
);
346 size_t facilities_dir_len
= strlen(facilities_path
);
347 strncat(facilities_file
, "/", PATH_MAX
- facilities_dir_len
);
348 strncat(facilities_file
, entry
->d_name
, PATH_MAX
- facilities_dir_len
-1);
349 FILE *src
= fopen(facilities_file
, "r");
352 perror("Cannot open eventdefs file for reading");
357 size_t read_size
, write_size
;
358 read_size
= fread(read_buf
, sizeof(char), BUF_SIZE
, src
);
361 perror("Cannot read eventdefs file");
364 write_size
= fwrite(read_buf
, sizeof(char), read_size
, dest
);
367 perror("Cannot write eventdefs file");
372 /* Add spacing between facilities */
373 fwrite("\n", 1, 1, dest
);
381 closedir(facilities_dir
);
389 int lttctl_daemon(struct lttctl_handle
*handle
, char *trace_name
)
391 char channel_path
[PATH_MAX
] = "";
394 char *lttd_path
= getenv("LTT_DAEMON");
395 struct sigaction act
;
397 if(lttd_path
== NULL
) lttd_path
=
398 PACKAGE_BIN_DIR
"/lttd";
400 strcat(channel_path
, channel_root
);
401 strcat(channel_path
, "/");
402 strcat(channel_path
, trace_name
);
405 ret
= lttctl_create_trace(handle
, trace_name
, mode
, trace_type
, subbuf_size
, n_subbufs
);
406 if(ret
!= 0) goto create_error
;
408 act
.sa_handler
= sigchld_handler
;
409 sigemptyset(&(act
.sa_mask
));
410 sigaddset(&(act
.sa_mask
), SIGCHLD
);
411 sigaction(SIGCHLD
, &act
, NULL
);
418 while(!(sigchld_received
)) pause();
420 waitpid(pid
, &status
, 0);
422 if(WIFEXITED(status
))
423 ret
= WEXITSTATUS(status
);
424 if(ret
) goto start_error
;
426 printf("Creating supplementary trace files\n");
427 ret
= create_eventdefs();
428 if(ret
) goto start_error
;
430 } else if(pid
== 0) {
434 ret
= execlp(lttd_path
, lttd_path
, "-t", trace_root
, "-c",
435 channel_path
, "-d", "-a", "-N", num_threads
, NULL
);
437 ret
= execlp(lttd_path
, lttd_path
, "-t", trace_root
, "-c",
438 channel_path
, "-d", "-N", num_threads
, NULL
);
441 perror("Error in executing the lttd daemon");
446 perror("Error in forking for lttd daemon");
449 ret
= lttctl_start(handle
, trace_name
);
450 if(ret
!= 0) goto start_error
;
456 printf("Trace start error\n");
457 ret
|= lttctl_destroy_trace(handle
, trace_name
);
462 int main(int argc
, char ** argv
)
465 struct lttctl_handle
*handle
;
467 ret
= parse_arguments(argc
, argv
);
469 if(ret
!= 0) show_arguments();
470 if(ret
== EINVAL
) return EINVAL
;
471 if(ret
== -1) return 0;
475 handle
= lttctl_create_handle();
477 if(handle
== NULL
) return -1;
480 case CTL_OP_CREATE_START
:
481 ret
= lttctl_create_trace(handle
, trace_name
, mode
, trace_type
, subbuf_size
,
484 ret
= lttctl_start(handle
, trace_name
);
487 ret
= lttctl_create_trace(handle
, trace_name
, mode
, trace_type
, subbuf_size
,
491 ret
= lttctl_destroy_trace(handle
, trace_name
);
493 case CTL_OP_STOP_DESTROY
:
494 ret
= lttctl_stop(handle
, trace_name
);
496 ret
= lttctl_destroy_trace(handle
, trace_name
);
499 ret
= lttctl_start(handle
, trace_name
);
502 ret
= lttctl_stop(handle
, trace_name
);
505 ret
= lttctl_daemon(handle
, trace_name
);
507 case CTL_OP_DESCRIPTION
:
508 ret
= create_eventdefs();
514 ret
|= lttctl_destroy_handle(handle
);
This page took 0.058285 seconds and 5 git commands to generate.