From patchwork Wed Jan 19 08:25:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12717222 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1BA63C4167B for ; Wed, 19 Jan 2022 08:25:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352401AbiASIZb (ORCPT ); Wed, 19 Jan 2022 03:25:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45830 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352370AbiASIZa (ORCPT ); Wed, 19 Jan 2022 03:25:30 -0500 Received: from mail-ed1-x535.google.com (mail-ed1-x535.google.com [IPv6:2a00:1450:4864:20::535]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D7D40C061574 for ; Wed, 19 Jan 2022 00:25:29 -0800 (PST) Received: by mail-ed1-x535.google.com with SMTP id 30so7614393edv.3 for ; Wed, 19 Jan 2022 00:25:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BTn2Y51qmp2VvereioebFaCTG95UE8sdJogNHdDX/O4=; b=lpPg9au8Xpq+BHHaQnOdoLhm4Mmjnq1nKZmRDYb9Gx/u0lYLWSqthOIXMFKWtuq02L s2GZ9HA8uurGciUuRMgCY9PTmSbXNOVY5TSP1COD3+3KkUVHE4aEOG25EKp3CHwDjbJz XjfZK6MA25RWhidtfL3Dq3Y9K4dRxM1vYu2Apk2BOcYXhCXFjx5CSw1A1l7t0TGejOKb HFjL9btJC7B/e8Sh420uF22aC0pBITBXn2hBF2BxczUf9eepCXEmil0M6OgWBE03CojV mU/8YRY6yMsH0rFQ1RhJHVPy+bzgiv3V1A5do9eOxh4IdskMSBy8/2q3ufGBsYnJy3F9 csLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BTn2Y51qmp2VvereioebFaCTG95UE8sdJogNHdDX/O4=; b=SKpKmjrziEkQUUSxAKxiV3RF4bgEHC7ZdJ+QbOPpSWYiPpe1bF85Ec9LBMoXF79lBA is8VGjikpweJAApMBzLDNO5JX252BzOk8VZ1NFmgBgFmJTJin720oT8sGrOTJ2cKUMeh Vmy90F39iTIu6rRcfzg67WQxyXdBzrb/gk2t9HoYtkNRIAiWbmCVveNXhwPRsQKnWgNz LJ5tNdFqvSXMSwGFGD2pso2rFV76CEjrWJ8LHbf0LMCY+eOX01qhzxXWJcUF54HzJNeX bC3136G0iRE67NSU8IKkv/hp0lk1UdPTrcsx+gRHawWP97Kr/Si6Qyrfm5IFHRwtqclg nE6Q== X-Gm-Message-State: AOAM531/z9PM6bFxXaNPt1sAAKYCMMhFzmmSLHLP36LvCMm3UloCTdGS JCugsiVvBlt11OCxJhz+6lkdKbfpuA8= X-Google-Smtp-Source: ABdhPJxcbWylgxli69Jc9lw4tURQ9dl+S5CMWjqwMJ4pjd6YPGqkCbW6Z23IM0nd2P5PCIXZZiCtew== X-Received: by 2002:a17:907:d93:: with SMTP id go19mr5846000ejc.430.1642580728443; Wed, 19 Jan 2022 00:25:28 -0800 (PST) Received: from oberon.zico.biz.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id l1sm5011122ejf.44.2022.01.19.00.25.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Jan 2022 00:25:28 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v8 18/25] trace-cmd library: Read extended BUFFER option Date: Wed, 19 Jan 2022 10:25:00 +0200 Message-Id: <20220119082507.245600-19-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220119082507.245600-1-tz.stoyanov@gmail.com> References: <20220119082507.245600-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org The BUFFER option is extended in trace file version 7. It holds CPU metadata related to the recorded CPU traces. Also, there is a new BUFFER_TEXT option for describing the latency trace data. A new logic is implemented for these new options. In trace file version 7, the top buffer is saved as other buffers in the file, no special treatment. But saving the top buffer in the list of buffers in the input handler causes problems. It breaks the legacy logic of trace-cmd library users, which have special logic for trace buffers processing. That's why "top_buffer" member is added in the input handler structure, to hold the top buffer. Signed-off-by: Tzvetomir Stoyanov (VMware) --- lib/trace-cmd/trace-input.c | 145 +++++++++++++++++++++++++++++++----- 1 file changed, 128 insertions(+), 17 deletions(-) diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c index 2e10ebad..1eb92f2a 100644 --- a/lib/trace-cmd/trace-input.c +++ b/lib/trace-cmd/trace-input.c @@ -74,9 +74,19 @@ struct cpu_data { int pipe_fd; }; +struct cpu_file_data { + int cpu; + unsigned long long offset; + unsigned long long size; +}; + struct input_buffer_instance { char *name; size_t offset; + char *clock; + bool latency; + int cpus; + struct cpu_file_data *cpu_data; }; struct ts_offset_sample { @@ -156,6 +166,7 @@ struct tracecmd_input { char * uname; char * version; char * trace_clock; + struct input_buffer_instance top_buffer; struct input_buffer_instance *buffers; int parsing_failures; struct guest_trace_info *guest; @@ -2859,13 +2870,115 @@ __hidden unsigned int get_meta_strings_size(struct tracecmd_input *handle) return handle->strings_size; } +static inline int save_read_number(struct tep_handle *tep, char *data, int *data_size, + int *read_pos, int bytes, unsigned long long *num) +{ + if (bytes > *data_size) + return -1; + + *num = tep_read_number(tep, (data + *read_pos), bytes); + *read_pos += bytes; + *data_size -= bytes; + return 0; +} + +static inline char *save_read_string(char *data, int *data_size, int *read_pos) +{ + char *str; + + if (*data_size < 1) + return NULL; + + str = strdup(data + *read_pos); + if (!str) + return NULL; + *data_size -= (strlen(str) + 1); + if (*data_size < 0) { + free(str); + return NULL; + } + *read_pos += (strlen(str) + 1); + + return str; +} + +static int handle_buffer_option(struct tracecmd_input *handle, + unsigned short id, char *data, int size) +{ + struct input_buffer_instance *buff; + unsigned long long tmp; + int rsize = 0; + char *name; + int i; + + if (save_read_number(handle->pevent, data, &size, &rsize, 8, &tmp)) + return -1; + + name = save_read_string(data, &size, &rsize); + if (!name) + return -1; + + if (*name == '\0') { + /* top buffer */ + buff = &handle->top_buffer; + } else { + buff = realloc(handle->buffers, sizeof(*handle->buffers) * (handle->nr_buffers + 1)); + if (!buff) { + free(name); + return -1; + } + handle->buffers = buff; + handle->nr_buffers++; + + buff = &handle->buffers[handle->nr_buffers - 1]; + } + memset(buff, 0, sizeof(struct input_buffer_instance)); + buff->name = name; + buff->offset = tmp; + + if (!HAS_SECTIONS(handle)) + return 0; + + /* file sections specific data */ + buff->clock = save_read_string(data, &size, &rsize); + if (!buff->clock) + return -1; + + if (*name == '\0' && !handle->trace_clock) + handle->trace_clock = strdup(buff->clock); + + if (id == TRACECMD_OPTION_BUFFER) { + if (save_read_number(handle->pevent, data, &size, &rsize, 4, &tmp)) + return -1; + buff->cpus = tmp; + if (!buff->cpus) + return 0; + buff->cpu_data = calloc(buff->cpus, sizeof(struct cpu_file_data)); + if (!buff->cpu_data) + return -1; + for (i = 0; i < buff->cpus; i++) { + if (save_read_number(handle->pevent, data, &size, &rsize, 4, &tmp)) + return -1; + buff->cpu_data[i].cpu = tmp; + if (save_read_number(handle->pevent, data, + &size, &rsize, 8, &buff->cpu_data[i].offset)) + return -1; + if (save_read_number(handle->pevent, data, + &size, &rsize, 8, &buff->cpu_data[i].size)) + return -1; + } + } else { + buff->latency = true; + } + return 0; +} + static int handle_options(struct tracecmd_input *handle) { long long offset; unsigned short option; unsigned int size; char *cpustats = NULL; - struct input_buffer_instance *buffer; struct hook_list *hook; char *buf; int cpus; @@ -2956,21 +3069,10 @@ static int handle_options(struct tracecmd_input *handle) handle->cpustats = cpustats; break; case TRACECMD_OPTION_BUFFER: - /* A buffer instance is saved at the end of the file */ - handle->nr_buffers++; - handle->buffers = realloc(handle->buffers, - sizeof(*handle->buffers) * handle->nr_buffers); - if (!handle->buffers) - return -ENOMEM; - buffer = &handle->buffers[handle->nr_buffers - 1]; - buffer->name = strdup(buf + 8); - if (!buffer->name) { - free(handle->buffers); - handle->buffers = NULL; - return -ENOMEM; - } - offset = *(unsigned long long *)buf; - buffer->offset = tep_read_number(handle->pevent, &offset, 8); + case TRACECMD_OPTION_BUFFER_TEXT: + ret = handle_buffer_option(handle, option, buf, size); + if (ret < 0) + return ret; break; case TRACECMD_OPTION_TRACECLOCK: if (!handle->ts2secs) @@ -3759,6 +3861,13 @@ void tracecmd_ref(struct tracecmd_input *handle) handle->ref++; } +static inline void free_buffer(struct input_buffer_instance *buf) +{ + free(buf->name); + free(buf->clock); + free(buf->cpu_data); +} + /** * tracecmd_close - close and free the trace.dat handle * @handle: input handle for the trace.dat file @@ -3815,8 +3924,9 @@ void tracecmd_close(struct tracecmd_input *handle) free(del_sec); } + free_buffer(&handle->top_buffer); for (i = 0; i < handle->nr_buffers; i++) - free(handle->buffers[i].name); + free_buffer(&handle->buffers[i]); free(handle->buffers); tracecmd_free_hooks(handle->hooks); @@ -4260,6 +4370,7 @@ tracecmd_buffer_instance_handle(struct tracecmd_input *handle, int indx) return NULL; *new_handle = *handle; + memset(&new_handle->top_buffer, 0, sizeof(new_handle->top_buffer)); new_handle->cpu_data = NULL; new_handle->nr_buffers = 0; new_handle->buffers = NULL;