X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Flttng-ctl.c;h=3b6423f6d3d7a4422727c4021587bf90346b4e56;hb=818ea544c74e89a68bcad32744a465bfdb648569;hp=7df8d6de7d2dae5f3da1c299fab160ec76d6808a;hpb=15e376636cbda79bdd8a71d0a1bec892d9997738;p=lttng-tools.git diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 7df8d6de7..3b6423f6d 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -287,6 +287,50 @@ end: return ret; } +static int check_enough_available_memory(size_t num_bytes_requested_per_cpu) +{ + int ret; + long num_cpu; + size_t best_mem_info; + size_t num_bytes_requested_total; + + /* + * Get the number of CPU currently online to compute the amount of + * memory needed to create a buffer for every CPU. + */ + num_cpu = sysconf(_SC_NPROCESSORS_ONLN); + if (num_cpu == -1) { + goto error; + } + + num_bytes_requested_total = num_bytes_requested_per_cpu * num_cpu; + + /* + * Try to get the `MemAvail` field of `/proc/meminfo`. This is the most + * reliable estimate we can get but it is only exposed by the kernel + * since 3.14. (See Linux kernel commit: + * 34e431b0ae398fc54ea69ff85ec700722c9da773) + */ + ret = utils_get_memory_available(&best_mem_info); + if (ret >= 0) { + goto success; + } + + /* + * As a backup plan, use `MemTotal` field of `/proc/meminfo`. This + * is a sanity check for obvious user error. + */ + ret = utils_get_memory_total(&best_mem_info); + if (ret >= 0) { + goto success; + } + +error: + return -1; +success: + return best_mem_info >= num_bytes_requested_total; +} + /* * Try connect to session daemon with sock_path. * @@ -1033,6 +1077,9 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, bool send_fd = false; unsigned int free_filter_expression = 0; struct filter_parser_ctx *ctx = NULL; + + memset(&send_buffer, 0, sizeof(send_buffer)); + /* * Cast as non-const since we may replace the filter expression * by a dynamically allocated string. Otherwise, the original @@ -1180,7 +1227,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, ret = lttng_userspace_probe_location_serialize( ev_ext->probe_location, &send_buffer, &fd_to_send); - if (ret) { + if (ret < 0) { goto mem_error; } @@ -1472,6 +1519,7 @@ int lttng_enable_channel(struct lttng_handle *handle, struct lttng_channel *in_chan) { struct lttcomm_session_msg lsm; + size_t total_buffer_size_needed_per_cpu = 0; /* NULL arguments are forbidden. No default values. */ if (handle == NULL || in_chan == NULL) { @@ -1507,6 +1555,16 @@ int lttng_enable_channel(struct lttng_handle *handle, memcpy(&lsm.u.channel.extended, extended, sizeof(*extended)); } + /* + * Verify that the amount of memory required to create the requested + * buffer is available on the system at the moment. + */ + total_buffer_size_needed_per_cpu = lsm.u.channel.chan.attr.num_subbuf * + lsm.u.channel.chan.attr.subbuf_size; + if (!check_enough_available_memory(total_buffer_size_needed_per_cpu)) { + return -LTTNG_ERR_NOMEM; + } + lsm.cmd_type = LTTNG_ENABLE_CHANNEL; lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); @@ -1726,6 +1784,26 @@ int lttng_create_session(const char *name, const char *url) return ret; } +/* + * Clear the session + */ +int lttng_clear_session(const char *session_name) +{ + struct lttcomm_session_msg lsm; + + if (session_name == NULL) { + return -LTTNG_ERR_INVALID; + } + + memset(&lsm, 0, sizeof(lsm)); + + lsm.cmd_type = LTTNG_CLEAR_SESSION; + lttng_ctl_copy_string(lsm.session.name, session_name, + sizeof(lsm.session.name)); + + return lttng_ctl_ask_sessiond(&lsm, NULL); +} + /* * Destroy session using name. * Returns size of returned session payload data or a negative error code. @@ -1932,9 +2010,8 @@ int lttng_list_events(struct lttng_handle *handle, size_t cmd_header_len; uint32_t nb_events, i; void *comm_ext_at; - void *listing_at; char *reception_buffer = NULL; - char *listing = NULL; + struct lttng_dynamic_buffer listing; size_t storage_req; /* Safety check. An handle and channel name are mandatory */ @@ -1957,6 +2034,11 @@ int lttng_list_events(struct lttng_handle *handle, goto end; } + if (!cmd_header) { + ret = -LTTNG_ERR_UNK; + goto end; + } + /* Set number of events and free command header */ nb_events = cmd_header->nb_events; if (nb_events > INT_MAX) { @@ -1970,12 +2052,12 @@ int lttng_list_events(struct lttng_handle *handle, * The buffer that is returned must contain a "flat" version of * the events that are returned. In other words, all pointers * within an lttng_event must point to a location within the returned - * buffer so that the user may free by simply calling free() on the - * returned buffer. This is needed in order to maintain API + * buffer so that the user may free everything by simply calling free() + * on the returned buffer. This is needed in order to maintain API * compatibility. * - * A first pass is performed to figure the size of the buffer that - * must be returned. A second pass is then performed to setup + * A first pass is performed to compute the size of the buffer that + * must be allocated. A second pass is then performed to setup * the returned events so that their members always point within the * buffer. * @@ -1995,66 +2077,170 @@ int lttng_list_events(struct lttng_handle *handle, for (i = 0; i < nb_events; i++) { struct lttcomm_event_extended_header *ext_comm = (struct lttcomm_event_extended_header *) comm_ext_at; + int probe_storage_req = 0; comm_ext_at += sizeof(*ext_comm); comm_ext_at += ext_comm->filter_len; comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; + if (ext_comm->userspace_probe_location_len) { + struct lttng_userspace_probe_location *probe_location = NULL; + struct lttng_buffer_view probe_location_view; + + probe_location_view = lttng_buffer_view_init( + comm_ext_at, 0, + ext_comm->userspace_probe_location_len); + + /* + * Create a temporary userspace probe location to + * determine the size needed by a "flattened" version + * of that same probe location. + */ + ret = lttng_userspace_probe_location_create_from_buffer( + &probe_location_view, &probe_location); + if (ret < 0) { + ret = -LTTNG_ERR_PROBE_LOCATION_INVAL; + goto end; + } + + ret = lttng_userspace_probe_location_flatten( + probe_location, NULL); + lttng_userspace_probe_location_destroy(probe_location); + if (ret < 0) { + ret = -LTTNG_ERR_PROBE_LOCATION_INVAL; + goto end; + } + + probe_storage_req = ret; + comm_ext_at += ext_comm->userspace_probe_location_len; + } + storage_req += sizeof(struct lttng_event_extended); - /* TODO: missing size of flat userspace probe. */ storage_req += ext_comm->filter_len; storage_req += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; - storage_req += storage_req % 8; + /* Padding to ensure the flat probe is aligned. */ + storage_req = ALIGN_TO(storage_req, sizeof(uint64_t)); + storage_req += probe_storage_req; } - listing = zmalloc(storage_req); - if (!listing) { + lttng_dynamic_buffer_init(&listing); + /* + * We must ensure that "listing" is never resized so as to preserve + * the validity of the flattened objects. + */ + ret = lttng_dynamic_buffer_set_capacity(&listing, storage_req); + if (ret) { + ret = -LTTNG_ERR_NOMEM; goto end; } - memcpy(listing, reception_buffer, - nb_events * sizeof(struct lttng_event)); + + ret = lttng_dynamic_buffer_append(&listing, reception_buffer, + nb_events * sizeof(struct lttng_event)); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto free_dynamic_buffer; + } comm_ext_at = reception_buffer + - (nb_events * sizeof(struct lttng_event)); - listing_at = listing + - (nb_events * sizeof(struct lttng_event)); + (nb_events * sizeof(struct lttng_event)); for (i = 0; i < nb_events; i++) { struct lttng_event *event = (struct lttng_event *) - (listing + (sizeof(struct lttng_event) * i)); + (listing.data + (sizeof(struct lttng_event) * i)); struct lttcomm_event_extended_header *ext_comm = (struct lttcomm_event_extended_header *) comm_ext_at; struct lttng_event_extended *event_extended = - (struct lttng_event_extended *) listing_at; + (struct lttng_event_extended *) + (listing.data + listing.size); + /* Insert struct lttng_event_extended. */ + ret = lttng_dynamic_buffer_set_size(&listing, + listing.size + sizeof(*event_extended)); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto free_dynamic_buffer; + } event->extended.ptr = event_extended; - listing_at += sizeof(*event_extended); + comm_ext_at += sizeof(*ext_comm); - /* Copy filter expression. */ - memcpy(listing_at, comm_ext_at, ext_comm->filter_len); - event_extended->filter_expression = listing_at; - comm_ext_at += ext_comm->filter_len; - listing_at += ext_comm->filter_len; + /* Insert filter expression. */ + if (ext_comm->filter_len) { + event_extended->filter_expression = listing.data + + listing.size; + ret = lttng_dynamic_buffer_append(&listing, comm_ext_at, + ext_comm->filter_len); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto free_dynamic_buffer; + } + comm_ext_at += ext_comm->filter_len; + } + + /* Insert exclusions. */ + if (ext_comm->nb_exclusions) { + event_extended->exclusions.count = + ext_comm->nb_exclusions; + event_extended->exclusions.strings = + listing.data + listing.size; + + ret = lttng_dynamic_buffer_append(&listing, + comm_ext_at, + ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto free_dynamic_buffer; + } + comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; + } + + /* Insert padding to align to 64-bits. */ + ret = lttng_dynamic_buffer_set_size(&listing, + ALIGN_TO(listing.size, sizeof(uint64_t))); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto free_dynamic_buffer; + } + + /* Insert flattened userspace probe location. */ + if (ext_comm->userspace_probe_location_len) { + struct lttng_userspace_probe_location *probe_location = NULL; + struct lttng_buffer_view probe_location_view; + + probe_location_view = lttng_buffer_view_init( + comm_ext_at, 0, + ext_comm->userspace_probe_location_len); + + ret = lttng_userspace_probe_location_create_from_buffer( + &probe_location_view, &probe_location); + if (ret < 0) { + ret = -LTTNG_ERR_PROBE_LOCATION_INVAL; + goto free_dynamic_buffer; + } - /* Copy exclusions. */ - event_extended->exclusions.count = ext_comm->nb_exclusions; - event_extended->exclusions.strings = listing_at; - memcpy(listing_at, comm_ext_at, - ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN); - listing_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; - comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; + event_extended->probe_location = (struct lttng_userspace_probe_location *) + (listing.data + listing.size); + ret = lttng_userspace_probe_location_flatten( + probe_location, &listing); + lttng_userspace_probe_location_destroy(probe_location); + if (ret < 0) { + ret = -LTTNG_ERR_PROBE_LOCATION_INVAL; + goto free_dynamic_buffer; + } - listing_at += ((uintptr_t) listing_at) % 8; + comm_ext_at += ext_comm->userspace_probe_location_len; + } } - *events = (struct lttng_event *) listing; - listing = NULL; + /* Don't reset listing buffer as we return its content. */ + *events = (struct lttng_event *) listing.data; + lttng_dynamic_buffer_init(&listing); ret = (int) nb_events; +free_dynamic_buffer: + lttng_dynamic_buffer_reset(&listing); end: free(cmd_header); free(reception_buffer); - free(listing); return ret; } @@ -2616,7 +2802,7 @@ int lttng_list_tracker_pids(struct lttng_handle *handle, int enabled = 1; struct lttcomm_session_msg lsm; size_t nr_pids; - int32_t *pids; + int32_t *pids = NULL; if (handle == NULL) { return -LTTNG_ERR_INVALID; @@ -2633,6 +2819,9 @@ int lttng_list_tracker_pids(struct lttng_handle *handle, return ret; } nr_pids = ret / sizeof(int32_t); + if (nr_pids > 0 && !pids) { + return -LTTNG_ERR_UNK; + } if (nr_pids == 1 && pids[0] == -1) { free(pids); pids = NULL; @@ -2779,50 +2968,6 @@ end: return ret; } -int lttng_session_get_current_archive_location(const char *session_name, - char **chunk_path) -{ - struct lttcomm_session_msg lsm; - struct lttng_session_get_current_output_return *output_return = NULL; - int ret; - size_t path_len; - - memset(&lsm, 0, sizeof(lsm)); - lsm.cmd_type = LTTNG_SESSION_GET_CURRENT_OUTPUT; - ret = lttng_strncpy(lsm.session.name, session_name, - sizeof(lsm.session.name)); - if (ret) { - ret = -LTTNG_ERR_INVALID; - goto end; - } - - ret = lttng_ctl_ask_sessiond(&lsm, (void **) &output_return); - if (ret < 0) { - ret = -1; - goto end; - } - - path_len = lttng_strnlen(output_return->path, - sizeof(output_return->path)); - if (path_len == 0 || path_len == sizeof(output_return->path)) { - ret = -LTTNG_ERR_NO_SESSION_OUTPUT; - goto end; - } - - *chunk_path = zmalloc(path_len + 1); - if (!*chunk_path) { - ret = -1; - goto end; - } - memcpy(*chunk_path, output_return->path, path_len); - - ret = 0; - -end: - free(output_return); - return ret; -} - /* * lib constructor. */