X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fkernel.c;h=c5fd30b7ead925f106cfe4d3c1164c6bc21fd5c8;hp=b79503b7d0185fd90b076c705f54ae6b90b8b3c2;hb=2d97a0067600335f07eecb2c1d9ba68fc164583e;hpb=7d268848fe44e591c53c8dfce796c6503c4539e8 diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index b79503b7d..c5fd30b7e 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -134,6 +134,26 @@ int kernel_create_session(struct ltt_session *session) DBG("Kernel session created (fd: %d)", lks->fd); + /* + * This is necessary since the creation time is present in the session + * name when it is generated. + */ + if (session->has_auto_generated_name) { + ret = kernctl_session_set_name(lks->fd, DEFAULT_SESSION_NAME); + } else { + ret = kernctl_session_set_name(lks->fd, session->name); + } + if (ret) { + WARN("Could not set kernel session name for session %" PRIu64 " name: %s", + session->id, session->name); + } + + ret = kernctl_session_set_creation_time(lks->fd, session->creation_time); + if (ret) { + WARN("Could not set kernel session creation time for session %" PRIu64 " name: %s", + session->id, session->name); + } + return 0; error: @@ -659,120 +679,277 @@ error: return ret; } +static struct lttng_tracker_list *get_id_tracker_list( + struct ltt_kernel_session *session, + enum lttng_tracker_type tracker_type) +{ + switch (tracker_type) { + case LTTNG_TRACKER_PID: + return session->tracker_list_pid; + case LTTNG_TRACKER_VPID: + return session->tracker_list_vpid; + case LTTNG_TRACKER_UID: + return session->tracker_list_uid; + case LTTNG_TRACKER_VUID: + return session->tracker_list_vuid; + case LTTNG_TRACKER_GID: + return session->tracker_list_gid; + case LTTNG_TRACKER_VGID: + return session->tracker_list_vgid; + default: + return NULL; + } +} -int kernel_track_pid(struct ltt_kernel_session *session, int pid) +int kernel_track_id(enum lttng_tracker_type tracker_type, + struct ltt_kernel_session *session, + const struct lttng_tracker_id *id) { - int ret; + int ret, value; + struct lttng_tracker_list *tracker_list; + struct lttng_tracker_id **saved_ids; + ssize_t saved_ids_count; - DBG("Kernel track PID %d for session id %" PRIu64 ".", - pid, session->id); - ret = kernctl_track_pid(session->fd, pid); - if (!ret) { - return LTTNG_OK; + ret = lttng_tracker_id_lookup_string(tracker_type, id, &value); + if (ret != LTTNG_OK) { + return ret; } - switch (-ret) { - case EINVAL: + + tracker_list = get_id_tracker_list(session, tracker_type); + if (!tracker_list) { return LTTNG_ERR_INVALID; - case ENOMEM: - return LTTNG_ERR_NOMEM; - case EEXIST: - return LTTNG_ERR_PID_TRACKED; - default: - return LTTNG_ERR_UNK; } -} -int kernel_untrack_pid(struct ltt_kernel_session *session, int pid) -{ - int ret; + /* Save list for restore on error. */ + saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids); + if (saved_ids_count < 0) { + return LTTNG_ERR_INVALID; + } - DBG("Kernel untrack PID %d for session id %" PRIu64 ".", - pid, session->id); - ret = kernctl_untrack_pid(session->fd, pid); - if (!ret) { - return LTTNG_OK; + /* Add to list. */ + ret = lttng_tracker_list_add(tracker_list, id); + if (ret != LTTNG_OK) { + goto end; } + + switch (tracker_type) { + case LTTNG_TRACKER_PID: + DBG("Kernel track PID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_track_pid(session->fd, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_VPID: + DBG("Kernel track VPID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VPID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_UID: + DBG("Kernel track UID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_track_id(session->fd, LTTNG_TRACKER_UID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_GID: + DBG("Kernel track GID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_track_id(session->fd, LTTNG_TRACKER_GID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_VUID: + DBG("Kernel track VUID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VUID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_VGID: + DBG("Kernel track VGID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VGID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + default: + ret = -EINVAL; + break; + } + + /* Error handling. */ switch (-ret) { case EINVAL: - return LTTNG_ERR_INVALID; + ret = LTTNG_ERR_INVALID; + break; case ENOMEM: - return LTTNG_ERR_NOMEM; - case ENOENT: - return LTTNG_ERR_PID_NOT_TRACKED; + ret = LTTNG_ERR_NOMEM; + break; + case EEXIST: + ret = LTTNG_ERR_ID_TRACKED; + break; default: - return LTTNG_ERR_UNK; + ret = LTTNG_ERR_UNK; + break; } + + if (lttng_tracker_id_set_list(tracker_list, saved_ids, + saved_ids_count) != LTTNG_OK) { + ERR("Error on tracker add error handling.\n"); + } +end: + lttng_tracker_ids_destroy(saved_ids, saved_ids_count); + free(saved_ids); + return ret; } -ssize_t kernel_list_tracker_pids(struct ltt_kernel_session *session, - int **_pids) +int kernel_untrack_id(enum lttng_tracker_type tracker_type, + struct ltt_kernel_session *session, + const struct lttng_tracker_id *id) { - int fd, ret; - int pid; - ssize_t nbmem, count = 0; - FILE *fp; - int *pids; + int ret, value; + struct lttng_tracker_list *tracker_list; + struct lttng_tracker_id **saved_ids; + ssize_t saved_ids_count; - fd = kernctl_list_tracker_pids(session->fd); - if (fd < 0) { - PERROR("kernel tracker pids list"); - goto error; + ret = lttng_tracker_id_lookup_string(tracker_type, id, &value); + if (ret != LTTNG_OK) { + return ret; } - fp = fdopen(fd, "r"); - if (fp == NULL) { - PERROR("kernel tracker pids list fdopen"); - goto error_fp; + tracker_list = get_id_tracker_list(session, tracker_type); + if (!tracker_list) { + return LTTNG_ERR_INVALID; } - - nbmem = KERNEL_TRACKER_PIDS_INIT_LIST_SIZE; - pids = zmalloc(sizeof(*pids) * nbmem); - if (pids == NULL) { - PERROR("alloc list pids"); - count = -ENOMEM; + /* Save list for restore on error. */ + saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids); + if (saved_ids_count < 0) { + return LTTNG_ERR_INVALID; + } + /* Remove from list. */ + ret = lttng_tracker_list_remove(tracker_list, id); + if (ret != LTTNG_OK) { goto end; } - while (fscanf(fp, "process { pid = %u; };\n", &pid) == 1) { - if (count >= nbmem) { - int *new_pids; - size_t new_nbmem; - - new_nbmem = nbmem << 1; - DBG("Reallocating pids list from %zu to %zu entries", - nbmem, new_nbmem); - new_pids = realloc(pids, new_nbmem * sizeof(*new_pids)); - if (new_pids == NULL) { - PERROR("realloc list events"); - free(pids); - count = -ENOMEM; - goto end; - } - /* Zero the new memory */ - memset(new_pids + nbmem, 0, - (new_nbmem - nbmem) * sizeof(*new_pids)); - nbmem = new_nbmem; - pids = new_pids; + switch (tracker_type) { + case LTTNG_TRACKER_PID: + DBG("Kernel untrack PID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_untrack_pid(session->fd, value); + if (!ret) { + ret = LTTNG_OK; + goto end; } - pids[count++] = pid; + break; + case LTTNG_TRACKER_VPID: + DBG("Kernel untrack VPID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_untrack_id( + session->fd, LTTNG_TRACKER_VPID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_UID: + DBG("Kernel untrack UID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_UID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_GID: + DBG("Kernel untrack GID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_GID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_VUID: + DBG("Kernel untrack VUID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_untrack_id( + session->fd, LTTNG_TRACKER_VUID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + case LTTNG_TRACKER_VGID: + DBG("Kernel untrack VGID %d for session id %" PRIu64 ".", value, + session->id); + ret = kernctl_untrack_id( + session->fd, LTTNG_TRACKER_VGID, value); + if (!ret) { + ret = LTTNG_OK; + goto end; + } + break; + default: + ret = -EINVAL; + break; } - *_pids = pids; - DBG("Kernel list tracker pids done (%zd pids)", count); -end: - ret = fclose(fp); /* closes both fp and fd */ - if (ret) { - PERROR("fclose"); + /* Error handling. */ + switch (-ret) { + case EINVAL: + ret = LTTNG_ERR_INVALID; + break; + case ENOMEM: + ret = LTTNG_ERR_NOMEM; + break; + case EEXIST: + ret = LTTNG_ERR_ID_TRACKED; + break; + default: + ret = LTTNG_ERR_UNK; + break; } - return count; -error_fp: - ret = close(fd); - if (ret) { - PERROR("close"); + if (lttng_tracker_id_set_list(tracker_list, saved_ids, + saved_ids_count) != LTTNG_OK) { + ERR("Error on tracker remove error handling.\n"); } -error: - return -1; +end: + lttng_tracker_ids_destroy(saved_ids, saved_ids_count); + free(saved_ids); + return ret; +} + +/* + * Called with session lock held. + */ +ssize_t kernel_list_tracker_ids(enum lttng_tracker_type tracker_type, + struct ltt_kernel_session *session, + struct lttng_tracker_id ***_ids) +{ + struct lttng_tracker_list *tracker_list; + + tracker_list = get_id_tracker_list(session, tracker_type); + if (!tracker_list) { + return -LTTNG_ERR_INVALID; + } + return lttng_tracker_id_get_list(tracker_list, _ids); } /* @@ -1269,6 +1446,7 @@ enum lttng_error_code kernel_snapshot_record( struct lttng_ht_iter iter; struct ltt_kernel_metadata *saved_metadata; char *trace_path = NULL; + size_t consumer_path_offset = 0; assert(ksess); assert(ksess->consumer); @@ -1295,7 +1473,7 @@ enum lttng_error_code kernel_snapshot_record( } trace_path = setup_channel_trace_path(ksess->consumer, - DEFAULT_KERNEL_TRACE_DIR); + DEFAULT_KERNEL_TRACE_DIR, &consumer_path_offset); if (!trace_path) { status = LTTNG_ERR_INVALID; goto error; @@ -1318,7 +1496,7 @@ enum lttng_error_code kernel_snapshot_record( cds_list_for_each_entry(chan, &ksess->channel_list.head, list) { status = consumer_snapshot_channel(socket, chan->key, output, 0, ksess->uid, ksess->gid, - trace_path, wait, + &trace_path[consumer_path_offset], wait, nb_packets_per_stream); if (status != LTTNG_OK) { (void) kernel_consumer_destroy_metadata(socket, @@ -1329,7 +1507,8 @@ enum lttng_error_code kernel_snapshot_record( /* Snapshot metadata, */ status = consumer_snapshot_channel(socket, ksess->metadata->key, output, - 1, ksess->uid, ksess->gid, trace_path, wait, 0); + 1, ksess->uid, ksess->gid, &trace_path[consumer_path_offset], + wait, 0); if (status != LTTNG_OK) { goto error_consumer; } @@ -1405,6 +1584,38 @@ error: return ret; } +/* + * Check for the support of the packet sequence number via abi version number. + * + * Return 1 on success, 0 when feature is not supported, negative value in case + * of errors. + */ +int kernel_supports_ring_buffer_packet_sequence_number(void) +{ + int ret = 0; // Not supported by default + struct lttng_kernel_tracer_abi_version abi; + + ret = kernctl_tracer_abi_version(kernel_tracer_fd, &abi); + if (ret < 0) { + ERR("Failed to retrieve lttng-modules ABI version"); + goto error; + } + + /* + * Packet sequence number was introduced in LTTng 2.8, + * lttng-modules ABI 2.1. + */ + if (abi.major >= 2 && abi.minor >= 1) { + /* Supported */ + ret = 1; + } else { + /* Not supported */ + ret = 0; + } +error: + return ret; +} + /* * Rotate a kernel session. * @@ -1594,3 +1805,83 @@ bool kernel_tracer_is_initialized(void) { return kernel_tracer_fd >= 0; } + +/* + * Clear a kernel session. + * + * Return LTTNG_OK on success or else an LTTng error code. + */ +enum lttng_error_code kernel_clear_session(struct ltt_session *session) +{ + int ret; + enum lttng_error_code status = LTTNG_OK; + struct consumer_socket *socket; + struct lttng_ht_iter iter; + struct ltt_kernel_session *ksess = session->kernel_session; + + assert(ksess); + assert(ksess->consumer); + + DBG("Clear kernel session %s (session %" PRIu64 ")", + session->name, session->id); + + rcu_read_lock(); + + if (ksess->active) { + ERR("Expecting inactive session %s (%" PRIu64 ")", session->name, session->id); + status = LTTNG_ERR_FATAL; + goto end; + } + + /* + * Note that this loop will end after one iteration given that there is + * only one kernel consumer. + */ + cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter, + socket, node.node) { + struct ltt_kernel_channel *chan; + + /* For each channel, ask the consumer to clear it. */ + cds_list_for_each_entry(chan, &ksess->channel_list.head, list) { + DBG("Clear kernel channel %" PRIu64 ", session %s", + chan->key, session->name); + ret = consumer_clear_channel(socket, chan->key); + if (ret < 0) { + goto error; + } + } + + if (!ksess->metadata) { + /* + * Nothing to do for the metadata. + * This is a snapshot session. + * The metadata is genererated on the fly. + */ + continue; + } + + /* + * Clear the metadata channel. + * Metadata channel is not cleared per se but we still need to + * perform a rotation operation on it behind the scene. + */ + ret = consumer_clear_channel(socket, ksess->metadata->key); + if (ret < 0) { + goto error; + } + } + + goto end; +error: + switch (-ret) { + case LTTCOMM_CONSUMERD_RELAYD_CLEAR_DISALLOWED: + status = LTTNG_ERR_CLEAR_RELAY_DISALLOWED; + break; + default: + status = LTTNG_ERR_CLEAR_FAIL_CONSUMER; + break; + } +end: + rcu_read_unlock(); + return status; +}