From 33a2b85433875769e92ca44a680c46b9498f5174 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Wed, 1 Jun 2011 17:10:45 -0400 Subject: [PATCH] Core modification and listing kernel event support File descriptor sent to the kconsumerd are now sent one at a time. The problem was that there is a maximum packet size once the control buffer is used with recvmsg/sendmsg. This upper bound can be read and set at : /proc/sys/net/core/optmem_max. Also, the kconsumerd execlp is set to verbose at this time for debugging purpose. Introduce --list-events to list all kernel events with the -k option added. NOT supported for user-space at this point. Signed-off-by: David Goulet --- kconsumerd/kconsumerd.c | 94 ++++++++++++------------- liblttngctl/liblttngctl.c | 12 +++- liblttsessiondcomm/liblttsessiondcomm.h | 1 + ltt-sessiond/kernel-ctl.c | 1 + ltt-sessiond/main.c | 94 ++++++++++++++++++------- ltt-sessiond/trace.c | 7 ++ lttng/lttng.c | 18 +++-- lttng/options.c | 3 + lttng/options.h | 1 + 9 files changed, 150 insertions(+), 81 deletions(-) diff --git a/kconsumerd/kconsumerd.c b/kconsumerd/kconsumerd.c index 5a1fe89a7..fd0b0b80c 100644 --- a/kconsumerd/kconsumerd.c +++ b/kconsumerd/kconsumerd.c @@ -418,82 +418,78 @@ static int consumerd_recv_fd(int sfd, int size, { struct msghdr msg; struct iovec iov[1]; - int ret, i, tmp2; + int ret = 0, i, tmp2; struct cmsghdr *cmsg; int nb_fd; - char tmp[CMSG_SPACE(size)]; - struct lttcomm_kconsumerd_msg *buf; + char recv_fd[CMSG_SPACE(sizeof(int))]; + struct lttcomm_kconsumerd_msg lkm; + /* the number of fds we are about to receive */ - nb_fd = size/sizeof(struct lttcomm_kconsumerd_msg); + nb_fd = size / sizeof(struct lttcomm_kconsumerd_msg); - buf = malloc(size); + for (i = 0; i < nb_fd; i++) { + memset(&msg, 0, sizeof(msg)); - memset(&msg, 0, sizeof(msg)); + /* Prepare to receive the structures */ + iov[0].iov_base = &lkm; + iov[0].iov_len = sizeof(lkm); + msg.msg_iov = iov; + msg.msg_iovlen = 1; - /* Prepare to receive the structures */ - iov[0].iov_base = buf; - iov[0].iov_len = size; - msg.msg_iov = iov; - msg.msg_iovlen = 1; + msg.msg_control = recv_fd; + msg.msg_controllen = sizeof(recv_fd); - msg.msg_control = tmp; - msg.msg_controllen = sizeof(tmp); + DBG("Waiting to receive fd"); + if ((ret = recvmsg(sfd, &msg, 0)) < 0) { + perror("recvmsg"); + continue; + } - DBG("Waiting to receive fds"); - if ((ret = recvmsg(sfd, &msg, 0)) < 0) { - perror("recvmsg"); - } - if (ret != size) { - ERR("Received only %d, expected %d", ret, size); - send_error(KCONSUMERD_ERROR_RECV_FD); - goto end; - } + if (ret != (size / nb_fd)) { + ERR("Received only %d, expected %d", ret, size); + send_error(KCONSUMERD_ERROR_RECV_FD); + goto end; + } - cmsg = CMSG_FIRSTHDR(&msg); - if (!cmsg) { - ERR("Invalid control message header"); - ret = -1; - send_error(KCONSUMERD_ERROR_RECV_FD); - goto end; - } + cmsg = CMSG_FIRSTHDR(&msg); + if (!cmsg) { + ERR("Invalid control message header"); + ret = -1; + send_error(KCONSUMERD_ERROR_RECV_FD); + goto end; + } - /* if we received fds */ - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - DBG("Receive : expecting %d fds", nb_fd); - for (i = 0; i < nb_fd; i++) { + /* if we received fds */ + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { switch (cmd_type) { case ADD_STREAM: - DBG("add_fd %s (%d)", buf[i].path_name, ((int *)CMSG_DATA(cmsg))[i]); - ret = add_fd(&buf[i], ((int *)CMSG_DATA(cmsg))[i]); + DBG("add_fd %s (%d)", lkm.path_name, (CMSG_DATA(cmsg)[0])); + ret = add_fd(&lkm, (CMSG_DATA(cmsg)[0])); if (ret < 0) { send_error(KCONSUMERD_OUTFD_ERROR); goto end; } break; case UPDATE_STREAM: - change_fd_state(buf[i].fd, buf[i].state); + change_fd_state(lkm.fd, lkm.state); break; default: break; } + /* flag to tell the polling thread to update its fd array */ + update_fd_array = 1; + /* signal the poll thread */ + tmp2 = write(poll_pipe[1], "4", 1); + } else { + ERR("Didn't received any fd"); + send_error(KCONSUMERD_ERROR_RECV_FD); + ret = -1; + goto end; } - /* flag to tell the polling thread to update its fd array */ - update_fd_array = 1; - /* signal the poll thread */ - tmp2 = write(poll_pipe[1], "4", 1); - } else { - ERR("Didn't received any fd"); - send_error(KCONSUMERD_ERROR_RECV_FD); - ret = -1; - goto end; } end: DBG("consumerd_recv_fd thread exiting"); - if (buf != NULL) { - free(buf); - buf = NULL; - } return ret; } diff --git a/liblttngctl/liblttngctl.c b/liblttngctl/liblttngctl.c index d8230c618..eb606166c 100644 --- a/liblttngctl/liblttngctl.c +++ b/liblttngctl/liblttngctl.c @@ -235,8 +235,16 @@ static int set_session_daemon_path(void) */ int lttng_kernel_enable_event(char *event_name) { - strncpy(lsm.u.event.event_name, event_name, NAME_MAX); - return ask_sessiond(KERNEL_ENABLE_EVENT, NULL); + int ret; + + if (event_name == NULL) { + ret = ask_sessiond(KERNEL_ENABLE_ALL_EVENT, NULL); + } else { + strncpy(lsm.u.event.event_name, event_name, NAME_MAX); + ret = ask_sessiond(KERNEL_ENABLE_EVENT, NULL); + } + + return ret; } /* diff --git a/liblttsessiondcomm/liblttsessiondcomm.h b/liblttsessiondcomm/liblttsessiondcomm.h index cb9e26dd8..195040822 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.h +++ b/liblttsessiondcomm/liblttsessiondcomm.h @@ -46,6 +46,7 @@ enum lttcomm_sessiond_command { KERNEL_CREATE_STREAM, KERNEL_DISABLE_EVENT, KERNEL_ENABLE_EVENT, + KERNEL_ENABLE_ALL_EVENT, KERNEL_LIST_EVENTS, KERNEL_OPEN_METADATA, KERNEL_START_TRACE, diff --git a/ltt-sessiond/kernel-ctl.c b/ltt-sessiond/kernel-ctl.c index f3fdc0e72..bf25de62f 100644 --- a/ltt-sessiond/kernel-ctl.c +++ b/ltt-sessiond/kernel-ctl.c @@ -123,6 +123,7 @@ int kernel_enable_event(struct ltt_kernel_session *session, char *name) cds_list_for_each_entry(chan, &session->channel_list.head, list) { ret = kernctl_create_event(chan->fd, event->event); if (ret < 0) { + ERR("Unable to enable event %s", name); goto error; } diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 97db535d1..93e6ca668 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -561,35 +561,17 @@ error: */ static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session) { - int ret, i = 0; - /* Plus one here for the metadata fd */ - size_t nb_fd = session->stream_count_global + 1; - int fds[nb_fd]; + int ret; + size_t nb_fd; struct ltt_kernel_stream *stream; struct ltt_kernel_channel *chan; struct lttcomm_kconsumerd_header lkh; - struct lttcomm_kconsumerd_msg buf[nb_fd]; - - /* Add metadata data */ - fds[i] = session->metadata_stream_fd; - buf[i].fd = fds[i]; - buf[i].state = ACTIVE_FD; - buf[i].max_sb_size = session->metadata->conf->subbuf_size; - strncpy(buf[i].path_name, session->metadata->pathname, PATH_MAX); + struct lttcomm_kconsumerd_msg lkm; - cds_list_for_each_entry(chan, &session->channel_list.head, list) { - cds_list_for_each_entry(stream, &chan->stream_list.head, list) { - i++; - fds[i] = stream->fd; - buf[i].fd = stream->fd; - buf[i].state = stream->state; - buf[i].max_sb_size = chan->channel->subbuf_size; - strncpy(buf[i].path_name, stream->pathname, PATH_MAX); - } - } + nb_fd = session->stream_count_global; /* Setup header */ - lkh.payload_size = nb_fd * sizeof(struct lttcomm_kconsumerd_msg); + lkh.payload_size = (nb_fd + 1) * sizeof(struct lttcomm_kconsumerd_msg); lkh.cmd_type = ADD_STREAM; DBG("Sending kconsumerd header"); @@ -600,14 +582,37 @@ static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session) goto error; } - DBG("Sending all fds to kconsumerd"); + DBG("Sending metadata stream fd"); - ret = lttcomm_send_fds_unix_sock(sock, buf, fds, nb_fd, lkh.payload_size); + /* Send metadata stream fd first */ + lkm.fd = session->metadata_stream_fd; + lkm.state = ACTIVE_FD; + lkm.max_sb_size = session->metadata->conf->subbuf_size; + strncpy(lkm.path_name, session->metadata->pathname, PATH_MAX); + + ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm)); if (ret < 0) { - perror("send kconsumerd fds"); + perror("send kconsumerd fd"); goto error; } + cds_list_for_each_entry(chan, &session->channel_list.head, list) { + cds_list_for_each_entry(stream, &chan->stream_list.head, list) { + lkm.fd = stream->fd; + lkm.state = stream->state; + lkm.max_sb_size = chan->channel->subbuf_size; + strncpy(lkm.path_name, stream->pathname, PATH_MAX); + + DBG("Sending fd %d to kconsumerd", lkm.fd); + + ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm)); + if (ret < 0) { + perror("send kconsumerd fd"); + goto error; + } + } + } + DBG("Kconsumerd fds sent"); return 0; @@ -767,6 +772,43 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = LTTCOMM_OK; break; } + case KERNEL_ENABLE_ALL_EVENT: + { + int pos, size; + char *event_list, *event, *ptr; + + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + DBG("Enabling all kernel event"); + + size = kernel_list_events(kernel_tracer_fd, &event_list); + if (size < 0) { + ret = LTTCOMM_KERN_LIST_FAIL; + goto error; + } + + ptr = event_list; + while ((size = sscanf(ptr, "event { name = %m[^;]; };%n\n", &event, &pos)) == 1) { + /* Enable each single event */ + ret = kernel_enable_event(cmd_ctx->session->kernel_session, event); + if (ret < 0) { + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; + } + /* Move pointer to the next line */ + ptr += pos + 1; + free(event); + } + + free(event_list); + + ret = LTTCOMM_OK; + break; + } case KERNEL_LIST_EVENTS: { char *event_list; diff --git a/ltt-sessiond/trace.c b/ltt-sessiond/trace.c index 5214cddfc..5cd053652 100644 --- a/ltt-sessiond/trace.c +++ b/ltt-sessiond/trace.c @@ -23,6 +23,7 @@ #include #include +#include "lttngerr.h" #include "ltt-sessiond.h" #include "trace.h" @@ -211,6 +212,7 @@ error: void trace_destroy_kernel_stream(struct ltt_kernel_stream *stream) { + DBG("[trace] Closing stream fd %d", stream->fd); /* Close kernel fd */ close(stream->fd); free(stream->pathname); @@ -222,6 +224,7 @@ void trace_destroy_kernel_stream(struct ltt_kernel_stream *stream) void trace_destroy_kernel_event(struct ltt_kernel_event *event) { + DBG("[trace] Closing event fd %d", event->fd); /* Close kernel fd */ close(event->fd); /* Free attributes */ @@ -237,6 +240,7 @@ void trace_destroy_kernel_channel(struct ltt_kernel_channel *channel) struct ltt_kernel_stream *stream; struct ltt_kernel_event *event; + DBG("[trace] Closing channel fd %d", channel->fd); /* Close kernel fd */ close(channel->fd); free(channel->pathname); @@ -260,6 +264,7 @@ void trace_destroy_kernel_channel(struct ltt_kernel_channel *channel) void trace_destroy_kernel_metadata(struct ltt_kernel_metadata *metadata) { + DBG("[trace] Closing metadata fd %d", metadata->fd); /* Close kernel fd */ close(metadata->fd); /* Free attributes */ @@ -272,8 +277,10 @@ void trace_destroy_kernel_session(struct ltt_kernel_session *session) { struct ltt_kernel_channel *channel; + DBG("[trace] Closing session fd %d", session->fd); /* Close kernel fds */ close(session->fd); + DBG("[trace] Closing metadata stream fd %d", session->metadata_stream_fd); close(session->metadata_stream_fd); trace_destroy_kernel_metadata(session->metadata); diff --git a/lttng/lttng.c b/lttng/lttng.c index 9c34d2c62..b523960c3 100644 --- a/lttng/lttng.c +++ b/lttng/lttng.c @@ -143,13 +143,11 @@ static int process_client_opt(void) } } - if (opt_event_list != NULL) { + if (opt_event_list != NULL || opt_enable_all_event) { ret = process_opt_kernel_event(); if (ret < 0) { goto end; } - } else { - // Enable all events } if (auto_trace || opt_start_trace) { @@ -308,6 +306,17 @@ static int process_opt_kernel_event(void) int ret; char *event_name; + if (opt_enable_all_event) { + ret = lttng_kernel_enable_event(NULL); + if (ret < 0) { + ERR("%s", lttng_get_readable_code(ret)); + } else { + MSG("All kernel event enabled"); + } + + goto end; + } + event_name = strtok(opt_event_list, ","); while (event_name != NULL) { DBG("Enabling kernel event %s", event_name); @@ -321,6 +330,7 @@ static int process_opt_kernel_event(void) event_name = strtok(NULL, ","); } +end: return 0; } @@ -621,7 +631,7 @@ static int validate_options(void) } /* If start trace, auto start tracing */ - if (opt_start_trace || opt_event_list != NULL) { + if (opt_start_trace || opt_event_list != NULL || opt_enable_all_event) { DBG("Requesting auto tracing"); auto_trace = 1; } diff --git a/lttng/options.c b/lttng/options.c index fe7e400f8..a24de7189 100644 --- a/lttng/options.c +++ b/lttng/options.c @@ -42,6 +42,7 @@ int opt_create_trace; int opt_start_trace; int opt_stop_trace; int opt_enable_event; +int opt_enable_all_event; int opt_disable_event; int opt_kern_create_channel; pid_t opt_trace_pid; @@ -66,6 +67,7 @@ static struct poptOption long_options[] = { {"destroy-session", 'd', POPT_ARG_STRING, 0, OPT_DESTROY_SESSION, 0, 0}, {"disable-event", 0, POPT_ARG_STRING, 0, OPT_DISABLE_EVENT, 0, 0}, {"enable-event", 'e', POPT_ARG_STRING, 0, OPT_ENABLE_EVENT, 0, 0}, + {"enable-all-event",'a', POPT_ARG_VAL, &opt_enable_all_event, 1, 0, 0}, {"group", 0, POPT_ARG_STRING, &opt_tracing_group, 0, 0, 0}, {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0}, {"kernel", 'k', POPT_ARG_VAL, &opt_trace_kernel, 1, 0, 0}, @@ -116,6 +118,7 @@ static void usage(FILE *ofp) fprintf(ofp, " -k, --kernel Specify action on kernel tracer\n"); fprintf(ofp, " --list-events List all available tracing events\n"); fprintf(ofp, " -e, --enable-event LIST Enable tracing event (support marker and tracepoint)\n"); + fprintf(ofp, " -a, --enable-all-event Enable all tracing event\n"); fprintf(ofp, " --disable-event LIST Disable tracing event (support marker and tracepoint)\n"); fprintf(ofp, " -C, --create-trace Create a trace. Allocate and setup a trace\n"); fprintf(ofp, " -D, --destroy-trace [NAME] Destroy a trace. Use NAME to identify user-space trace\n"); diff --git a/lttng/options.h b/lttng/options.h index 45a76c77e..612043d0a 100644 --- a/lttng/options.h +++ b/lttng/options.h @@ -34,6 +34,7 @@ extern char *opt_event_list; extern char *opt_trace_name; extern int opt_destroy_trace; extern int opt_enable_event; +extern int opt_enable_all_event; extern int opt_disable_event; extern int opt_destroy_session; extern int opt_create_session; -- 2.34.1