X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust-ctl%2Fustctl.c;h=32fa2ebc33e92e054a7591435fa9aadffef47009;hb=457a6b5879a7dd8cdd1b5b22b20d028a59489159;hp=2d915260c8c522a2ac919b58a1222d48ec0c072c;hpb=b52190f262330b5ffbbdd49f1190114e68004069;p=lttng-ust.git diff --git a/liblttng-ust-ctl/ustctl.c b/liblttng-ust-ctl/ustctl.c index 2d915260..32fa2ebc 100644 --- a/liblttng-ust-ctl/ustctl.c +++ b/liblttng-ust-ctl/ustctl.c @@ -20,8 +20,11 @@ #include #include #include -#include -#include +#include +#include + +#include +#include #include "../libringbuffer/backend.h" #include "../libringbuffer/frontend.h" @@ -37,22 +40,44 @@ void init_object(struct lttng_ust_object_data *data) data->memory_map_size = 0; } -void ustctl_release_object(int sock, struct lttng_ust_object_data *data) +int ustctl_release_handle(int sock, int handle) { struct ustcomm_ust_msg lum; struct ustcomm_ust_reply lur; int ret; - if (data->shm_fd >= 0) - close(data->shm_fd); - if (data->wait_fd >= 0) - close(data->wait_fd); - memset(&lum, 0, sizeof(lum)); - lum.handle = data->handle; - lum.cmd = LTTNG_UST_RELEASE; - ret = ustcomm_send_app_cmd(sock, &lum, &lur); - assert(!ret); - free(data); + if (sock >= 0) { + memset(&lum, 0, sizeof(lum)); + lum.handle = handle; + lum.cmd = LTTNG_UST_RELEASE; + ret = ustcomm_send_app_cmd(sock, &lum, &lur); + if (ret < 0) { + return ret; + } + } + return 0; +} +/* + * If sock is negative, it means we don't have to notify the other side + * (e.g. application has already vanished). + */ +int ustctl_release_object(int sock, struct lttng_ust_object_data *data) +{ + int ret; + + if (data->shm_fd >= 0) { + ret = close(data->shm_fd); + if (ret < 0) { + return ret; + } + } + if (data->wait_fd >= 0) { + ret = close(data->wait_fd); + if (ret < 0) { + return ret; + } + } + return ustctl_release_handle(sock, data->handle); } /* @@ -110,7 +135,7 @@ int ustctl_open_metadata(int sock, int session_handle, struct ustcomm_ust_msg lum; struct ustcomm_ust_reply lur; struct lttng_ust_object_data *metadata_data; - int ret; + int ret, err = 0; metadata_data = malloc(sizeof(*metadata_data)); if (!metadata_data) @@ -141,18 +166,27 @@ int ustctl_open_metadata(int sock, int session_handle, /* get shm fd */ ret = ustcomm_recv_fd(sock); if (ret < 0) - goto error; - metadata_data->shm_fd = ret; + err = 1; + else + metadata_data->shm_fd = ret; + /* + * We need to get the second FD even if the first fails, because + * libust expects us to read the two FDs. + */ /* get wait fd */ ret = ustcomm_recv_fd(sock); if (ret < 0) + err = 1; + else + metadata_data->wait_fd = ret; + if (err) goto error; - metadata_data->wait_fd = ret; *_metadata_data = metadata_data; return 0; error: - ustctl_release_object(sock, metadata_data); + (void) ustctl_release_object(sock, metadata_data); + free(metadata_data); return -EINVAL; } @@ -163,7 +197,7 @@ int ustctl_create_channel(int sock, int session_handle, struct ustcomm_ust_msg lum; struct ustcomm_ust_reply lur; struct lttng_ust_object_data *channel_data; - int ret; + int ret, err = 0; channel_data = malloc(sizeof(*channel_data)); if (!channel_data) @@ -194,18 +228,27 @@ int ustctl_create_channel(int sock, int session_handle, /* get shm fd */ ret = ustcomm_recv_fd(sock); if (ret < 0) - goto error; - channel_data->shm_fd = ret; + err = 1; + else + channel_data->shm_fd = ret; + /* + * We need to get the second FD even if the first fails, because + * libust expects us to read the two FDs. + */ /* get wait fd */ ret = ustcomm_recv_fd(sock); if (ret < 0) + err = 1; + else + channel_data->wait_fd = ret; + if (err) goto error; - channel_data->wait_fd = ret; *_channel_data = channel_data; return 0; error: - ustctl_release_object(sock, channel_data); + (void) ustctl_release_object(sock, channel_data); + free(channel_data); return -EINVAL; } @@ -220,7 +263,7 @@ int ustctl_create_stream(int sock, struct lttng_ust_object_data *channel_data, struct ustcomm_ust_msg lum; struct ustcomm_ust_reply lur; struct lttng_ust_object_data *stream_data; - int ret, fd; + int ret, fd, err = 0; stream_data = malloc(sizeof(*stream_data)); if (!stream_data) @@ -245,18 +288,27 @@ int ustctl_create_stream(int sock, struct lttng_ust_object_data *channel_data, /* get shm fd */ fd = ustcomm_recv_fd(sock); if (fd < 0) - goto error; - stream_data->shm_fd = fd; + err = 1; + else + stream_data->shm_fd = fd; + /* + * We need to get the second FD even if the first fails, because + * libust expects us to read the two FDs. + */ /* get wait fd */ fd = ustcomm_recv_fd(sock); if (fd < 0) + err = 1; + else + stream_data->wait_fd = fd; + if (err) goto error; - stream_data->wait_fd = fd; *_stream_data = stream_data; return ret; error: - ustctl_release_object(sock, stream_data); + (void) ustctl_release_object(sock, stream_data); + free(stream_data); return -EINVAL; } @@ -279,6 +331,8 @@ int ustctl_create_event(int sock, struct lttng_ust_event *ev, strncpy(lum.u.event.name, ev->name, LTTNG_UST_SYM_NAME_LEN); lum.u.event.instrumentation = ev->instrumentation; + lum.u.event.loglevel_type = ev->loglevel_type; + lum.u.event.loglevel = ev->loglevel; ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) { free(event_data); @@ -368,10 +422,41 @@ int ustctl_stop_session(int sock, int handle) return ustctl_disable(sock, &obj); } - int ustctl_tracepoint_list(int sock) { - return -ENOSYS; /* not implemented */ + struct ustcomm_ust_msg lum; + struct ustcomm_ust_reply lur; + int ret, tp_list_handle; + + memset(&lum, 0, sizeof(lum)); + lum.handle = LTTNG_UST_ROOT_HANDLE; + lum.cmd = LTTNG_UST_TRACEPOINT_LIST; + ret = ustcomm_send_app_cmd(sock, &lum, &lur); + if (ret) + return ret; + tp_list_handle = lur.ret_val; + DBG("received tracepoint list handle %u", tp_list_handle); + return tp_list_handle; +} + +int ustctl_tracepoint_list_get(int sock, int tp_list_handle, + struct lttng_ust_tracepoint_iter *iter) +{ + struct ustcomm_ust_msg lum; + struct ustcomm_ust_reply lur; + int ret; + + memset(&lum, 0, sizeof(lum)); + lum.handle = tp_list_handle; + lum.cmd = LTTNG_UST_TRACEPOINT_LIST_GET; + ret = ustcomm_send_app_cmd(sock, &lum, &lur); + if (ret) + return ret; + DBG("received tracepoint list entry name %s loglevel %d", + lur.u.tracepoint.name, + lur.u.tracepoint.loglevel); + memcpy(iter, &lur.u.tracepoint, sizeof(*iter)); + return 0; } int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v) @@ -412,6 +497,22 @@ int ustctl_calibrate(int sock, struct lttng_ust_calibrate *calibrate) return -ENOSYS; } +int ustctl_sock_flush_buffer(int sock, struct lttng_ust_object_data *object) +{ + struct ustcomm_ust_msg lum; + struct ustcomm_ust_reply lur; + int ret; + + memset(&lum, 0, sizeof(lum)); + lum.handle = object->handle; + lum.cmd = LTTNG_UST_FLUSH_BUFFER; + ret = ustcomm_send_app_cmd(sock, &lum, &lur); + if (ret) + return ret; + DBG("flushed buffer handle %u", object->handle); + return 0; +} + /* Buffer operations */ /* Map channel shm into process memory */ @@ -420,6 +521,8 @@ struct lttng_ust_shm_handle *ustctl_map_channel(struct lttng_ust_object_data *ch struct lttng_ust_shm_handle *handle; struct channel *chan; size_t chan_size; + struct lttng_ust_lib_ring_buffer_config *config; + int ret; handle = channel_handle_create(chan_data->shm_fd, chan_data->wait_fd, @@ -429,12 +532,24 @@ struct lttng_ust_shm_handle *ustctl_map_channel(struct lttng_ust_object_data *ch return NULL; } /* - * Set to -1 because the lttng_ust_shm_handle destruction will take care - * of closing shm_fd and wait_fd. + * Set to -1, and then close the shm fd, and set the handle shm + * fd to -1 too. We don't need the shm fds after they have been + * mapped. + * The wait_fd is set to -1 in chan_data because it is now owned + * by the handle. */ chan_data->shm_fd = -1; chan_data->wait_fd = -1; + /* chan is object 0. This is hardcoded. */ + if (handle->table->objects[0].shm_fd >= 0) { + ret = close(handle->table->objects[0].shm_fd); + if (ret) { + perror("Error closing shm_fd"); + } + handle->table->objects[0].shm_fd = -1; + } + /* * TODO: add consistency checks to be resilient if the * application try to feed us with incoherent channel structure @@ -449,6 +564,38 @@ struct lttng_ust_shm_handle *ustctl_map_channel(struct lttng_ust_object_data *ch return NULL; } memcpy(handle->shadow_chan, chan, chan_size); + /* + * The callback pointers in the producer are invalid in the + * consumer. We need to look them up here. + */ + config = &handle->shadow_chan->backend.config; + switch (config->client_type) { + case LTTNG_CLIENT_METADATA: + memcpy(&config->cb, lttng_client_callbacks_metadata, + sizeof(config->cb)); + break; + case LTTNG_CLIENT_DISCARD: + memcpy(&config->cb, lttng_client_callbacks_discard, + sizeof(config->cb)); + break; + case LTTNG_CLIENT_OVERWRITE: + memcpy(&config->cb, lttng_client_callbacks_overwrite, + sizeof(config->cb)); + break; + default: + ERR("Unknown client type %d", config->client_type); + channel_destroy(chan, handle, 1); + return NULL; + } + /* Replace the object table pointer. */ + ret = munmap(handle->table->objects[0].memory_map, + handle->table->objects[0].memory_map_size); + if (ret) { + perror("munmap"); + assert(0); + } + handle->table->objects[0].memory_map = (char *) handle->shadow_chan; + handle->table->objects[0].is_shadow = 1; return handle; } @@ -486,12 +633,15 @@ void ustctl_unmap_channel(struct lttng_ust_shm_handle *handle) channel_destroy(chan, handle, 1); } +/* + * ustctl closes the shm_fd fds after mapping it. + */ struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_handle *handle, int cpu) { struct channel *chan = handle->shadow_chan; - int shm_fd, wait_fd; - uint64_t memory_map_size; + int *shm_fd, *wait_fd; + uint64_t *memory_map_size; struct lttng_ust_lib_ring_buffer *buf; int ret; @@ -502,6 +652,16 @@ struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_h ret = lib_ring_buffer_open_read(buf, handle, 1); if (ret) return NULL; + /* + * We can close shm_fd early, right after is has been mapped. + */ + if (*shm_fd >= 0) { + ret = close(*shm_fd); + if (ret) { + perror("Error closing shm_fd"); + } + *shm_fd = -1; + } return buf; } @@ -649,12 +809,11 @@ int ustctl_put_subbuf(struct lttng_ust_shm_handle *handle, return 0; } -int ustctl_flush_buffer(struct lttng_ust_shm_handle *handle, +void ustctl_flush_buffer(struct lttng_ust_shm_handle *handle, struct lttng_ust_lib_ring_buffer *buf, int producer_active) { lib_ring_buffer_switch_slow(buf, producer_active ? SWITCH_ACTIVE : SWITCH_FLUSH, handle); - return 0; }