remove facilities from lttctl
[lttv.git] / ltt-control / lttctl / lttctl.c
CommitLineData
2cdb6fcb 1/* lttctl
2 *
3 * Linux Trace Toolkit Control
4 *
5 * Small program that controls LTT through libltt.
6 *
7 * Copyright 2005 -
8 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
9 */
10
4e4d11b3 11#ifdef HAVE_CONFIG_H
12#include <config.h>
13#endif
14
5cec0a15 15#include <liblttctl/lttctl.h>
5adba60f 16#include <errno.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/types.h>
86a65fdb 20#include <sys/wait.h>
5adba60f 21#include <unistd.h>
22#include <signal.h>
d5fbdb60 23#include <dirent.h>
24#include <string.h>
25#include <sys/stat.h>
26
27/* Buffer for file copy : 4k seems optimal. */
2312de30 28#define BUF_SIZE 4096
2cdb6fcb 29
5adba60f 30enum trace_ctl_op {
24331c3d 31 CTL_OP_CREATE_START,
5adba60f 32 CTL_OP_CREATE,
33 CTL_OP_DESTROY,
24331c3d 34 CTL_OP_STOP_DESTROY,
5adba60f 35 CTL_OP_START,
36 CTL_OP_STOP,
37 CTL_OP_DAEMON,
d24c12e7 38 CTL_OP_DAEMON_HYBRID_FINISH,
5adba60f 39 CTL_OP_NONE
40};
2cdb6fcb 41
5adba60f 42static char *trace_name = NULL;
313b3771 43static char *trace_type = "relay";
5adba60f 44static char *mode_name = NULL;
d24c12e7 45static unsigned subbuf_size_low = 0;
46static unsigned n_subbufs_low = 0;
47static unsigned subbuf_size_med = 0;
48static unsigned n_subbufs_med = 0;
49static unsigned subbuf_size_high = 0;
50static unsigned n_subbufs_high = 0;
45653836 51static unsigned append_trace = 0;
5adba60f 52static enum trace_mode mode = LTT_TRACE_NORMAL;
53static enum trace_ctl_op op = CTL_OP_NONE;
54static char *channel_root = NULL;
55static char *trace_root = NULL;
22acb617 56static char *num_threads = "1";
5adba60f 57
5adba60f 58/* Args :
59 *
60 */
61void show_arguments(void)
62{
63 printf("Please use the following arguments :\n");
64 printf("\n");
2299770f 65 printf("-n name Name of the trace.\n");
66 printf("-b Create trace channels and start tracing (no daemon).\n");
67 printf("-c Create trace channels.\n");
d24c12e7 68 printf("-m mode Normal, flight recorder or hybrid mode.\n");
69 printf(" Mode values : normal (default), flight or hybrid.\n");
2299770f 70 printf("-r Destroy trace channels.\n");
71 printf("-R Stop tracing and destroy trace channels.\n");
72 printf("-s Start tracing.\n");
73 //printf(" Note : will automatically create a normal trace if "
74 // "none exists.\n");
75 printf("-q Stop tracing.\n");
76 printf("-d Create trace, spawn a lttd daemon, start tracing.\n");
d24c12e7 77 printf(" (optionally, you can set LTT_DAEMON\n");
741f0397 78 printf(" env. var.)\n");
d24c12e7 79 printf("-f Stop tracing, dump flight recorder trace, destroy channels\n");
80 printf(" (for hybrid traces)\n");
2299770f 81 printf("-t Trace root path. (ex. /root/traces/example_trace)\n");
82 printf("-T Type of trace (ex. relay)\n");
bb01fdc6 83 printf("-l LTT channels root path. (ex. /mnt/debugfs/ltt)\n");
d24c12e7 84 printf("-Z Size of the low data rate subbuffers (will be rounded to next page size)\n");
85 printf("-X Number of low data rate subbuffers\n");
86 printf("-V Size of the medium data rate subbuffers (will be rounded to next page size)\n");
87 printf("-B Number of medium data rate subbuffers\n");
88 printf("-z Size of the high data rate subbuffers (will be rounded to next page size)\n");
89 printf("-x Number of high data rate subbuffers\n");
2299770f 90 printf("-a Append to trace\n");
91 printf("-N Number of lttd threads\n");
5adba60f 92 printf("\n");
93}
94
95
96/* parse_arguments
97 *
98 * Parses the command line arguments.
99 *
2baf08e5 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.
5adba60f 102 */
103int parse_arguments(int argc, char **argv)
104{
105 int ret = 0;
106 int argn = 1;
107
108 if(argc == 2) {
109 if(strcmp(argv[1], "-h") == 0) {
2baf08e5 110 return -1;
5adba60f 111 }
112 }
113
114 while(argn < argc) {
115
116 switch(argv[argn][0]) {
117 case '-':
118 switch(argv[argn][1]) {
119 case 'n':
120 if(argn+1 < argc) {
121 trace_name = argv[argn+1];
122 argn++;
123 } else {
8eab4866 124 printf("Specify a trace name after -n.\n");
5adba60f 125 printf("\n");
2baf08e5 126 ret = EINVAL;
5adba60f 127 }
128
129 break;
24331c3d 130 case 'b':
131 op = CTL_OP_CREATE_START;
cd39bb61 132 break;
5adba60f 133 case 'c':
134 op = CTL_OP_CREATE;
24331c3d 135 break;
bc0fcb31 136 case 'm':
5adba60f 137 if(argn+1 < argc) {
138 mode_name = argv[argn+1];
139 argn++;
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;
d24c12e7 144 else if(strcmp(mode_name, "hybrid") == 0)
145 mode = LTT_TRACE_HYBRID;
5adba60f 146 else {
147 printf("Invalid mode '%s'.\n", argv[argn]);
148 printf("\n");
2baf08e5 149 ret = EINVAL;
5adba60f 150 }
151 } else {
bc0fcb31 152 printf("Specify a mode after -m.\n");
5adba60f 153 printf("\n");
2baf08e5 154 ret = EINVAL;
5adba60f 155 }
156 break;
157 case 'r':
158 op = CTL_OP_DESTROY;
159 break;
b7f08766 160 case 'R':
161 op = CTL_OP_STOP_DESTROY;
162 break;
5adba60f 163 case 's':
164 op = CTL_OP_START;
165 break;
166 case 'q':
167 op = CTL_OP_STOP;
168 break;
d24c12e7 169 case 'Z':
170 if(argn+1 < argc) {
171 subbuf_size_low = (unsigned)atoi(argv[argn+1]);
172 argn++;
173 } else {
174 printf("Specify a number of low traffic subbuffers after -Z.\n");
175 printf("\n");
176 ret = EINVAL;
177 }
178 break;
179 case 'X':
180 if(argn+1 < argc) {
181 n_subbufs_low = (unsigned)atoi(argv[argn+1]);
182 argn++;
183 } else {
184 printf("Specify a low traffic subbuffer size after -X.\n");
185 printf("\n");
186 ret = EINVAL;
187 }
188 break;
189 case 'V':
190 if(argn+1 < argc) {
191 subbuf_size_med = (unsigned)atoi(argv[argn+1]);
192 argn++;
193 } else {
194 printf("Specify a number of medium traffic subbuffers after -V.\n");
195 printf("\n");
196 ret = EINVAL;
197 }
198 break;
199 case 'B':
200 if(argn+1 < argc) {
201 n_subbufs_med = (unsigned)atoi(argv[argn+1]);
202 argn++;
203 } else {
204 printf("Specify a medium traffic subbuffer size after -B.\n");
205 printf("\n");
206 ret = EINVAL;
207 }
208 break;
988614ed 209 case 'z':
210 if(argn+1 < argc) {
d24c12e7 211 subbuf_size_high = (unsigned)atoi(argv[argn+1]);
988614ed 212 argn++;
213 } else {
d24c12e7 214 printf("Specify a number of high traffic subbuffers after -z.\n");
988614ed 215 printf("\n");
2baf08e5 216 ret = EINVAL;
988614ed 217 }
218 break;
219 case 'x':
220 if(argn+1 < argc) {
d24c12e7 221 n_subbufs_high = (unsigned)atoi(argv[argn+1]);
988614ed 222 argn++;
223 } else {
d24c12e7 224 printf("Specify a high traffic subbuffer size after -x.\n");
988614ed 225 printf("\n");
2baf08e5 226 ret = EINVAL;
988614ed 227 }
228 break;
5adba60f 229 case 'd':
230 op = CTL_OP_DAEMON;
231 break;
d24c12e7 232 case 'f':
233 op = CTL_OP_DAEMON_HYBRID_FINISH;
234 break;
5adba60f 235 case 't':
236 if(argn+1 < argc) {
237 trace_root = argv[argn+1];
238 argn++;
239 } else {
988614ed 240 printf("Specify a trace root path after -t.\n");
5adba60f 241 printf("\n");
2baf08e5 242 ret = EINVAL;
5adba60f 243 }
244 break;
245 case 'l':
246 if(argn+1 < argc) {
247 channel_root = argv[argn+1];
248 argn++;
249 } else {
988614ed 250 printf("Specify a channel root path after -l.\n");
5adba60f 251 printf("\n");
2baf08e5 252 ret = EINVAL;
5adba60f 253 }
254 break;
24331c3d 255 case 'a':
256 append_trace = 1;
257 break;
258 case 'N':
22acb617 259 if(argn+1 < argc) {
260 num_threads = argv[argn+1];
261 argn++;
262 }
263 break;
313b3771 264 case 'T':
265 if(argn+1 < argc) {
266 trace_type = argv[argn+1];
267 argn++;
268 } else {
269 printf("Specify a trace type after -T.\n");
270 printf("\n");
271 ret = EINVAL;
272 }
273 break;
5adba60f 274 default:
275 printf("Invalid argument '%s'.\n", argv[argn]);
276 printf("\n");
2baf08e5 277 ret = EINVAL;
5adba60f 278 }
279 break;
280 default:
281 printf("Invalid argument '%s'.\n", argv[argn]);
282 printf("\n");
2baf08e5 283 ret = EINVAL;
5adba60f 284 }
285 argn++;
286 }
287
741f0397 288 if(trace_name == NULL) {
5adba60f 289 printf("Please specify a trace name.\n");
290 printf("\n");
2baf08e5 291 ret = EINVAL;
5adba60f 292 }
293
294 if(op == CTL_OP_NONE) {
295 printf("Please specify an operation.\n");
296 printf("\n");
2baf08e5 297 ret = EINVAL;
5adba60f 298 }
299
d24c12e7 300 if(op == CTL_OP_DAEMON || op == CTL_OP_DAEMON_HYBRID_FINISH) {
5adba60f 301 if(trace_root == NULL) {
302 printf("Please specify -t trace_root_path with the -d option.\n");
303 printf("\n");
2baf08e5 304 ret = EINVAL;
5adba60f 305 }
306 if(channel_root == NULL) {
307 printf("Please specify -l ltt_root_path with the -d option.\n");
308 printf("\n");
2baf08e5 309 ret = EINVAL;
5adba60f 310 }
311 }
312
313 return ret;
314}
315
316void show_info(void)
317{
e7480f75 318 printf("Linux Trace Toolkit Trace Control " VERSION"\n");
5adba60f 319 printf("\n");
24331c3d 320 if(trace_name != NULL) {
321 printf("Controlling trace : %s\n", trace_name);
322 printf("\n");
323 }
129fd24a 324}
325
5adba60f 326int lttctl_daemon(struct lttctl_handle *handle, char *trace_name)
327{
328 char channel_path[PATH_MAX] = "";
329 pid_t pid;
330 int ret;
331 char *lttd_path = getenv("LTT_DAEMON");
5adba60f 332
86a65fdb 333 if(lttd_path == NULL) lttd_path =
24331c3d 334 PACKAGE_BIN_DIR "/lttd";
5adba60f 335
336 strcat(channel_path, channel_root);
337 strcat(channel_path, "/");
338 strcat(channel_path, trace_name);
339
340
d24c12e7 341 ret = lttctl_create_trace(handle, trace_name, mode, trace_type,
342 subbuf_size_low, n_subbufs_low,
343 subbuf_size_med, n_subbufs_med,
344 subbuf_size_high, n_subbufs_high);
5adba60f 345 if(ret != 0) goto create_error;
346
5adba60f 347 pid = fork();
348
349 if(pid > 0) {
2299770f 350 int status = 0;
5adba60f 351 /* parent */
2299770f 352
24331c3d 353 ret = waitpid(pid, &status, 0);
354 if(ret == -1) {
355 ret = errno;
356 perror("Error in waitpid");
357 goto start_error;
358 }
359
360 ret = 0;
361 if(WIFEXITED(status))
362 ret = WEXITSTATUS(status);
363 if(ret) goto start_error;
5adba60f 364
5adba60f 365 printf("Creating supplementary trace files\n");
24331c3d 366 ret = create_eventdefs();
367 if(ret) goto start_error;
5adba60f 368
369 } else if(pid == 0) {
370 /* child */
24331c3d 371 int ret;
d24c12e7 372 if(mode != LTT_TRACE_HYBRID) {
373 if(append_trace)
374 ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c",
375 channel_path, "-d", "-a", "-N", num_threads, NULL);
376 else
377 ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c",
378 channel_path, "-d", "-N", num_threads, NULL);
379 } else {
380 if(append_trace)
381 ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c",
382 channel_path, "-d", "-a", "-N", num_threads, "-n", NULL);
383 else
384 ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c",
385 channel_path, "-d", "-N", num_threads, "-n", NULL);
386 }
5adba60f 387 if(ret) {
24331c3d 388 ret = errno;
5adba60f 389 perror("Error in executing the lttd daemon");
618fbcc1 390 exit(ret);
5adba60f 391 }
392 } else {
393 /* error */
394 perror("Error in forking for lttd daemon");
5adba60f 395 }
396
397 ret = lttctl_start(handle, trace_name);
398 if(ret != 0) goto start_error;
399
400 return 0;
401
402 /* error handling */
403start_error:
24331c3d 404 printf("Trace start error\n");
5adba60f 405 ret |= lttctl_destroy_trace(handle, trace_name);
406create_error:
407 return ret;
408}
409
d24c12e7 410
411
412
413int lttctl_daemon_hybrid_finish(struct lttctl_handle *handle, char *trace_name)
414{
415 char channel_path[PATH_MAX] = "";
416 pid_t pid;
417 int ret;
418 char *lttd_path = getenv("LTT_DAEMON");
419
420 if(lttd_path == NULL) lttd_path =
421 PACKAGE_BIN_DIR "/lttd";
422
423 strcat(channel_path, channel_root);
424 strcat(channel_path, "/");
425 strcat(channel_path, trace_name);
426
427
428 ret = lttctl_stop(handle, trace_name);
429 if(ret != 0) goto stop_error;
430
431 pid = fork();
432
433 if(pid > 0) {
434 int status = 0;
435 /* parent */
436
437 ret = waitpid(pid, &status, 0);
438 if(ret == -1) {
439 ret = errno;
440 perror("Error in waitpid");
441 goto destroy_error;
442 }
443
444 ret = 0;
445 if(WIFEXITED(status))
446 ret = WEXITSTATUS(status);
447 if(ret) goto destroy_error;
448
449 } else if(pid == 0) {
450 /* child */
451 int ret;
452 if(append_trace)
453 ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c",
454 channel_path, "-d", "-a", "-N", num_threads, "-f", NULL);
455 else
456 ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c",
457 channel_path, "-d", "-N", num_threads, "-f", NULL);
458 if(ret) {
459 ret = errno;
460 perror("Error in executing the lttd daemon");
461 exit(ret);
462 }
463 } else {
464 /* error */
465 perror("Error in forking for lttd daemon");
466 }
467
468 ret = lttctl_destroy_trace(handle, trace_name);
469 if(ret != 0) goto destroy_error;
470
471 return 0;
472
473 /* error handling */
474destroy_error:
475 printf("Hybrid trace destroy error\n");
476stop_error:
477 return ret;
478}
479
480
481
5adba60f 482int main(int argc, char ** argv)
483{
484 int ret;
485 struct lttctl_handle *handle;
486
487 ret = parse_arguments(argc, argv);
488
489 if(ret != 0) show_arguments();
2baf08e5 490 if(ret == EINVAL) return EINVAL;
491 if(ret == -1) return 0;
5adba60f 492
493 show_info();
494
495 handle = lttctl_create_handle();
496
497 if(handle == NULL) return -1;
498
499 switch(op) {
24331c3d 500 case CTL_OP_CREATE_START:
d24c12e7 501 ret = lttctl_create_trace(handle, trace_name, mode, trace_type,
502 subbuf_size_low, n_subbufs_low,
503 subbuf_size_med, n_subbufs_med,
504 subbuf_size_high, n_subbufs_high);
24331c3d 505 if(!ret)
506 ret = lttctl_start(handle, trace_name);
507 break;
508 case CTL_OP_CREATE:
d24c12e7 509 ret = lttctl_create_trace(handle, trace_name, mode, trace_type,
510 subbuf_size_low, n_subbufs_low,
511 subbuf_size_med, n_subbufs_med,
512 subbuf_size_high, n_subbufs_high);
24331c3d 513 break;
5adba60f 514 case CTL_OP_DESTROY:
515 ret = lttctl_destroy_trace(handle, trace_name);
516 break;
b7f08766 517 case CTL_OP_STOP_DESTROY:
518 ret = lttctl_stop(handle, trace_name);
24331c3d 519 if(!ret)
520 ret = lttctl_destroy_trace(handle, trace_name);
b7f08766 521 break;
5adba60f 522 case CTL_OP_START:
523 ret = lttctl_start(handle, trace_name);
524 break;
525 case CTL_OP_STOP:
526 ret = lttctl_stop(handle, trace_name);
527 break;
528 case CTL_OP_DAEMON:
529 ret = lttctl_daemon(handle, trace_name);
530 break;
d24c12e7 531 case CTL_OP_DAEMON_HYBRID_FINISH:
532 ret = lttctl_daemon_hybrid_finish(handle, trace_name);
533 break;
5adba60f 534 case CTL_OP_NONE:
535 break;
536 }
537
538 ret |= lttctl_destroy_handle(handle);
539
540 return ret;
541}
This page took 0.059688 seconds and 4 git commands to generate.