X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=ltt-control%2Flttctl%2Flttctl.c;h=ce728928d7f9a0cced026b60fdd1a234466385df;hb=6623c1761b23430c7e2a02616c6587219be84a03;hp=11483c99a7002dd5834a76ffa45a6234824ad0b3;hpb=2727692a61acaf38e731277b6cc2a78a913d3e16;p=ltt-control.git diff --git a/ltt-control/lttctl/lttctl.c b/ltt-control/lttctl/lttctl.c index 11483c9..ce72892 100644 --- a/ltt-control/lttctl/lttctl.c +++ b/ltt-control/lttctl/lttctl.c @@ -28,21 +28,26 @@ #define BUF_SIZE 4096 enum trace_ctl_op { - CTL_OP_CREATE_START, + CTL_OP_CREATE_START, CTL_OP_CREATE, CTL_OP_DESTROY, - CTL_OP_STOP_DESTROY, + CTL_OP_STOP_DESTROY, CTL_OP_START, CTL_OP_STOP, CTL_OP_DAEMON, - CTL_OP_DESCRIPTION, + CTL_OP_DAEMON_HYBRID_FINISH, CTL_OP_NONE }; static char *trace_name = NULL; +static char *trace_type = "relay"; static char *mode_name = NULL; -static unsigned subbuf_size = 0; -static unsigned n_subbufs = 0; +static unsigned subbuf_size_low = 0; +static unsigned n_subbufs_low = 0; +static unsigned subbuf_size_med = 0; +static unsigned n_subbufs_med = 0; +static unsigned subbuf_size_high = 0; +static unsigned n_subbufs_high = 0; static unsigned append_trace = 0; static enum trace_mode mode = LTT_TRACE_NORMAL; static enum trace_ctl_op op = CTL_OP_NONE; @@ -50,15 +55,6 @@ static char *channel_root = NULL; static char *trace_root = NULL; static char *num_threads = "1"; -static int sigchld_received = 0; - -void sigchld_handler(int signo) -{ - printf("signal %d received\n", signo); - sigchld_received = 1; -} - - /* Args : * */ @@ -69,22 +65,28 @@ void show_arguments(void) printf("-n name Name of the trace.\n"); printf("-b Create trace channels and start tracing (no daemon).\n"); printf("-c Create trace channels.\n"); - printf("-m mode Normal or flight recorder mode.\n"); - printf(" Mode values : normal (default) or flight.\n"); + printf("-m mode Normal, flight recorder or hybrid mode.\n"); + printf(" Mode values : normal (default), flight or hybrid.\n"); printf("-r Destroy trace channels.\n"); printf("-R Stop tracing and destroy trace channels.\n"); printf("-s Start tracing.\n"); //printf(" Note : will automatically create a normal trace if " - // "none exists.\n"); + // "none exists.\n"); printf("-q Stop tracing.\n"); printf("-d Create trace, spawn a lttd daemon, start tracing.\n"); - printf(" (optionnaly, you can set LTT_DAEMON\n"); - printf(" and the LTT_FACILITIES env. vars.)\n"); + printf(" (optionally, you can set LTT_DAEMON\n"); + printf(" env. var.)\n"); + printf("-f Stop tracing, dump flight recorder trace, destroy channels\n"); + printf(" (for hybrid traces)\n"); printf("-t Trace root path. (ex. /root/traces/example_trace)\n"); - printf("-l LTT channels root path. (ex. /mnt/relayfs/ltt)\n"); - printf("-z Size of the subbuffers (will be rounded to next page size)\n"); - printf("-x Number of subbuffers\n"); - printf("-e Get XML facilities description\n"); + printf("-T Type of trace (ex. relay)\n"); + printf("-l LTT channels root path. (ex. /mnt/debugfs/ltt)\n"); + printf("-Z Size of the low data rate subbuffers (will be rounded to next page size)\n"); + printf("-X Number of low data rate subbuffers\n"); + printf("-V Size of the medium data rate subbuffers (will be rounded to next page size)\n"); + printf("-B Number of medium data rate subbuffers\n"); + printf("-z Size of the high data rate subbuffers (will be rounded to next page size)\n"); + printf("-x Number of high data rate subbuffers\n"); printf("-a Append to trace\n"); printf("-N Number of lttd threads\n"); printf("\n"); @@ -125,12 +127,12 @@ int parse_arguments(int argc, char **argv) } break; - case 'b': - op = CTL_OP_CREATE_START; + case 'b': + op = CTL_OP_CREATE_START; break; case 'c': op = CTL_OP_CREATE; - break; + break; case 'm': if(argn+1 < argc) { mode_name = argv[argn+1]; @@ -139,6 +141,8 @@ int parse_arguments(int argc, char **argv) mode = LTT_TRACE_NORMAL; else if(strcmp(mode_name, "flight") == 0) mode = LTT_TRACE_FLIGHT; + else if(strcmp(mode_name, "hybrid") == 0) + mode = LTT_TRACE_HYBRID; else { printf("Invalid mode '%s'.\n", argv[argn]); printf("\n"); @@ -162,22 +166,62 @@ int parse_arguments(int argc, char **argv) case 'q': op = CTL_OP_STOP; break; + case 'Z': + if(argn+1 < argc) { + subbuf_size_low = (unsigned)atoi(argv[argn+1]); + argn++; + } else { + printf("Specify a number of low traffic subbuffers after -Z.\n"); + printf("\n"); + ret = EINVAL; + } + break; + case 'X': + if(argn+1 < argc) { + n_subbufs_low = (unsigned)atoi(argv[argn+1]); + argn++; + } else { + printf("Specify a low traffic subbuffer size after -X.\n"); + printf("\n"); + ret = EINVAL; + } + break; + case 'V': + if(argn+1 < argc) { + subbuf_size_med = (unsigned)atoi(argv[argn+1]); + argn++; + } else { + printf("Specify a number of medium traffic subbuffers after -V.\n"); + printf("\n"); + ret = EINVAL; + } + break; + case 'B': + if(argn+1 < argc) { + n_subbufs_med = (unsigned)atoi(argv[argn+1]); + argn++; + } else { + printf("Specify a medium traffic subbuffer size after -B.\n"); + printf("\n"); + ret = EINVAL; + } + break; case 'z': if(argn+1 < argc) { - subbuf_size = (unsigned)atoi(argv[argn+1]); + subbuf_size_high = (unsigned)atoi(argv[argn+1]); argn++; } else { - printf("Specify a number of subbuffers after -z.\n"); + printf("Specify a number of high traffic subbuffers after -z.\n"); printf("\n"); ret = EINVAL; } break; case 'x': if(argn+1 < argc) { - n_subbufs = (unsigned)atoi(argv[argn+1]); + n_subbufs_high = (unsigned)atoi(argv[argn+1]); argn++; } else { - printf("Specify a subbuffer size after -x.\n"); + printf("Specify a high traffic subbuffer size after -x.\n"); printf("\n"); ret = EINVAL; } @@ -185,9 +229,9 @@ int parse_arguments(int argc, char **argv) case 'd': op = CTL_OP_DAEMON; break; - case 'e': - op = CTL_OP_DESCRIPTION; - break; + case 'f': + op = CTL_OP_DAEMON_HYBRID_FINISH; + break; case 't': if(argn+1 < argc) { trace_root = argv[argn+1]; @@ -208,15 +252,25 @@ int parse_arguments(int argc, char **argv) ret = EINVAL; } break; - case 'a': - append_trace = 1; - break; - case 'N': + case 'a': + append_trace = 1; + break; + case 'N': if(argn+1 < argc) { num_threads = argv[argn+1]; argn++; } break; + case 'T': + if(argn+1 < argc) { + trace_type = argv[argn+1]; + argn++; + } else { + printf("Specify a trace type after -T.\n"); + printf("\n"); + ret = EINVAL; + } + break; default: printf("Invalid argument '%s'.\n", argv[argn]); printf("\n"); @@ -231,7 +285,7 @@ int parse_arguments(int argc, char **argv) argn++; } - if(op != CTL_OP_DESCRIPTION && trace_name == NULL) { + if(trace_name == NULL) { printf("Please specify a trace name.\n"); printf("\n"); ret = EINVAL; @@ -243,7 +297,7 @@ int parse_arguments(int argc, char **argv) ret = EINVAL; } - if(op == CTL_OP_DAEMON) { + if(op == CTL_OP_DAEMON || op == CTL_OP_DAEMON_HYBRID_FINISH) { if(trace_root == NULL) { printf("Please specify -t trace_root_path with the -d option.\n"); printf("\n"); @@ -256,176 +310,82 @@ int parse_arguments(int argc, char **argv) } } - if(op == CTL_OP_DESCRIPTION) { - if(trace_root == NULL) { - printf("Please specify -t trace_root_path with the -e option.\n"); - printf("\n"); - ret = EINVAL; - } - } - return ret; } void show_info(void) { - printf("Linux Trace Toolkit Trace Control\n"); + printf("Linux Trace Toolkit Trace Control " VERSION"\n"); printf("\n"); - if(trace_name != NULL) { - printf("Controlling trace : %s\n", trace_name); - printf("\n"); - } -} - -int create_eventdefs(void) -{ - int ret = 0; - char eventdefs_path[PATH_MAX]; - char eventdefs_file[PATH_MAX]; - char facilities_file[PATH_MAX]; - char read_buf[BUF_SIZE]; - struct dirent *entry; - char *facilities_path = getenv("LTT_FACILITIES"); - if(facilities_path == NULL) facilities_path = - PACKAGE_DATA_DIR "/" PACKAGE "/facilities"; - - ret = mkdir(trace_root, S_IRWXU|S_IRWXG|S_IRWXO); - if(ret == -1 && errno != EEXIST) { - ret = errno; - perror("Cannot create trace_root directory"); - printf("trace_root is %s\n", trace_root); - goto error; - } - ret = 0; - - size_t trace_root_len = strlen(trace_root); - strncpy(eventdefs_path, trace_root, PATH_MAX); - strncat(eventdefs_path, "/eventdefs/", PATH_MAX - trace_root_len); - size_t eventdefs_path_len = strlen(eventdefs_path); - ret = mkdir(eventdefs_path, S_IRWXU|S_IRWXG|S_IRWXO); - if(ret == -1 && (!append_trace || errno != EEXIST)) { - ret = errno; - perror("Cannot create eventdefs directory"); - goto error; - } - ret = 0; - - DIR *facilities_dir = opendir(facilities_path); - - if(facilities_dir == NULL) { - perror("Cannot open facilities directory"); - ret = EEXIST; - goto error; - } - - while((entry = readdir(facilities_dir)) != NULL) { - if(entry->d_name[0] == '.') continue; - - printf("Appending facility file %s\n", entry->d_name); - strncpy(eventdefs_file, eventdefs_path, PATH_MAX); - strncat(eventdefs_file, entry->d_name, PATH_MAX - eventdefs_path_len); - /* Append to the file */ - FILE *dest = fopen(eventdefs_file, "a"); - if(!dest) { - perror("Cannot create eventdefs file"); - continue; - } - strncpy(facilities_file, facilities_path, PATH_MAX); - size_t facilities_dir_len = strlen(facilities_path); - strncat(facilities_file, "/", PATH_MAX - facilities_dir_len); - strncat(facilities_file, entry->d_name, PATH_MAX - facilities_dir_len-1); - FILE *src = fopen(facilities_file, "r"); - if(!src) { - ret = errno; - perror("Cannot open eventdefs file for reading"); - goto close_dest; - } - - do { - size_t read_size, write_size; - read_size = fread(read_buf, sizeof(char), BUF_SIZE, src); - if(ferror(src)) { - ret = errno; - perror("Cannot read eventdefs file"); - goto close_src; - } - write_size = fwrite(read_buf, sizeof(char), read_size, dest); - if(ferror(dest)) { - ret = errno; - perror("Cannot write eventdefs file"); - goto close_src; - } - } while(!feof(src)); - - /* Add spacing between facilities */ - fwrite("\n", 1, 1, dest); - -close_src: - fclose(src); -close_dest: - fclose(dest); - } - - closedir(facilities_dir); - -error: - return ret; - + if(trace_name != NULL) { + printf("Controlling trace : %s\n", trace_name); + printf("\n"); + } } - int lttctl_daemon(struct lttctl_handle *handle, char *trace_name) { char channel_path[PATH_MAX] = ""; pid_t pid; int ret; char *lttd_path = getenv("LTT_DAEMON"); - struct sigaction act; if(lttd_path == NULL) lttd_path = - PACKAGE_BIN_DIR "/lttd"; + PACKAGE_BIN_DIR "/lttd"; strcat(channel_path, channel_root); strcat(channel_path, "/"); strcat(channel_path, trace_name); - ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size, n_subbufs); + ret = lttctl_create_trace(handle, trace_name, mode, trace_type, + subbuf_size_low, n_subbufs_low, + subbuf_size_med, n_subbufs_med, + subbuf_size_high, n_subbufs_high); if(ret != 0) goto create_error; - act.sa_handler = sigchld_handler; - sigemptyset(&(act.sa_mask)); - sigaddset(&(act.sa_mask), SIGCHLD); - sigaction(SIGCHLD, &act, NULL); - pid = fork(); if(pid > 0) { - int status; + int status = 0; /* parent */ - while(!(sigchld_received)) pause(); + + ret = waitpid(pid, &status, 0); + if(ret == -1) { + ret = errno; + perror("Error in waitpid"); + goto start_error; + } - waitpid(pid, &status, 0); - ret = 0; - if(WIFEXITED(status)) - ret = WEXITSTATUS(status); - if(ret) goto start_error; + ret = 0; + if(WIFEXITED(status)) + ret = WEXITSTATUS(status); + if(ret) goto start_error; printf("Creating supplementary trace files\n"); - ret = create_eventdefs(); - if(ret) goto start_error; + ret = create_eventdefs(); + if(ret) goto start_error; } else if(pid == 0) { /* child */ - int ret; - if(append_trace) - ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", - channel_path, "-d", "-a", "-N", num_threads, NULL); - else - ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", - channel_path, "-d", "-N", num_threads, NULL); + int ret; + if(mode != LTT_TRACE_HYBRID) { + if(append_trace) + ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", + channel_path, "-d", "-a", "-N", num_threads, NULL); + else + ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", + channel_path, "-d", "-N", num_threads, NULL); + } else { + if(append_trace) + ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", + channel_path, "-d", "-a", "-N", num_threads, "-n", NULL); + else + ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", + channel_path, "-d", "-N", num_threads, "-n", NULL); + } if(ret) { - ret = errno; + ret = errno; perror("Error in executing the lttd daemon"); exit(ret); } @@ -441,12 +401,84 @@ int lttctl_daemon(struct lttctl_handle *handle, char *trace_name) /* error handling */ start_error: - printf("Trace start error\n"); + printf("Trace start error\n"); ret |= lttctl_destroy_trace(handle, trace_name); create_error: return ret; } + + + +int lttctl_daemon_hybrid_finish(struct lttctl_handle *handle, char *trace_name) +{ + char channel_path[PATH_MAX] = ""; + pid_t pid; + int ret; + char *lttd_path = getenv("LTT_DAEMON"); + + if(lttd_path == NULL) lttd_path = + PACKAGE_BIN_DIR "/lttd"; + + strcat(channel_path, channel_root); + strcat(channel_path, "/"); + strcat(channel_path, trace_name); + + + ret = lttctl_stop(handle, trace_name); + if(ret != 0) goto stop_error; + + pid = fork(); + + if(pid > 0) { + int status = 0; + /* parent */ + + ret = waitpid(pid, &status, 0); + if(ret == -1) { + ret = errno; + perror("Error in waitpid"); + goto destroy_error; + } + + ret = 0; + if(WIFEXITED(status)) + ret = WEXITSTATUS(status); + if(ret) goto destroy_error; + + } else if(pid == 0) { + /* child */ + int ret; + if(append_trace) + ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", + channel_path, "-d", "-a", "-N", num_threads, "-f", NULL); + else + ret = execlp(lttd_path, lttd_path, "-t", trace_root, "-c", + channel_path, "-d", "-N", num_threads, "-f", NULL); + if(ret) { + ret = errno; + perror("Error in executing the lttd daemon"); + exit(ret); + } + } else { + /* error */ + perror("Error in forking for lttd daemon"); + } + + ret = lttctl_destroy_trace(handle, trace_name); + if(ret != 0) goto destroy_error; + + return 0; + + /* error handling */ +destroy_error: + printf("Hybrid trace destroy error\n"); +stop_error: + return ret; +} + + + int main(int argc, char ** argv) { int ret; @@ -465,23 +497,27 @@ int main(int argc, char ** argv) if(handle == NULL) return -1; switch(op) { - case CTL_OP_CREATE_START: - ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size, - n_subbufs); - if(!ret) - ret = lttctl_start(handle, trace_name); - break; - case CTL_OP_CREATE: - ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size, - n_subbufs); - break; + case CTL_OP_CREATE_START: + ret = lttctl_create_trace(handle, trace_name, mode, trace_type, + subbuf_size_low, n_subbufs_low, + subbuf_size_med, n_subbufs_med, + subbuf_size_high, n_subbufs_high); + if(!ret) + ret = lttctl_start(handle, trace_name); + break; + case CTL_OP_CREATE: + ret = lttctl_create_trace(handle, trace_name, mode, trace_type, + subbuf_size_low, n_subbufs_low, + subbuf_size_med, n_subbufs_med, + subbuf_size_high, n_subbufs_high); + break; case CTL_OP_DESTROY: ret = lttctl_destroy_trace(handle, trace_name); break; case CTL_OP_STOP_DESTROY: ret = lttctl_stop(handle, trace_name); - if(!ret) - ret = lttctl_destroy_trace(handle, trace_name); + if(!ret) + ret = lttctl_destroy_trace(handle, trace_name); break; case CTL_OP_START: ret = lttctl_start(handle, trace_name); @@ -492,9 +528,9 @@ int main(int argc, char ** argv) case CTL_OP_DAEMON: ret = lttctl_daemon(handle, trace_name); break; - case CTL_OP_DESCRIPTION: - ret = create_eventdefs(); - break; + case CTL_OP_DAEMON_HYBRID_FINISH: + ret = lttctl_daemon_hybrid_finish(handle, trace_name); + break; case CTL_OP_NONE: break; }