From patchwork Wed Jan 16 13:43:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10765993 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3205B1580 for ; Wed, 16 Jan 2019 13:43:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 219442E136 for ; Wed, 16 Jan 2019 13:43:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2032C2E158; Wed, 16 Jan 2019 13:43:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 70C122E136 for ; Wed, 16 Jan 2019 13:43:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390606AbfAPNn1 (ORCPT ); Wed, 16 Jan 2019 08:43:27 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:43455 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733175AbfAPNn1 (ORCPT ); Wed, 16 Jan 2019 08:43:27 -0500 Received: by mail-wr1-f67.google.com with SMTP id r10so6946703wrs.10 for ; Wed, 16 Jan 2019 05:43:25 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9+GF+jrI4TNjak2yGXa8jMFomUvzyDNqUDFXxev7EiI=; b=c3zNzp7SVFhc5R8uYSmjWMMcXZUFad36lYVioLr4gxfu3xBREjkPqnv4zUyIYpA/bQ wS06r3BP/lqCyoF0l29I7N76Z+CjG7HBiO5K1rij8X8WxPTfbkg8kmZxdqve3R/TvvTw 4x7BjAvThbwMh0+3g2Pze8UStqhwKboKLhAatpQnrkM6Kwo7dPxW6XDZu2SEMYzMxpcV +L7/K5rG06UWOzqq8Np4CgAlytNDDHeRBuPvSZ6Wsv8iRkydnXdHZGTjMdsPrBpKxMZP T4KgSiEeC4U2cK/rAtFQcaVzaPStMYHBz0KEvIgRncUl1bYEtz6v+O4B1D1H1WdXys/g VwaQ== X-Gm-Message-State: AJcUukeuQkQfhLheTyfI+u7EzzLLVO1FoshJwb+yq8T1zN/YnwIGbJUC XqQ+09CVnpyloW746xE6F82l+rY0xfpl X-Google-Smtp-Source: ALg8bN7mQStdI79pRKCucOJcRTfRO72oCZpX2/pHS2CLefLtgK6th1ZdLVR7zRG29+4zhLXW1sypaw== X-Received: by 2002:adf:be0f:: with SMTP id n15mr7880948wrh.267.1547646198866; Wed, 16 Jan 2019 05:43:18 -0800 (PST) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y13sm34636460wme.2.2019.01.16.05.43.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 05:43:15 -0800 (PST) From: Slavomir Kaslev To: linux-trace-devel@vger.kernel.org Cc: rostedt@goodmis.org, ykaradzhov@vmware.com, tstoyanov@vmware.com Subject: [PATCH v4 1/8] trace-cmd: Minor refactoring Date: Wed, 16 Jan 2019 15:43:00 +0200 Message-Id: <20190116134307.4185-2-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190116134307.4185-1-kaslevs@vmware.com> References: <20190116134307.4185-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Pass `struct common_record_context` in trace-record.c instead of explicitly passing necessary options through additional arguments. Signed-off-by: Slavomir Kaslev --- tracecmd/trace-record.c | 91 +++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 01330ee..a8c3464 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -191,6 +191,36 @@ enum { RESET_HIGH_PRIO = 100000, }; +enum trace_cmd { + CMD_extract, + CMD_start, + CMD_stream, + CMD_profile, + CMD_record, + CMD_record_agent, +}; + +struct common_record_context { + enum trace_cmd curr_cmd; + struct buffer_instance *instance; + const char *output; + char *date2ts; + char *max_graph_depth; + int data_flags; + + int record_all; + int total_disable; + int disable; + int events; + int global; + int filtered; + int date; + int manual; + int topt; + int do_child; + int run_command; +}; + static void add_reset_file(const char *file, const char *val, int prio) { struct reset_file *reset; @@ -2880,10 +2910,10 @@ again: return msg_handle; } -static void add_options(struct tracecmd_output *handle, char *date2ts, int flags); +static void add_options(struct tracecmd_output *handle, struct common_record_context *ctx); static struct tracecmd_msg_handle * -setup_connection(struct buffer_instance *instance, char *date2ts, int flags) +setup_connection(struct buffer_instance *instance, struct common_record_context *ctx) { struct tracecmd_msg_handle *msg_handle; struct tracecmd_output *network_handle; @@ -2893,7 +2923,7 @@ setup_connection(struct buffer_instance *instance, char *date2ts, int flags) /* Now create the handle through this socket */ if (msg_handle->version == V3_PROTOCOL) { network_handle = tracecmd_create_init_fd_msg(msg_handle, listed_events); - add_options(network_handle, date2ts, flags); + add_options(network_handle, ctx); tracecmd_write_cpus(network_handle, instance->cpu_count); tracecmd_write_options(network_handle); tracecmd_msg_finish_sending_data(msg_handle); @@ -2915,7 +2945,7 @@ static void finish_network(struct tracecmd_msg_handle *msg_handle) free(host); } -void start_threads(enum trace_type type, int global, char *date2ts, int flags) +void start_threads(enum trace_type type, struct common_record_context *ctx) { struct buffer_instance *instance; int *brass = NULL; @@ -2937,7 +2967,7 @@ void start_threads(enum trace_type type, int global, char *date2ts, int flags) int x, pid; if (host) { - instance->msg_handle = setup_connection(instance, date2ts, flags); + instance->msg_handle = setup_connection(instance, ctx); if (!instance->msg_handle) die("Failed to make connection"); } @@ -2952,7 +2982,7 @@ void start_threads(enum trace_type type, int global, char *date2ts, int flags) brass[0], instance->cpu_count, hooks, handle_init, - global); + ctx->global); if (!pids[i].stream) die("Creating stream for %d", i); } else @@ -3091,19 +3121,19 @@ enum { DATA_FL_OFFSET = 2, }; -static void add_options(struct tracecmd_output *handle, char *date2ts, int flags) +static void add_options(struct tracecmd_output *handle, struct common_record_context *ctx) { int type = 0; - if (date2ts) { - if (flags & DATA_FL_DATE) + if (ctx->date2ts) { + if (ctx->data_flags & DATA_FL_DATE) type = TRACECMD_OPTION_DATE; - else if (flags & DATA_FL_OFFSET) + else if (ctx->data_flags & DATA_FL_OFFSET) type = TRACECMD_OPTION_OFFSET; } if (type) - tracecmd_add_option(handle, type, strlen(date2ts)+1, date2ts); + tracecmd_add_option(handle, type, strlen(ctx->date2ts)+1, ctx->date2ts); tracecmd_add_option(handle, TRACECMD_OPTION_TRACECLOCK, 0, NULL); add_option_hooks(handle); @@ -3111,7 +3141,7 @@ static void add_options(struct tracecmd_output *handle, char *date2ts, int flags } -static void record_data(char *date2ts, int flags) +static void record_data(struct common_record_context *ctx) { struct tracecmd_option **buffer_options; struct tracecmd_output *handle; @@ -3166,7 +3196,7 @@ static void record_data(char *date2ts, int flags) if (!handle) die("Error creating output file"); - add_options(handle, date2ts, flags); + add_options(handle, ctx); /* Only record the top instance under TRACECMD_OPTION_CPUSTAT*/ if (!no_top_instance() && !top_instance.msg_handle) { @@ -4469,35 +4499,6 @@ void trace_reset(int argc, char **argv) exit(0); } -enum trace_cmd { - CMD_extract, - CMD_start, - CMD_stream, - CMD_profile, - CMD_record -}; - -struct common_record_context { - enum trace_cmd curr_cmd; - struct buffer_instance *instance; - const char *output; - char *date2ts; - char *max_graph_depth; - int data_flags; - - int record_all; - int total_disable; - int disable; - int events; - int global; - int filtered; - int date; - int manual; - int topt; - int do_child; - int run_command; -}; - static void init_common_record_context(struct common_record_context *ctx, enum trace_cmd curr_cmd) { @@ -4986,7 +4987,7 @@ static void record_trace(int argc, char **argv, if (type & (TRACE_TYPE_RECORD | TRACE_TYPE_STREAM)) { signal(SIGINT, finish); if (!latency) - start_threads(type, ctx->global, ctx->date2ts, ctx->data_flags); + start_threads(type, ctx); } else { update_task_filter(); tracecmd_enable_tracing(); @@ -5017,7 +5018,7 @@ static void record_trace(int argc, char **argv, tracecmd_disable_all_tracing(0); if (IS_RECORD(ctx)) { - record_data(ctx->date2ts, ctx->data_flags); + record_data(ctx); delete_thread_data(); } else print_stats(); @@ -5097,7 +5098,7 @@ void trace_extract(int argc, char **argv) ctx.date2ts = get_date_to_ts(); } - record_data(ctx.date2ts, ctx.data_flags); + record_data(&ctx); delete_thread_data(); destroy_stats(); finalize_record_trace(&ctx); From patchwork Wed Jan 16 13:43:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10765985 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 57AD991E for ; Wed, 16 Jan 2019 13:43:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 478402E05A for ; Wed, 16 Jan 2019 13:43:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 461222E084; Wed, 16 Jan 2019 13:43:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D51432E148 for ; Wed, 16 Jan 2019 13:43:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390634AbfAPNnW (ORCPT ); Wed, 16 Jan 2019 08:43:22 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:43446 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733175AbfAPNnW (ORCPT ); Wed, 16 Jan 2019 08:43:22 -0500 Received: by mail-wr1-f67.google.com with SMTP id r10so6946435wrs.10 for ; Wed, 16 Jan 2019 05:43:21 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qAVEmCrwQ7LbzgWl1iLQa+qb+EmOa9tBt+vB6/lwOjI=; b=s0ItrsBx7rAOCBngxtaO4giAPjS+q4fw0zyyWqsWxZjj5WpcjE9lly3c+F5IIDlKsC nJSHDdn5Op2tBIanFGZhnOv1Fga11Dc1krtFcwyto2L/EWiMadCLEBGYYDIo2Zr6nZ4k pQmtO86aebyvn8BFKQZMavc3+MZkSwgeSwCN2apKHMdOrNwkOwLyUG7aneUz0sy4jy52 KDYst00EpdhHv3RH4rChWOMHZaIkjb8Xtg6iD4AI9RVg5abLTd0k+tF/bOQ8sw6ZqwlN u8BsdhCkMjOm5f/cEwUn/N8778ZxP1rCAqLLg2oXuw4/0MG3LjupAV1tJOJf7+M6FXmK 8QsQ== X-Gm-Message-State: AJcUukdqH64ZKEwaMWaV1+yppqHvYkOqrVOQljAn+2lXaMJV0aOpRVP7 bu6Xpi/mD3eMxqTOUltCENcobPxySY1l X-Google-Smtp-Source: ALg8bN5T1ShX3WzHPMsvAUP1GWnxAc2rjfglmsD13w6XRvdY6yhgcDcA1IeaNcW/Qx5e/TOtGsLUJg== X-Received: by 2002:adf:b307:: with SMTP id j7mr8146129wrd.46.1547646200335; Wed, 16 Jan 2019 05:43:20 -0800 (PST) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y13sm34636460wme.2.2019.01.16.05.43.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 05:43:19 -0800 (PST) From: Slavomir Kaslev To: linux-trace-devel@vger.kernel.org Cc: rostedt@goodmis.org, ykaradzhov@vmware.com, tstoyanov@vmware.com Subject: [PATCH v4 2/8] trace-cmd: Detect if vsock sockets are available Date: Wed, 16 Jan 2019 15:43:01 +0200 Message-Id: <20190116134307.4185-3-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190116134307.4185-1-kaslevs@vmware.com> References: <20190116134307.4185-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Steven Rostedt (VMware)" Detect and define VSOCK if vsock sockets are available on the system. This macro is used to disable VM remote tracing features on older kernels. Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Slavomir Kaslev --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index 27d3683..abc4f0c 100644 --- a/Makefile +++ b/Makefile @@ -205,6 +205,13 @@ CFLAGS ?= -g -Wall CPPFLAGS ?= LDFLAGS ?= +VSOCK_DEFINED := $(shell if (echo "\#include " | $(CC) -E - >/dev/null 2>&1) ; then echo 1; else echo 0 ; fi) + +export VSOCK_DEFINED +ifeq ($(VSOCK_DEFINED), 1) +CFLAGS += -DVSOCK +endif + export CFLAGS export INCLUDES From patchwork Wed Jan 16 13:43:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10765987 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C9CE391E for ; Wed, 16 Jan 2019 13:43:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9BB52E035 for ; Wed, 16 Jan 2019 13:43:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B7BE22E148; Wed, 16 Jan 2019 13:43:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3B0B02DF94 for ; Wed, 16 Jan 2019 13:43:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2393123AbfAPNnY (ORCPT ); Wed, 16 Jan 2019 08:43:24 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:39719 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390606AbfAPNnX (ORCPT ); Wed, 16 Jan 2019 08:43:23 -0500 Received: by mail-wm1-f66.google.com with SMTP id y8so2028273wmi.4 for ; Wed, 16 Jan 2019 05:43:22 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=is+fCEKAowcfnxMqwkgjpPxrBQbER9H2tVdWYmXmRW4=; b=oJxv0eKLOrJT6cvMMSa3UQAhPopCgX88vbmB2IJAwCwv2RgAg7inM4wt7fIuYnjJHY MNUi8T/5XMhlbp8Qf7vy/ggDhogsD8yqVfq43uK+w+sgl09FmKOlTYdOa4N/9s5w1kny kvcI+rMRfXEV9E2MUHdUCGhk9UFM33OjvZqh+gTLgdN6ArZiX5R+OHxqUQ12tK6MNujd AxqI0QV7c8/rNBkA7c9q38hVzZSQzDhcc+oOJ7pV57jM6YjB7yCADAOmKCdbQctgAHF4 ANxI9LfnibMOaw9yOGq+AYg98G+6t0SJYGoo3ikeNqtmCwfOxwbJrh7k1Umn2RkmZXBz rOTQ== X-Gm-Message-State: AJcUukcYipEX71A3X9zCaWd8hT2G+j8S49z9Kyj7QsvVl3ug30w4iiax dQBlmg77F2Ly3eM5fODoMu0BMBvmkaWw X-Google-Smtp-Source: ALg8bN4RTZ/FC+kf8Ui2Io0mx1Yyo7MKcWtYhtnMdARZ+45oeCpUDbPtgwgDPt2caM8ugCxRNd9DjA== X-Received: by 2002:a1c:7c07:: with SMTP id x7mr7754348wmc.82.1547646201603; Wed, 16 Jan 2019 05:43:21 -0800 (PST) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y13sm34636460wme.2.2019.01.16.05.43.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 05:43:20 -0800 (PST) From: Slavomir Kaslev To: linux-trace-devel@vger.kernel.org Cc: rostedt@goodmis.org, ykaradzhov@vmware.com, tstoyanov@vmware.com Subject: [PATCH v4 3/8] trace-cmd: Add tracecmd_create_recorder_virt function Date: Wed, 16 Jan 2019 15:43:02 +0200 Message-Id: <20190116134307.4185-4-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190116134307.4185-1-kaslevs@vmware.com> References: <20190116134307.4185-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add tracecmd_create_recorder_virt function that will be used for tracing VM guests. Signed-off-by: Slavomir Kaslev --- include/trace-cmd/trace-cmd.h | 1 + lib/trace-cmd/trace-recorder.c | 53 ++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 99a455c..ff4f0f7 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -277,6 +277,7 @@ enum { void tracecmd_free_recorder(struct tracecmd_recorder *recorder); struct tracecmd_recorder *tracecmd_create_recorder(const char *file, int cpu, unsigned flags); struct tracecmd_recorder *tracecmd_create_recorder_fd(int fd, int cpu, unsigned flags); +struct tracecmd_recorder *tracecmd_create_recorder_virt(const char *file, int cpu, unsigned flags, int trace_fd); struct tracecmd_recorder *tracecmd_create_recorder_maxkb(const char *file, int cpu, unsigned flags, int maxkb); struct tracecmd_recorder *tracecmd_create_buffer_recorder_fd(int fd, int cpu, unsigned flags, const char *buffer); struct tracecmd_recorder *tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags, const char *buffer); diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index 5331925..83a12f4 100644 --- a/lib/trace-cmd/trace-recorder.c +++ b/lib/trace-cmd/trace-recorder.c @@ -148,16 +148,22 @@ tracecmd_create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags, recorder->fd1 = fd; recorder->fd2 = fd2; - if (flags & TRACECMD_RECORD_SNAPSHOT) - ret = asprintf(&path, "%s/per_cpu/cpu%d/snapshot_raw", buffer, cpu); - else - ret = asprintf(&path, "%s/per_cpu/cpu%d/trace_pipe_raw", buffer, cpu); - if (ret < 0) - goto out_free; + if (buffer) { + if (flags & TRACECMD_RECORD_SNAPSHOT) + ret = asprintf(&path, "%s/per_cpu/cpu%d/snapshot_raw", + buffer, cpu); + else + ret = asprintf(&path, "%s/per_cpu/cpu%d/trace_pipe_raw", + buffer, cpu); + if (ret < 0) + goto out_free; + + recorder->trace_fd = open(path, O_RDONLY); + free(path); - recorder->trace_fd = open(path, O_RDONLY); - if (recorder->trace_fd < 0) - goto out_free; + if (recorder->trace_fd < 0) + goto out_free; + } if ((recorder->flags & TRACECMD_RECORD_NOSPLICE) == 0) { ret = pipe(recorder->brass); @@ -177,13 +183,9 @@ tracecmd_create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags, recorder->pipe_size = pipe_size; } - free(path); - return recorder; out_free: - free(path); - tracecmd_free_recorder(recorder); return NULL; } @@ -194,8 +196,9 @@ tracecmd_create_buffer_recorder_fd(int fd, int cpu, unsigned flags, const char * return tracecmd_create_buffer_recorder_fd2(fd, -1, cpu, flags, buffer, 0); } -struct tracecmd_recorder * -tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags, const char *buffer) +static struct tracecmd_recorder * +__tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags, + const char *buffer) { struct tracecmd_recorder *recorder; int fd; @@ -258,6 +261,26 @@ tracecmd_create_buffer_recorder_maxkb(const char *file, int cpu, unsigned flags, goto out; } +struct tracecmd_recorder * +tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags, + const char *buffer) +{ + return __tracecmd_create_buffer_recorder(file, cpu, flags, buffer); +} + +struct tracecmd_recorder * +tracecmd_create_recorder_virt(const char *file, int cpu, unsigned flags, + int trace_fd) +{ + struct tracecmd_recorder *recorder; + + recorder = __tracecmd_create_buffer_recorder(file, cpu, flags, NULL); + if (recorder) + recorder->trace_fd = trace_fd; + + return recorder; +} + struct tracecmd_recorder *tracecmd_create_recorder_fd(int fd, int cpu, unsigned flags) { const char *tracing; From patchwork Wed Jan 16 13:43:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10765989 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E13AC91E for ; Wed, 16 Jan 2019 13:43:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D120F2E158 for ; Wed, 16 Jan 2019 13:43:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C56132E110; Wed, 16 Jan 2019 13:43:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 672952E158 for ; Wed, 16 Jan 2019 13:43:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2393146AbfAPNnZ (ORCPT ); Wed, 16 Jan 2019 08:43:25 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:39724 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733175AbfAPNnZ (ORCPT ); Wed, 16 Jan 2019 08:43:25 -0500 Received: by mail-wm1-f68.google.com with SMTP id y8so2028355wmi.4 for ; Wed, 16 Jan 2019 05:43:23 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JEXu/pVG/AZlTpO1z3QOm0XGovcYNNOUFX16etekqGU=; b=ZL5H6+mBeceXgWOQx7Bp08mueWEQ0bEtAHSzMOnaMiOWOFLbPpdHposljHUWRDv3Sk zU3nV+ojgHnW8Q2uJV8VU2RJG2EMnF6ymWZzRNHbFsSZyO/X/E41YhbvajjYVpGgpdBr tg4ZAr7l3YXc0rkhuoK91rkqsSLmEn9Jb5OFpw3AMPJdXByZAjOiZQGKejATkKh+aW0U KoNPUTY9ZmRxA+dx0kQHbHziYI1TN4dX+z3pz2DQRvPJJwKJpWEja1vyFPr6SOYK86Zl sL1JTf1Iu8HVKlp80lnC9qnYv3jBIRvznxKE6Ie079rUSXWrhDF65RT43lW8cO1ZwERO 7iYw== X-Gm-Message-State: AJcUukf5szEBhPKq0RoQtSGa/Hk0ke65Nl1qZG/zq1dhj/uRlAC8u/yj uzvhVpRBxxd2p2c4tQH71sb4bjBjxnEl X-Google-Smtp-Source: ALg8bN7WmsL8tYHJWBkyDBNCTxpzrb+kr8gNEjdkTdKdgz6vU1WVdg08OrshyMX+UJFhcYbtgzq4tQ== X-Received: by 2002:a1c:c44c:: with SMTP id u73mr7957236wmf.45.1547646202854; Wed, 16 Jan 2019 05:43:22 -0800 (PST) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y13sm34636460wme.2.2019.01.16.05.43.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 05:43:22 -0800 (PST) From: Slavomir Kaslev To: linux-trace-devel@vger.kernel.org Cc: rostedt@goodmis.org, ykaradzhov@vmware.com, tstoyanov@vmware.com Subject: [PATCH v4 4/8] trace-cmd: Use unsigned int for trace-cmd client ports Date: Wed, 16 Jan 2019 15:43:03 +0200 Message-Id: <20190116134307.4185-5-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190116134307.4185-1-kaslevs@vmware.com> References: <20190116134307.4185-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Tzvetomir Stoyanov By definition, communication ports used by trace-cmd clients are 32 bit unsigned integers. These ports are generated randomly, and in some implementations can overlap the signed integer range. This patch converts all client ports in trace-cmd to be unsigned 32 bit integers. Signed-off-by: Tzvetomir Stoyanov Signed-off-by: Slavomir Kaslev --- include/trace-cmd/trace-cmd.h | 2 +- tracecmd/trace-msg.c | 4 ++-- tracecmd/trace-record.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index ff4f0f7..8b43462 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -322,7 +322,7 @@ void tracecmd_msg_handle_close(struct tracecmd_msg_handle *msg_handle); /* for clients */ int tracecmd_msg_send_init_data(struct tracecmd_msg_handle *msg_handle, - int **client_ports); + unsigned int **client_ports); int tracecmd_msg_data_send(struct tracecmd_msg_handle *msg_handle, const char *buf, int size); int tracecmd_msg_finish_sending_data(struct tracecmd_msg_handle *msg_handle); diff --git a/tracecmd/trace-msg.c b/tracecmd/trace-msg.c index edde582..529ae2a 100644 --- a/tracecmd/trace-msg.c +++ b/tracecmd/trace-msg.c @@ -386,12 +386,12 @@ static int tracecmd_msg_wait_for_msg(int fd, struct tracecmd_msg *msg) } int tracecmd_msg_send_init_data(struct tracecmd_msg_handle *msg_handle, - int **client_ports) + unsigned int **client_ports) { struct tracecmd_msg send_msg; struct tracecmd_msg recv_msg; int fd = msg_handle->fd; - int *ports; + unsigned int *ports; int i, cpus; int ret; diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index a8c3464..3034a4b 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -74,7 +74,7 @@ static int buffers; static int clear_function_filters; static char *host; -static int *client_ports; +static unsigned int *client_ports; static int sfd; /* Max size to let a per cpu file get */ @@ -2545,7 +2545,7 @@ static void connect_port(int cpu) int s; char buf[BUFSIZ]; - snprintf(buf, BUFSIZ, "%d", client_ports[cpu]); + snprintf(buf, BUFSIZ, "%u", client_ports[cpu]); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -2755,7 +2755,7 @@ static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle) /* No options */ write(msg_handle->fd, "0", 2); - client_ports = malloc(sizeof(int) * local_cpu_count); + client_ports = malloc(local_cpu_count * sizeof(*client_ports)); if (!client_ports) die("Failed to allocate client ports for %d cpus", local_cpu_count); From patchwork Wed Jan 16 13:43:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10765991 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1C24C13BF for ; Wed, 16 Jan 2019 13:43:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0BDF42E158 for ; Wed, 16 Jan 2019 13:43:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 09F8B2E179; Wed, 16 Jan 2019 13:43:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 45B1E2E167 for ; Wed, 16 Jan 2019 13:43:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2393195AbfAPNn1 (ORCPT ); Wed, 16 Jan 2019 08:43:27 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:53981 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390606AbfAPNn0 (ORCPT ); Wed, 16 Jan 2019 08:43:26 -0500 Received: by mail-wm1-f65.google.com with SMTP id d15so2028046wmb.3 for ; Wed, 16 Jan 2019 05:43:25 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=T9HjdvgaJF6PBPV6Si/8FnQfnGxz8wksS6OUCM3jlew=; b=G899P/U073vY8rOo1xTMknTzdiiWxS04rnOQeJP99+zAfqmknB+RJZ6i+5h0YNSKk8 yNqro4ahOVwTJSErpU2AWKzLQ9KreP6LgeQZiMUjJ0uCwFnNYtsL5t0zG6Bjio8omeI3 8Sq4ZT2LI+oGkKZ0zphX7KM441u5hkBlPLrpOAap2LsPjQKI26L1YwgXRFXI4DxrCJ9F M18Wehglkk8wqM4iJnP6gn3YghWDX+fKAvQUm4bePN1GFG9LYXIyfo2msBVmW/m8VMLn rDjDNIRzI+yjMhAmkeYNZi5YHYYwqWbTuRMJIwNyObyJ+NEms6qAFmBk3n/kobrE62AG NhZA== X-Gm-Message-State: AJcUukf93W+g7vqhJqC2AzVg2M5iKLVtdZ+o655F74of0oWednu/xRsT UQCZ0yNPAisJnaKOnOWL0Ds6Zc0/mLDP X-Google-Smtp-Source: ALg8bN7L5mFCYrK3aEu8LmftWlOCgTxTUsHgjGQut7C5XGCUfCTdyLyb07LyKKSY346AoJ6WDFiAAQ== X-Received: by 2002:a1c:1383:: with SMTP id 125mr7908464wmt.71.1547646204005; Wed, 16 Jan 2019 05:43:24 -0800 (PST) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y13sm34636460wme.2.2019.01.16.05.43.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 05:43:23 -0800 (PST) From: Slavomir Kaslev To: linux-trace-devel@vger.kernel.org Cc: rostedt@goodmis.org, ykaradzhov@vmware.com, tstoyanov@vmware.com Subject: [PATCH v4 5/8] trace-cmd: Add TRACE_REQ and TRACE_RESP messages Date: Wed, 16 Jan 2019 15:43:04 +0200 Message-Id: <20190116134307.4185-6-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190116134307.4185-1-kaslevs@vmware.com> References: <20190116134307.4185-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add TRACE_REQ and TRACE_RESP messages which are used for initiating guest VM tracing. Signed-off-by: Slavomir Kaslev --- include/trace-cmd/trace-cmd.h | 14 +++ tracecmd/trace-msg.c | 206 +++++++++++++++++++++++++++++++++- 2 files changed, 219 insertions(+), 1 deletion(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 8b43462..238e16b 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -337,6 +337,20 @@ int tracecmd_msg_collect_data(struct tracecmd_msg_handle *msg_handle, int ofd); bool tracecmd_msg_done(struct tracecmd_msg_handle *msg_handle); void tracecmd_msg_set_done(struct tracecmd_msg_handle *msg_handle); +int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle, + int argc, char **argv); +int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle, + int *argc, char ***argv); + +int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle, + int nr_cpus, int page_size, + unsigned int *ports); +int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, + int *nr_cpus, int *page_size, + unsigned int **ports); + +int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle); + /* --- Plugin handling --- */ extern struct tep_plugin_option trace_ftrace_options[]; diff --git a/tracecmd/trace-msg.c b/tracecmd/trace-msg.c index 529ae2a..46b18aa 100644 --- a/tracecmd/trace-msg.c +++ b/tracecmd/trace-msg.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,16 @@ struct tracecmd_msg_rinit { be32 cpus; } __attribute__((packed)); +struct tracecmd_msg_trace_req { + be32 flags; + be32 argc; +} __attribute__((packed)); + +struct tracecmd_msg_trace_resp { + be32 cpus; + be32 page_size; +} __attribute__((packed)); + struct tracecmd_msg_header { be32 size; be32 cmd; @@ -90,7 +101,9 @@ struct tracecmd_msg_header { C(TINIT, 1, sizeof(struct tracecmd_msg_tinit)), \ C(RINIT, 2, sizeof(struct tracecmd_msg_rinit)), \ C(SEND_DATA, 3, 0), \ - C(FIN_DATA, 4, 0), + C(FIN_DATA, 4, 0), \ + C(TRACE_REQ, 5, sizeof(struct tracecmd_msg_trace_req)), \ + C(TRACE_RESP, 6, sizeof(struct tracecmd_msg_trace_resp)), #undef C #define C(a,b,c) MSG_##a = b @@ -122,6 +135,8 @@ struct tracecmd_msg { union { struct tracecmd_msg_tinit tinit; struct tracecmd_msg_rinit rinit; + struct tracecmd_msg_trace_req trace_req; + struct tracecmd_msg_trace_resp trace_resp; }; union { struct tracecmd_msg_opt *opt; @@ -715,3 +730,192 @@ error: msg_free(&msg); return ret; } + +static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv) +{ + size_t args_size = 0; + char *p; + int i; + + for (i = 0; i < argc; i++) + args_size += strlen(argv[i]) + 1; + + msg->hdr.size = htonl(ntohl(msg->hdr.size) + args_size); + msg->trace_req.argc = htonl(argc); + msg->buf = calloc(args_size, 1); + if (!msg->buf) + return -ENOMEM; + + p = msg->buf; + for (i = 0; i < argc; i++) + p = stpcpy(p, argv[i]) + 1; + + return 0; +} + +int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle, + int argc, char **argv) +{ + struct tracecmd_msg msg; + int ret; + + tracecmd_msg_init(MSG_TRACE_REQ, &msg); + ret = make_trace_req(&msg, argc, argv); + if (ret) + return ret; + + return tracecmd_msg_send(msg_handle->fd, &msg); +} + + /* + * NOTE: On success, the returned `argv` should be freed with: + * free(argv[0]); + * free(argv); + */ +int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle, + int *argc, char ***argv) +{ + struct tracecmd_msg msg; + char *p, *buf_end, **args; + int i, ret, nr_args; + size_t buf_len; + + ret = tracecmd_msg_recv(msg_handle->fd, &msg); + if (ret < 0) + return ret; + + if (ntohl(msg.hdr.cmd) != MSG_TRACE_REQ) + goto out; + + if (ntohl(msg.trace_req.argc) < 0) + goto out; + + buf_len = ntohl(msg.hdr.size) - MSG_HDR_LEN - ntohl(msg.hdr.cmd_size); + buf_end = (char *)msg.buf + buf_len; + p = msg.buf; + nr_args = ntohl(msg.trace_req.argc); + args = calloc(nr_args, sizeof(*args)); + if (!args) { + ret = -ENOMEM; + goto out; + } + for (i = 0; i < nr_args; i++) { + if (p >= buf_end) { + ret = -1; + free(args); + goto out; + } + + args[i] = p; + p = strchr(p, '\0'); + p++; + } + + /* + * On success we're passing msg.buf to the caller through argv[0] so we + * reset it here to avoid getting it freed below. + */ + msg.buf = NULL; + *argc = nr_args; + *argv = args; + ret = 0; + +out: + msg_free(&msg); + return ret; +} + +static int make_trace_resp(struct tracecmd_msg *msg, + int page_size, int nr_cpus, unsigned int *ports) +{ + int ports_size = nr_cpus * sizeof(*msg->port_array); + int i; + + msg->hdr.size = htonl(ntohl(msg->hdr.size) + ports_size); + msg->trace_resp.cpus = htonl(nr_cpus); + msg->trace_resp.page_size = htonl(page_size); + + msg->port_array = malloc(ports_size); + if (!msg->port_array) + return -ENOMEM; + + for (i = 0; i < nr_cpus; i++) + msg->port_array[i] = htonl(ports[i]); + + return 0; +} + +int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle, + int nr_cpus, int page_size, + unsigned int *ports) +{ + struct tracecmd_msg msg; + int ret; + + tracecmd_msg_init(MSG_TRACE_RESP, &msg); + ret = make_trace_resp(&msg, page_size, nr_cpus, ports); + if (ret < 0) + return ret; + + return tracecmd_msg_send(msg_handle->fd, &msg); +} + +int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, + int *nr_cpus, int *page_size, + unsigned int **ports) +{ + struct tracecmd_msg msg; + size_t buf_len; + int i, ret; + + ret = tracecmd_msg_recv(msg_handle->fd, &msg); + if (ret < 0) + return ret; + + if (ntohl(msg.hdr.cmd) != MSG_TRACE_RESP) { + ret = -1; + goto out; + } + + buf_len = ntohl(msg.hdr.size) - MSG_HDR_LEN - ntohl(msg.hdr.cmd_size); + if (buf_len <= 0 || + buf_len != sizeof(*msg.port_array) * ntohl(msg.trace_resp.cpus)) { + ret = -1; + goto out; + } + + *nr_cpus = ntohl(msg.trace_resp.cpus); + *page_size = ntohl(msg.trace_resp.page_size); + *ports = calloc(*nr_cpus, sizeof(**ports)); + if (!*ports) { + ret = -ENOMEM; + goto out; + } + for (i = 0; i < *nr_cpus; i++) + (*ports)[i] = ntohl(msg.port_array[i]); + + ret = 0; + +out: + msg_free(&msg); + return ret; +} + +int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle) +{ + struct tracecmd_msg msg; + int ret; + + memset(&msg, 0, sizeof(msg)); + for (;;) { + ret = tracecmd_msg_wait_for_msg(msg_handle->fd, &msg); + msg_free(&msg); + + if (ret == -ECONNABORTED) + return 0; + if (ret < 0) + return ret; + } + + return -1; +} From patchwork Wed Jan 16 13:43:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10765995 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B4DE291E for ; Wed, 16 Jan 2019 13:43:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A43A52E107 for ; Wed, 16 Jan 2019 13:43:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A271E2E14E; Wed, 16 Jan 2019 13:43:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 168F12E165 for ; Wed, 16 Jan 2019 13:43:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2393197AbfAPNn2 (ORCPT ); Wed, 16 Jan 2019 08:43:28 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36419 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733175AbfAPNn2 (ORCPT ); Wed, 16 Jan 2019 08:43:28 -0500 Received: by mail-wm1-f68.google.com with SMTP id p6so2037597wmc.1 for ; Wed, 16 Jan 2019 05:43:27 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cILFA6YqC26BwdhG6xlYaNZ/d3tVOXiWsCpNOhOBXGY=; b=LFpwSQBTp+cpQOXmdIiJNXPl++wep7utb7tTmtV8dPzOYqYruuM4lxXPnyaSOOl8GL 77PkkRcTzfy6m2OGCVtYiqQ0lVV68iixuCE7BSEDXmcGJxgZPcgrYO/R2lSRni36cM9F ZxJ5/WEyMU9d+WMa8gzewntFrm4skiR/aJ8VymgU9XGtZV1Q8HYj98sYP5pjDOvzD6ob WroULqi+tEQx3twXQYtw/U+XwXpyqRxgU9PQ5PpSEcVis0qU85KisZGLQGicOCPThPRx 6KGXOozQwCJQqixsElMu6AKgumVg9cLCgtEh2nJeG8wG13AUWVQK9a+waD0keyMnqCAl DkGw== X-Gm-Message-State: AJcUukeUfRL6Bp3h68gCjZpg3LjEjH+bngvQAhwIzmk25jrmiMg3ns1w twB2btI/DO8XUbyLHzhklr7uBC6TKg== X-Google-Smtp-Source: ALg8bN7Ie1Z7VIoP5Jt06sgStzXSJmjRSwNc7LmqbBv9QvCOvfVko8y/PRsNSxVXam1ECnhNOS+S8Q== X-Received: by 2002:a1c:f509:: with SMTP id t9mr8083201wmh.76.1547646206215; Wed, 16 Jan 2019 05:43:26 -0800 (PST) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y13sm34636460wme.2.2019.01.16.05.43.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 05:43:24 -0800 (PST) From: Slavomir Kaslev To: linux-trace-devel@vger.kernel.org Cc: rostedt@goodmis.org, ykaradzhov@vmware.com, tstoyanov@vmware.com Subject: [PATCH v4 6/8] trace-cmd: Add buffer instance flags for tracing in guest and agent context Date: Wed, 16 Jan 2019 15:43:05 +0200 Message-Id: <20190116134307.4185-7-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190116134307.4185-1-kaslevs@vmware.com> References: <20190116134307.4185-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add BUFFER_FL_GUEST and BUFFER_FL_AGENT flags to differentiate when trace-record.c is being called to trace guest or the VM tracing agent. Also disable functions talking to the local tracefs when called in recording guest instances context. Signed-off-by: Slavomir Kaslev --- tracecmd/include/trace-local.h | 2 ++ tracecmd/trace-record.c | 55 ++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index a1a06e9..f19c8bb 100644 --- a/tracecmd/include/trace-local.h +++ b/tracecmd/include/trace-local.h @@ -149,6 +149,8 @@ char *strstrip(char *str); enum buffer_instance_flags { BUFFER_FL_KEEP = 1 << 0, BUFFER_FL_PROFILE = 1 << 1, + BUFFER_FL_GUEST = 1 << 2, + BUFFER_FL_AGENT = 1 << 3, }; struct func_list { diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 3034a4b..b911c34 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -781,6 +781,9 @@ static void __clear_trace(struct buffer_instance *instance) FILE *fp; char *path; + if (instance->flags & BUFFER_FL_GUEST) + return; + /* reset the trace */ path = get_instance_file(instance, "trace"); fp = fopen(path, "w"); @@ -1264,6 +1267,9 @@ set_plugin_instance(struct buffer_instance *instance, const char *name) char *path; char zero = '0'; + if (instance->flags & BUFFER_FL_GUEST) + return; + path = get_instance_file(instance, "current_tracer"); fp = fopen(path, "w"); if (!fp) { @@ -1360,6 +1366,9 @@ static void disable_func_stack_trace_instance(struct buffer_instance *instance) int size; int ret; + if (instance->flags & BUFFER_FL_GUEST) + return; + path = get_instance_file(instance, "current_tracer"); ret = stat(path, &st); tracecmd_put_tracing_file(path); @@ -1553,6 +1562,9 @@ reset_events_instance(struct buffer_instance *instance) int i; int ret; + if (instance->flags & BUFFER_FL_GUEST) + return; + if (use_old_event_method()) { /* old way only had top instance */ if (!is_top_instance(instance)) @@ -1904,6 +1916,9 @@ static void write_tracing_on(struct buffer_instance *instance, int on) int ret; int fd; + if (instance->flags & BUFFER_FL_GUEST) + return; + fd = open_tracing_on(instance); if (fd < 0) return; @@ -1923,6 +1938,9 @@ static int read_tracing_on(struct buffer_instance *instance) char buf[10]; int ret; + if (instance->flags & BUFFER_FL_GUEST) + return -1; + fd = open_tracing_on(instance); if (fd < 0) return fd; @@ -2156,6 +2174,9 @@ static void set_mask(struct buffer_instance *instance) int fd; int ret; + if (instance->flags & BUFFER_FL_GUEST) + return; + if (!instance->cpumask) return; @@ -2186,6 +2207,9 @@ static void enable_events(struct buffer_instance *instance) { struct event_list *event; + if (instance->flags & BUFFER_FL_GUEST) + return; + for (event = instance->events; event; event = event->next) { if (!event->neg) update_event(event, event->filter, 0, '1'); @@ -2209,6 +2233,9 @@ static void set_clock(struct buffer_instance *instance) char *content; char *str; + if (instance->flags & BUFFER_FL_GUEST) + return; + if (!instance->clock) return; @@ -2238,6 +2265,9 @@ static void set_max_graph_depth(struct buffer_instance *instance, char *max_grap char *path; int ret; + if (instance->flags & BUFFER_FL_GUEST) + return; + path = get_instance_file(instance, "max_graph_depth"); reset_save_file(path, RESET_DEFAULT_PRIO); tracecmd_put_tracing_file(path); @@ -2463,6 +2493,9 @@ static void expand_event_instance(struct buffer_instance *instance) struct event_list *compressed_list = instance->events; struct event_list *event; + if (instance->flags & BUFFER_FL_GUEST) + return; + reset_event_list(instance); while (compressed_list) { @@ -3336,6 +3369,9 @@ static void set_funcs(struct buffer_instance *instance) int set_notrace = 0; int ret; + if (instance->flags & BUFFER_FL_GUEST) + return; + ret = write_func_file(instance, "set_ftrace_filter", &instance->filter_funcs); if (ret < 0) die("set_ftrace_filter does not exist. Can not filter functions"); @@ -3632,6 +3668,9 @@ static void set_buffer_size_instance(struct buffer_instance *instance) int ret; int fd; + if (instance->flags & BUFFER_FL_GUEST) + return; + if (!buffer_size) return; @@ -3829,6 +3868,9 @@ static void make_instances(void) int ret; for_each_instance(instance) { + if (instance->flags & BUFFER_FL_GUEST) + continue; + path = get_instance_dir(instance); ret = stat(path, &st); if (ret < 0) { @@ -3850,7 +3892,7 @@ void tracecmd_remove_instances(void) for_each_instance(instance) { /* Only delete what we created */ - if (instance->flags & BUFFER_FL_KEEP) + if (instance->flags & (BUFFER_FL_KEEP | BUFFER_FL_GUEST)) continue; if (instance->tracing_on_fd > 0) { close(instance->tracing_on_fd); @@ -3932,7 +3974,7 @@ static void check_function_plugin(void) static int __check_doing_something(struct buffer_instance *instance) { - return (instance->flags & BUFFER_FL_PROFILE) || + return (instance->flags & (BUFFER_FL_PROFILE | BUFFER_FL_GUEST)) || instance->plugin || instance->events; } @@ -3954,6 +3996,9 @@ update_plugin_instance(struct buffer_instance *instance, { const char *plugin = instance->plugin; + if (instance->flags & BUFFER_FL_GUEST) + return; + if (!plugin) return; @@ -4053,6 +4098,9 @@ static void record_stats(void) int cpu; for_all_instances(instance) { + if (instance->flags & BUFFER_FL_GUEST) + continue; + s_save = instance->s_save; s_print = instance->s_print; for (cpu = 0; cpu < instance->cpu_count; cpu++) { @@ -4079,6 +4127,9 @@ static void destroy_stats(void) int cpu; for_all_instances(instance) { + if (instance->flags & BUFFER_FL_GUEST) + continue; + for (cpu = 0; cpu < instance->cpu_count; cpu++) { trace_seq_destroy(&instance->s_save[cpu]); trace_seq_destroy(&instance->s_print[cpu]); From patchwork Wed Jan 16 13:43:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10765999 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ACDAC1580 for ; Wed, 16 Jan 2019 13:43:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 997852E107 for ; Wed, 16 Jan 2019 13:43:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8DB492E141; Wed, 16 Jan 2019 13:43:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 896A82E035 for ; Wed, 16 Jan 2019 13:43:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2393238AbfAPNnd (ORCPT ); Wed, 16 Jan 2019 08:43:33 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:56156 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733175AbfAPNnd (ORCPT ); Wed, 16 Jan 2019 08:43:33 -0500 Received: by mail-wm1-f67.google.com with SMTP id y139so2002666wmc.5 for ; Wed, 16 Jan 2019 05:43:29 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LGkGftOVMglb3sz/hGOIkx/Eu8wnF3MG3DaMbjKKtIE=; b=q0boTdmBsWl8GeXwuKnNKPI8B1t98sM4UL+IzYX1LrxTVTs191guLFbxtR1A7UTUkJ sAn8KBVfAqOR0T4K58CyOS6kGGPBWVUeSAiF5+hcJFLzsMA+tcueB4894tps0OVNE2MD dUyvNGTbCXx3MfhwX0IkXPJ1JSRTjndaVdt45OV4Z/J75iTG4HVXCP3egk0iryTuYa/L kz1MOSwLMAR5KegTJe1kIRDBWlCJhuzfJo167ATwYW9PV9AKJfVEtHuNPF4cpIXRrr7+ 0yLG2L4kfPzVKMRTcryQNl7TkCQSlN8B45ayRmM3Mr0off1S3AWw+Rsbe9LbCgvU5MEP 3hvQ== X-Gm-Message-State: AJcUukf/Wf8a6nSPPgreWTF7p/eS2xLQMa1Gfpr/aHNea0nInZk11Eil 7+6T1taMawFafuzAceO2yslY34J67w== X-Google-Smtp-Source: ALg8bN4EgftgYXy7EEPmmf1hZH9ZtfWTOJ/w2O2p/9POeLltJqbPgD5rYXbgKc5VTcFGfawIowsa7A== X-Received: by 2002:a1c:2884:: with SMTP id o126mr7939354wmo.17.1547646207746; Wed, 16 Jan 2019 05:43:27 -0800 (PST) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y13sm34636460wme.2.2019.01.16.05.43.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 05:43:26 -0800 (PST) From: Slavomir Kaslev To: linux-trace-devel@vger.kernel.org Cc: rostedt@goodmis.org, ykaradzhov@vmware.com, tstoyanov@vmware.com Subject: [PATCH v4 7/8] trace-cmd: Add VM kernel tracing over vsock sockets transport Date: Wed, 16 Jan 2019 15:43:06 +0200 Message-Id: <20190116134307.4185-8-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190116134307.4185-1-kaslevs@vmware.com> References: <20190116134307.4185-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP To test, start a VM and assign it a valid (> 2) unused CID: you@host # qemu-system-x86_64 \ -name guest2 --uuid 7edfdf4a-cb9e-11e8-b38a-173b58342476 \ -m 4096 -boot d -enable-kvm -smp 3 -net nic -net user -hda $HOME/vm/guest2.img \ -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 and start `trace-cmd agent` on the guest as root: you@guest2 # trace-cmd agent Finally, start `trace-cmd record` on the host (running as root is only necessary if the host will be traced too): you@host $ trace-cmd record -A guest2 -e irq -e sched Co-developed-by: Tzvetomir Stoyanov Signed-off-by: Tzvetomir Stoyanov Signed-off-by: Slavomir Kaslev --- tracecmd/Makefile | 6 +- tracecmd/include/trace-local.h | 16 + tracecmd/trace-agent.c | 230 +++++++++++++ tracecmd/trace-cmd.c | 3 + tracecmd/trace-record.c | 606 ++++++++++++++++++++++++++++++--- tracecmd/trace-usage.c | 13 +- 6 files changed, 822 insertions(+), 52 deletions(-) create mode 100644 tracecmd/trace-agent.c diff --git a/tracecmd/Makefile b/tracecmd/Makefile index 3a11024..865b1c6 100644 --- a/tracecmd/Makefile +++ b/tracecmd/Makefile @@ -33,13 +33,17 @@ TRACE_CMD_OBJS += trace-output.o TRACE_CMD_OBJS += trace-usage.o TRACE_CMD_OBJS += trace-msg.o +ifeq ($(VSOCK_DEFINED), 1) +TRACE_CMD_OBJS += trace-agent.o +endif + ALL_OBJS := $(TRACE_CMD_OBJS:%.o=$(bdir)/%.o) all_objs := $(sort $(ALL_OBJS)) all_deps := $(all_objs:$(bdir)/%.o=$(bdir)/.%.d) CONFIG_INCLUDES = -CONFIG_LIBS = +CONFIG_LIBS = -lrt CONFIG_FLAGS = all: $(TARGETS) diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index f19c8bb..823d323 100644 --- a/tracecmd/include/trace-local.h +++ b/tracecmd/include/trace-local.h @@ -12,6 +12,8 @@ #include "trace-cmd.h" #include "event-utils.h" +#define TRACE_AGENT_DEFAULT_PORT 823 + extern int debug; extern int quiet; @@ -64,6 +66,8 @@ void trace_split(int argc, char **argv); void trace_listen(int argc, char **argv); +void trace_agent(int argc, char **argv); + void trace_restore(int argc, char **argv); void trace_clear(int argc, char **argv); @@ -88,6 +92,10 @@ void trace_list(int argc, char **argv); void trace_usage(int argc, char **argv); +int trace_record_agent(struct tracecmd_msg_handle *msg_handle, + int cpus, int *fds, + int argc, char **argv); + struct hook_list; void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hooks, @@ -176,6 +184,7 @@ struct buffer_instance { struct func_list *notrace_funcs; const char *clock; + unsigned int *client_ports; struct trace_seq *s_save; struct trace_seq *s_print; @@ -190,6 +199,13 @@ struct buffer_instance { int tracing_on_fd; int buffer_size; int cpu_count; + + int argc; + char **argv; + + int cid; + int port; + int *fds; }; extern struct buffer_instance top_instance; diff --git a/tracecmd/trace-agent.c b/tracecmd/trace-agent.c new file mode 100644 index 0000000..3ccf396 --- /dev/null +++ b/tracecmd/trace-agent.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2018 VMware Inc, Slavomir Kaslev + * + * based on prior implementation by Yoshihiro Yunomae + * Copyright (C) 2013 Hitachi, Ltd. + * Yoshihiro YUNOMAE + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "trace-local.h" +#include "trace-msg.h" + +static int make_vsock(unsigned int port) +{ + struct sockaddr_vm addr = { + .svm_family = AF_VSOCK, + .svm_cid = VMADDR_CID_ANY, + .svm_port = port, + }; + int sd; + + sd = socket(AF_VSOCK, SOCK_STREAM, 0); + if (sd < 0) + return -1; + + setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); + + if (bind(sd, (struct sockaddr *)&addr, sizeof(addr))) + return -1; + + if (listen(sd, SOMAXCONN)) + return -1; + + return sd; +} + +static int get_vsock_port(int sd, unsigned int *port) +{ + struct sockaddr_vm addr; + socklen_t addr_len = sizeof(addr); + + if (getsockname(sd, (struct sockaddr *)&addr, &addr_len)) + return -1; + + if (addr.svm_family != AF_VSOCK) + return -1; + + if (port) + *port = addr.svm_port; + return 0; +} + +static void make_vsocks(int nr, int **fds, unsigned int **ports) +{ + unsigned int port; + int i, fd, ret; + + *fds = calloc(nr, sizeof(*fds)); + *ports = calloc(nr, sizeof(*ports)); + if (!*fds || !*ports) + die("Failed to allocate memory"); + + for (i = 0; i < nr; i++) { + fd = make_vsock(VMADDR_PORT_ANY); + if (fd < 0) + die("Failed to open vsock socket"); + + ret = get_vsock_port(fd, &port); + if (ret < 0) + die("Failed to get vsock socket address"); + + (*fds)[i] = fd; + (*ports)[i] = port; + } +} + +static void free_vsocks(int nr, int *fds, unsigned int *ports) +{ + int i; + + for (i = 0; i < nr; i++) + close(fds[i]); + free(fds); + free(ports); +} + +static void agent_handle(int sd, int nr_cpus, int page_size) +{ + struct tracecmd_msg_handle *msg_handle; + int *fds; + unsigned int *ports; + char **argv = NULL; + int argc = 0; + + msg_handle = tracecmd_msg_handle_alloc(sd, TRACECMD_MSG_FL_CLIENT); + if (!msg_handle) + die("Failed to allocate message handle"); + + if (tracecmd_msg_recv_trace_req(msg_handle, &argc, &argv)) + die("Failed to receive trace request"); + + make_vsocks(nr_cpus, &fds, &ports); + + if (tracecmd_msg_send_trace_resp(msg_handle, nr_cpus, page_size, ports)) + die("Failed to send trace response"); + + trace_record_agent(msg_handle, nr_cpus, fds, argc, argv); + + free_vsocks(nr_cpus, fds, ports); + free(argv[0]); + free(argv); + tracecmd_msg_handle_close(msg_handle); + exit(0); +} + +static volatile pid_t handler_pid; + +static void handle_sigchld(int sig) +{ + int wstatus; + pid_t pid; + + for (;;) { + pid = waitpid(-1, &wstatus, WNOHANG); + if (pid <= 0) + break; + + if (pid == handler_pid) + handler_pid = 0; + } +} + +static void agent_serve(unsigned int port) +{ + int sd, cd, nr_cpus; + pid_t pid; + + signal(SIGCHLD, handle_sigchld); + + nr_cpus = count_cpus(); + page_size = getpagesize(); + + sd = make_vsock(port); + if (sd < 0) + die("Failed to open vsock socket"); + + for (;;) { + cd = accept(sd, NULL, NULL); + if (cd < 0) { + if (errno == EINTR) + continue; + die("accept"); + } + + if (handler_pid) + goto busy; + + pid = fork(); + if (pid == 0) { + close(sd); + signal(SIGCHLD, SIG_DFL); + agent_handle(cd, nr_cpus, page_size); + } + if (pid > 0) + handler_pid = pid; + +busy: + close(cd); + } +} + +void trace_agent(int argc, char **argv) +{ + bool do_daemon = false; + unsigned int port = TRACE_AGENT_DEFAULT_PORT; + + if (argc < 2) + usage(argv); + + if (strcmp(argv[1], "agent") != 0) + usage(argv); + + for (;;) { + int c, option_index = 0; + static struct option long_options[] = { + {"port", required_argument, NULL, 'p'}, + {"help", no_argument, NULL, '?'}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long(argc-1, argv+1, "+hp:D", + long_options, &option_index); + if (c == -1) + break; + switch (c) { + case 'h': + usage(argv); + break; + case 'p': + port = atoi(optarg); + break; + case 'D': + do_daemon = true; + break; + default: + usage(argv); + } + } + + if ((argc - optind) >= 2) + usage(argv); + + if (do_daemon && daemon(1, 0)) + die("daemon"); + + agent_serve(port); +} diff --git a/tracecmd/trace-cmd.c b/tracecmd/trace-cmd.c index 797b303..3ae5e2e 100644 --- a/tracecmd/trace-cmd.c +++ b/tracecmd/trace-cmd.c @@ -83,6 +83,9 @@ struct command commands[] = { {"hist", trace_hist}, {"mem", trace_mem}, {"listen", trace_listen}, +#ifdef VSOCK + {"agent", trace_agent}, +#endif {"split", trace_split}, {"restore", trace_restore}, {"stack", trace_stack}, diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index b911c34..1622b5e 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -33,6 +33,9 @@ #include #include #include +#ifdef VSOCK +#include +#endif #include "trace-local.h" #include "trace-msg.h" @@ -74,8 +77,6 @@ static int buffers; static int clear_function_filters; static char *host; -static unsigned int *client_ports; -static int sfd; /* Max size to let a per cpu file get */ static int max_kb; @@ -518,6 +519,22 @@ static char *get_temp_file(struct buffer_instance *instance, int cpu) return file; } +static char *get_guest_file(const char *file, const char *guest) +{ + const char *p; + char *out = NULL; + int base_len; + + p = strrchr(file, '.'); + if (p && p != file) + base_len = p - file; + else + base_len = strlen(file); + + asprintf(&out, "%.*s-%s%s", base_len, file, guest, file + base_len); + return out; +} + static void put_temp_file(char *file) { free(file); @@ -623,6 +640,18 @@ static void delete_thread_data(void) } } +static void tell_guests_to_stop(void) +{ + struct buffer_instance *instance; + + for_all_instances(instance) { + if (instance->flags & BUFFER_FL_GUEST) { + tracecmd_msg_send_close_msg(instance->msg_handle); + tracecmd_msg_handle_close(instance->msg_handle); + } + } +} + static void stop_threads(enum trace_type type) { struct timeval tv = { 0, 0 }; @@ -632,6 +661,8 @@ static void stop_threads(enum trace_type type) if (!recorder_threads) return; + tell_guests_to_stop(); + /* Tell all threads to finish up */ for (i = 0; i < recorder_threads; i++) { if (pids[i].pid > 0) { @@ -2571,14 +2602,14 @@ static void flush(int sig) tracecmd_stop_recording(recorder); } -static void connect_port(int cpu) +static int connect_port(const char *host, unsigned int port) { struct addrinfo hints; struct addrinfo *results, *rp; - int s; + int s, sfd; char buf[BUFSIZ]; - snprintf(buf, BUFSIZ, "%u", client_ports[cpu]); + snprintf(buf, BUFSIZ, "%u", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -2605,7 +2636,190 @@ static void connect_port(int cpu) freeaddrinfo(results); - client_ports[cpu] = sfd; + return sfd; +} + +#ifdef VSOCK +static int open_vsock(unsigned int cid, unsigned int port) +{ + struct sockaddr_vm addr = { + .svm_family = AF_VSOCK, + .svm_cid = cid, + .svm_port = port, + }; + int sd; + + sd = socket(AF_VSOCK, SOCK_STREAM, 0); + if (sd < 0) + return -1; + + if (connect(sd, (struct sockaddr *)&addr, sizeof(addr))) + return -1; + + return sd; +} +#else +static inline int open_vsock(unsigned int cid, unsigned int port) +{ + die("vsock is not supported"); + return -1; +} +#endif + +static int do_accept(int sd) +{ + int cd; + + for (;;) { + cd = accept(sd, NULL, NULL); + if (cd < 0) { + if (errno == EINTR) + continue; + die("accept"); + } + + return cd; + } + + return -1; +} + +static bool is_digits(const char *s) +{ + const char *p; + + for (p = s; *p; p++) + if (!isdigit(*p)) + return false; + + return true; +} + +struct guest { + char *name; + int cid; + int pid; +}; + +static struct guest *guests; +static size_t guests_len; + +static char *get_qemu_guest_name(char *arg) +{ + char *tok, *end = arg; + + while ((tok = strsep(&end, ","))) { + if (strncmp(tok, "guest=", 6) == 0) + return tok + 6; + } + + return arg; +} + +static void read_qemu_guests(void) +{ + static bool initialized; + struct dirent *entry; + char path[PATH_MAX]; + DIR *dir; + + if (initialized) + return; + + initialized = true; + dir = opendir("/proc"); + if (!dir) + die("opendir"); + + for (entry = readdir(dir); entry; entry = readdir(dir)) { + bool is_qemu = false, last_was_name = false; + struct guest guest = {}; + char *p, *arg = NULL; + size_t arg_size = 0; + FILE *f; + + if (!(entry->d_type == DT_DIR && is_digits(entry->d_name))) + continue; + + guest.pid = atoi(entry->d_name); + snprintf(path, sizeof(path), "/proc/%s/cmdline", entry->d_name); + f = fopen(path, "r"); + if (!f) + continue; + + while (getdelim(&arg, &arg_size, 0, f) != -1) { + if (!is_qemu && strstr(arg, "qemu-system-")) { + is_qemu = true; + continue; + } + + if (!is_qemu) + continue; + + if (strcmp(arg, "-name") == 0) { + last_was_name = true; + continue; + } + + if (last_was_name) { + guest.name = strdup(get_qemu_guest_name(arg)); + last_was_name = false; + continue; + } + + p = strstr(arg, "guest-cid="); + if (p) { + guest.cid = atoi(p + 10); + continue; + } + } + + if (!is_qemu) + goto next; + + guests = realloc(guests, (guests_len + 1) * sizeof(*guests)); + if (!guests) + die("Can not allocate guest buffer"); + guests[guests_len++] = guest; + +next: + free(arg); + fclose(f); + } + + closedir(dir); +} + +static char *parse_guest_name(char *guest, int *cid, int *port) +{ + size_t i; + char *p; + + *port = -1; + p = strrchr(guest, ':'); + if (p) { + *p = '\0'; + *port = atoi(p + 1); + } + + *cid = -1; + p = strrchr(guest, '@'); + if (p) { + *p = '\0'; + *cid = atoi(p + 1); + } else if (is_digits(guest)) + *cid = atoi(guest); + + read_qemu_guests(); + for (i = 0; i < guests_len; i++) { + if ((*cid > 0 && *cid == guests[i].cid) || + strcmp(guest, guests[i].name) == 0) { + *cid = guests[i].cid; + return guests[i].name; + } + } + + return guest; } static void set_prio(int prio) @@ -2652,6 +2866,17 @@ create_recorder_instance(struct buffer_instance *instance, const char *file, int struct tracecmd_recorder *record; char *path; + if (instance->flags & BUFFER_FL_GUEST) { + int sd; + + sd = open_vsock(instance->cid, instance->client_ports[cpu]); + if (sd < 0) + die("Failed to connect to agent"); + + return tracecmd_create_recorder_virt( + file, cpu, recorder_flags | TRACECMD_RECORD_NOSPLICE, sd); + } + if (brass) return create_recorder_instance_pipe(instance, cpu, brass); @@ -2676,7 +2901,7 @@ static int create_recorder(struct buffer_instance *instance, int cpu, { long ret; char *file; - int pid; + pid_t pid; if (type != TRACE_TYPE_EXTRACT) { signal(SIGUSR1, flush); @@ -2695,19 +2920,26 @@ static int create_recorder(struct buffer_instance *instance, int cpu, instance->cpu_count = 0; } - if (client_ports) { - char *path; + if ((instance->client_ports && !(instance->flags & BUFFER_FL_GUEST)) || + (instance->flags & BUFFER_FL_AGENT)) { + unsigned int flags = recorder_flags; + char *path = NULL; + int fd; - connect_port(cpu); - if (instance->name) + if (instance->flags & BUFFER_FL_AGENT) { + fd = do_accept(instance->fds[cpu]); + flags |= TRACECMD_RECORD_NOSPLICE; + } else { + fd = connect_port(host, instance->client_ports[cpu]); + } + if (fd < 0) + die("Failed connecting to client"); + if (instance->name && !(instance->flags & BUFFER_FL_AGENT)) path = get_instance_dir(instance); else path = tracecmd_find_tracing_dir(); - recorder = tracecmd_create_buffer_recorder_fd(client_ports[cpu], - cpu, recorder_flags, - path); - if (instance->name) - tracecmd_put_tracing_file(path); + recorder = tracecmd_create_buffer_recorder_fd(fd, cpu, flags, path); + tracecmd_put_tracing_file(path); } else { file = get_temp_file(instance, cpu); recorder = create_recorder_instance(instance, file, cpu, brass); @@ -2745,7 +2977,8 @@ static void check_first_msg_from_server(struct tracecmd_msg_handle *msg_handle) die("server not tracecmd server"); } -static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle) +static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle, + unsigned int **client_ports) { char buf[BUFSIZ]; ssize_t n; @@ -2788,8 +3021,8 @@ static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle) /* No options */ write(msg_handle->fd, "0", 2); - client_ports = malloc(local_cpu_count * sizeof(*client_ports)); - if (!client_ports) + *client_ports = malloc(local_cpu_count * sizeof(*client_ports)); + if (!*client_ports) die("Failed to allocate client ports for %d cpus", local_cpu_count); /* @@ -2807,13 +3040,14 @@ static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle) if (i == BUFSIZ) die("read bad port number"); buf[i] = 0; - client_ports[cpu] = atoi(buf); + (*client_ports)[cpu] = atoi(buf); } } -static void communicate_with_listener_v3(struct tracecmd_msg_handle *msg_handle) +static void communicate_with_listener_v3(struct tracecmd_msg_handle *msg_handle, + unsigned int **client_ports) { - if (tracecmd_msg_send_init_data(msg_handle, &client_ports) < 0) + if (tracecmd_msg_send_init_data(msg_handle, client_ports) < 0) die("Cannot communicate with server"); } @@ -2864,7 +3098,7 @@ static void check_protocol_version(struct tracecmd_msg_handle *msg_handle) } } -static struct tracecmd_msg_handle *setup_network(void) +static struct tracecmd_msg_handle *setup_network(struct buffer_instance *instance) { struct tracecmd_msg_handle *msg_handle = NULL; struct addrinfo hints; @@ -2934,11 +3168,11 @@ again: close(sfd); goto again; } - communicate_with_listener_v3(msg_handle); + communicate_with_listener_v3(msg_handle, &instance->client_ports); } if (msg_handle->version == V1_PROTOCOL) - communicate_with_listener_v1(msg_handle); + communicate_with_listener_v1(msg_handle, &instance->client_ports); return msg_handle; } @@ -2951,7 +3185,7 @@ setup_connection(struct buffer_instance *instance, struct common_record_context struct tracecmd_msg_handle *msg_handle; struct tracecmd_output *network_handle; - msg_handle = setup_network(); + msg_handle = setup_network(instance); /* Now create the handle through this socket */ if (msg_handle->version == V3_PROTOCOL) { @@ -2978,28 +3212,97 @@ static void finish_network(struct tracecmd_msg_handle *msg_handle) free(host); } +static void connect_to_agent(struct buffer_instance *instance) +{ + struct tracecmd_msg_handle *msg_handle; + int sd, nr_cpus, page_size; + unsigned int *ports; + + sd = open_vsock(instance->cid, instance->port); + if (sd < 0) + die("Failed to connect to vsock socket @%d:%d", + instance->cid, instance->port); + + msg_handle = tracecmd_msg_handle_alloc(sd, TRACECMD_MSG_FL_CLIENT); + if (!msg_handle) + die("Failed to allocate message handle"); + + if (tracecmd_msg_send_trace_req(msg_handle, instance->argc, instance->argv)) + die("Failed to send trace request"); + + if (tracecmd_msg_recv_trace_resp(msg_handle, &nr_cpus, &page_size, &ports)) + die("Failed to receive trace response"); + + instance->client_ports = ports; + instance->cpu_count = nr_cpus; + + /* the msg_handle now points to the guest fd */ + instance->msg_handle = msg_handle; +} + +static void setup_guest(struct buffer_instance *instance) +{ + struct tracecmd_msg_handle *msg_handle = instance->msg_handle; + char *file; + int fd; + + /* Create a place to store the guest meta data */ + file = get_guest_file(output_file, instance->name); + if (!file) + die("Failed to allocate memory"); + + fd = open(file, O_CREAT|O_WRONLY|O_TRUNC, 0644); + put_temp_file(file); + if (fd < 0) + die("Failed to open", file); + + /* Start reading tracing metadata */ + if (tracecmd_msg_read_data(msg_handle, fd)) + die("Failed receiving metadata"); + close(fd); +} + +static void setup_agent(struct buffer_instance *instance, struct common_record_context *ctx) +{ + struct tracecmd_output *network_handle; + + network_handle = tracecmd_create_init_fd_msg(instance->msg_handle, + listed_events); + add_options(network_handle, ctx); + tracecmd_write_cpus(network_handle, instance->cpu_count); + tracecmd_write_options(network_handle); + tracecmd_msg_finish_sending_data(instance->msg_handle); + instance->network_handle = network_handle; +} + void start_threads(enum trace_type type, struct common_record_context *ctx) { struct buffer_instance *instance; - int *brass = NULL; int total_cpu_count = 0; int i = 0; int ret; - for_all_instances(instance) + for_all_instances(instance) { + /* Start the connection now to find out how many CPUs we need */ + if (instance->flags & BUFFER_FL_GUEST) + connect_to_agent(instance); total_cpu_count += instance->cpu_count; + } /* make a thread for every CPU we have */ - pids = malloc(sizeof(*pids) * total_cpu_count * (buffers + 1)); + pids = calloc(total_cpu_count * (buffers + 1), sizeof(*pids)); if (!pids) - die("Failed to allocat pids for %d cpus", total_cpu_count); - - memset(pids, 0, sizeof(*pids) * total_cpu_count * (buffers + 1)); + die("Failed to allocate pids for %d cpus", total_cpu_count); for_all_instances(instance) { + int *brass = NULL; int x, pid; - if (host) { + if (instance->flags & BUFFER_FL_AGENT) { + setup_agent(instance, ctx); + } else if (instance->flags & BUFFER_FL_GUEST) { + setup_guest(instance); + } else if (host) { instance->msg_handle = setup_connection(instance, ctx); if (!instance->msg_handle) die("Failed to make connection"); @@ -3139,13 +3442,14 @@ static void print_stat(struct buffer_instance *instance) { int cpu; + if (quiet) + return; + if (!is_top_instance(instance)) - if (!quiet) - printf("\nBuffer: %s\n\n", instance->name); + printf("\nBuffer: %s\n\n", instance->name); for (cpu = 0; cpu < instance->cpu_count; cpu++) - if (!quiet) - trace_seq_do_printf(&instance->s_print[cpu]); + trace_seq_do_printf(&instance->s_print[cpu]); } enum { @@ -3171,7 +3475,44 @@ static void add_options(struct tracecmd_output *handle, struct common_record_con tracecmd_add_option(handle, TRACECMD_OPTION_TRACECLOCK, 0, NULL); add_option_hooks(handle); add_uname(handle); +} + +static void write_guest_file(struct buffer_instance *instance) +{ + struct tracecmd_output *handle; + int cpu_count = instance->cpu_count; + char *file; + char **temp_files; + int i, fd; + + file = get_guest_file(output_file, instance->name); + fd = open(file, O_RDWR); + if (fd < 0) + die("error opening %s", file); + put_temp_file(file); + + handle = tracecmd_get_output_handle_fd(fd); + if (!handle) + die("error writing to %s", file); + + temp_files = malloc(sizeof(*temp_files) * cpu_count); + if (!temp_files) + die("failed to allocate temp_files for %d cpus", + cpu_count); + for (i = 0; i < cpu_count; i++) { + temp_files[i] = get_temp_file(instance, i); + if (!temp_files[i]) + die("failed to allocate memory"); + } + + if (tracecmd_write_cpu_data(handle, cpu_count, temp_files) < 0) + die("failed to write CPU data"); + tracecmd_output_close(handle); + + for (i = 0; i < cpu_count; i++) + put_temp_file(temp_files[i]); + free(temp_files); } static void record_data(struct common_record_context *ctx) @@ -3185,7 +3526,9 @@ static void record_data(struct common_record_context *ctx) int i; for_all_instances(instance) { - if (instance->msg_handle) + if (instance->flags & BUFFER_FL_GUEST) + write_guest_file(instance); + else if (host && instance->msg_handle) finish_network(instance->msg_handle); else local = true; @@ -4404,6 +4747,7 @@ void trace_stop(int argc, char **argv) c = getopt(argc-1, argv+1, "hatB:"); if (c == -1) break; + switch (c) { case 'h': usage(argv); @@ -4566,6 +4910,63 @@ static void init_common_record_context(struct common_record_context *ctx, #define IS_STREAM(ctx) ((ctx)->curr_cmd == CMD_stream) #define IS_PROFILE(ctx) ((ctx)->curr_cmd == CMD_profile) #define IS_RECORD(ctx) ((ctx)->curr_cmd == CMD_record) +#define IS_AGENT(ctx) ((ctx)->curr_cmd == CMD_record_agent) + +static void add_argv(struct buffer_instance *instance, char *arg, bool prepend) +{ + instance->argv = realloc(instance->argv, + (instance->argc + 1) * sizeof(char *)); + if (!instance->argv) + die("Can not allocate instance args"); + if (prepend) { + memmove(instance->argv + 1, instance->argv, + instance->argc * sizeof(*instance->argv)); + instance->argv[0] = arg; + } else { + instance->argv[instance->argc] = arg; + } + instance->argc++; +} + +static void add_arg(struct buffer_instance *instance, + int c, const char *opts, + struct option *long_options, char *optarg) +{ + char *ptr; + char *arg; + int ret; + int i; + + /* Short or long arg */ + if (!(c & 0x80)) { + ret = asprintf(&arg, "-%c", c); + if (ret < 0) + die("Can not allocate argument"); + ptr = strstr(opts, arg+1); + if (!ptr) + return; /* Not found? */ + add_argv(instance, arg, false); + if (ptr[1] == ':') + add_argv(instance, optarg, false); + return; + } + for (i = 0; long_options[i].name; i++) { + if (c == long_options[i].val) { + ret = asprintf(&arg, "--%s", long_options[i].name); + if (ret < 0) + die("Can not allocate argument"); + add_argv(instance, arg, false); + if (long_options[i].has_arg) { + arg = strdup(optarg); + if (!arg) + die("Can not allocate arguments"); + add_argv(instance, arg, false); + return; + } + } + } + /* Not found? */ +} static void parse_record_options(int argc, char **argv, @@ -4607,10 +5008,20 @@ static void parse_record_options(int argc, if (IS_EXTRACT(ctx)) opts = "+haf:Fp:co:O:sr:g:l:n:P:N:tb:B:ksiT"; else - opts = "+hae:f:Fp:cC:dDGo:O:s:r:vg:l:n:P:N:tb:R:B:ksSiTm:M:H:q"; + opts = "+hae:f:FA:p:cC:dDGo:O:s:r:vg:l:n:P:N:tb:R:B:ksSiTm:M:H:q"; c = getopt_long (argc-1, argv+1, opts, long_options, &option_index); if (c == -1) break; + + /* + * If the current instance is to record a guest, then save + * all the arguments for this instance. + */ + if (c != 'B' && c != 'A' && ctx->instance->flags & BUFFER_FL_GUEST) { + add_arg(ctx->instance, c, opts, long_options, optarg); + continue; + } + switch (c) { case 'h': usage(argv); @@ -4663,6 +5074,26 @@ static void parse_record_options(int argc, add_trigger(event, optarg); break; + case 'A': { + char *name = NULL; + int cid = -1, port = -1; + + if (!IS_RECORD(ctx)) + die("-A is only allowed for record operations"); + + name = parse_guest_name(optarg, &cid, &port); + if (!name || cid == -1) + die("guest %s not found", optarg); + if (port == -1) + port = TRACE_AGENT_DEFAULT_PORT; + + ctx->instance = create_instance(name); + ctx->instance->flags |= BUFFER_FL_GUEST; + ctx->instance->cid = cid; + ctx->instance->port = port; + add_instance(ctx->instance, 0); + break; + } case 'F': test_set_event_pid(); filter_task = 1; @@ -4733,6 +5164,8 @@ static void parse_record_options(int argc, ctx->disable = 1; break; case 'o': + if (IS_AGENT(ctx)) + die("-o incompatible with agent recording"); if (host) die("-o incompatible with -N"); if (IS_START(ctx)) @@ -4794,6 +5227,8 @@ static void parse_record_options(int argc, case 'N': if (!IS_RECORD(ctx)) die("-N only available with record"); + if (IS_AGENT(ctx)) + die("-N incompatible with agent recording"); if (ctx->output) die("-N incompatible with -o"); host = optarg; @@ -4890,6 +5325,16 @@ static void parse_record_options(int argc, } } + /* If --date is specified, prepend it to all guest VM flags */ + if (ctx->date) { + struct buffer_instance *instance; + + for_all_instances(instance) { + if (instance->flags & BUFFER_FL_GUEST) + add_argv(instance, "--date", true); + } + } + if (!ctx->filtered && ctx->instance->filter_mod) add_func(&ctx->instance->filter_funcs, ctx->instance->filter_mod, "*"); @@ -4920,7 +5365,8 @@ static enum trace_type get_trace_cmd_type(enum trace_cmd cmd) {CMD_stream, TRACE_TYPE_STREAM}, {CMD_extract, TRACE_TYPE_EXTRACT}, {CMD_profile, TRACE_TYPE_STREAM}, - {CMD_start, TRACE_TYPE_START} + {CMD_start, TRACE_TYPE_START}, + {CMD_record_agent, TRACE_TYPE_RECORD} }; for (int i = 0; i < ARRAY_SIZE(trace_type_per_command); i++) { @@ -4952,12 +5398,28 @@ static void finalize_record_trace(struct common_record_context *ctx) if (instance->flags & BUFFER_FL_KEEP) write_tracing_on(instance, instance->tracing_on_init_val); + if (instance->flags & BUFFER_FL_AGENT) + tracecmd_output_close(instance->network_handle); } if (host) tracecmd_output_close(ctx->instance->network_handle); } +static bool has_local_instances(void) +{ + struct buffer_instance *instance; + + for_all_instances(instance) { + if (instance->flags & BUFFER_FL_GUEST) + continue; + if (host && instance->msg_handle) + continue; + return true; + } + return false; +} + /* * This function contains common code for the following commands: * record, start, stream, profile. @@ -4986,7 +5448,6 @@ static void record_trace(int argc, char **argv, /* Save the state of tracing_on before starting */ for_all_instances(instance) { - if (!ctx->manual && instance->flags & BUFFER_FL_PROFILE) enable_profile(instance); @@ -5003,14 +5464,16 @@ static void record_trace(int argc, char **argv, page_size = getpagesize(); - fset = set_ftrace(!ctx->disable, ctx->total_disable); + if (!(ctx->instance->flags & BUFFER_FL_GUEST)) + fset = set_ftrace(!ctx->disable, ctx->total_disable); tracecmd_disable_all_tracing(1); for_all_instances(instance) set_clock(instance); /* Record records the date first */ - if (IS_RECORD(ctx) && ctx->date) + if (ctx->date && + ((IS_RECORD(ctx) && has_local_instances()) || IS_AGENT(ctx))) ctx->date2ts = get_date_to_ts(); for_all_instances(instance) { @@ -5045,9 +5508,13 @@ static void record_trace(int argc, char **argv, exit(0); } - if (ctx->run_command) + if (ctx->run_command) { run_cmd(type, (argc - optind) - 1, &argv[optind + 1]); - else { + } else if (ctx->instance && (ctx->instance->flags & BUFFER_FL_AGENT)) { + update_task_filter(); + tracecmd_enable_tracing(); + tracecmd_msg_wait_close(ctx->instance->msg_handle); + } else { update_task_filter(); tracecmd_enable_tracing(); /* We don't ptrace ourself */ @@ -5068,11 +5535,13 @@ static void record_trace(int argc, char **argv, if (!keep) tracecmd_disable_all_tracing(0); - if (IS_RECORD(ctx)) { - record_data(ctx); - delete_thread_data(); - } else - print_stats(); + if (!IS_AGENT(ctx)) { + if (IS_RECORD(ctx)) { + record_data(ctx); + delete_thread_data(); + } else + print_stats(); + } destroy_stats(); finalize_record_trace(ctx); @@ -5202,3 +5671,40 @@ void trace_record(int argc, char **argv) record_trace(argc, argv, &ctx); exit(0); } + +int trace_record_agent(struct tracecmd_msg_handle *msg_handle, + int cpus, int *fds, + int argc, char **argv) +{ + struct common_record_context ctx; + char **argv_plus; + + /* Reset optind for getopt_long */ + optind = 1; + /* + * argc is the number of elements in argv, but we need to convert + * argc and argv into "trace-cmd", "record", argv. + * where argc needs to grow by two. + */ + argv_plus = calloc(argc + 2, sizeof(char *)); + if (!argv_plus) + return -ENOMEM; + + argv_plus[0] = "trace-cmd"; + argv_plus[1] = "record"; + memcpy(argv_plus + 2, argv, argc * sizeof(char *)); + argc += 2; + + parse_record_options(argc, argv_plus, CMD_record_agent, &ctx); + if (ctx.run_command) + return -EINVAL; + + ctx.instance->fds = fds; + ctx.instance->flags |= BUFFER_FL_AGENT; + ctx.instance->msg_handle = msg_handle; + msg_handle->version = V3_PROTOCOL; + record_trace(argc, argv, &ctx); + + free(argv_plus); + return 0; +} diff --git a/tracecmd/trace-usage.c b/tracecmd/trace-usage.c index 9ea1906..93e85ba 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -231,11 +231,22 @@ static struct usage_help usage_help[] = { "listen on a network socket for trace clients", " %s listen -p port[-D][-o file][-d dir][-l logfile]\n" " Creates a socket to listen for clients.\n" - " -D create it in daemon mode.\n" + " -p port number to listen on.\n" + " -D run in daemon mode.\n" " -o file name to use for clients.\n" " -d directory to store client files.\n" " -l logfile to write messages to.\n" }, +#ifdef VSOCK + { + "agent", + "listen on a vsock socket for trace clients", + " %s agent -p port[-D]\n" + " Creates a vsock socket to listen for clients.\n" + " -p port number to listen on.\n" + " -D run in daemon mode.\n" + }, +#endif { "list", "list the available events, plugins or options", From patchwork Wed Jan 16 13:43:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10765997 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7F62091E for ; Wed, 16 Jan 2019 13:43:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6D44D2E084 for ; Wed, 16 Jan 2019 13:43:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6B1062E067; Wed, 16 Jan 2019 13:43:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7AF3A2E137 for ; Wed, 16 Jan 2019 13:43:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390597AbfAPNnb (ORCPT ); Wed, 16 Jan 2019 08:43:31 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:39732 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2393238AbfAPNnb (ORCPT ); Wed, 16 Jan 2019 08:43:31 -0500 Received: by mail-wm1-f65.google.com with SMTP id y8so2028685wmi.4 for ; Wed, 16 Jan 2019 05:43:29 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=O7V6rYXgz87+rMg4j9CZD+X3Wk8alHg55qvqsEDG/MY=; b=LpfowkoF4ptlu/48er9GEom8oIvGScb61ccBcMHRQDA8H6M8AgjTl/KXLcFp9XrgAi xV0fwGPON+DFvKuaw0oV3bvza3MrDeTi/lxMV4JUaNsUoYxmkUz7fYJPwX8abHrq2YW2 YJEY/eByyO4djtW8zhQJFdnOfNH2CTzbOW71HuGCy6pvUxCJHVcNuTNoyCq066ZNM2H9 qJWfAJNiYRjkpbaR4emT2B+CB12tgaWAPtUu/0Ecfg1mwNr/rvwxPKxI9eQpOnW5qqp4 fZ6MVNRxoHUr4LBdPkOPkPJBJalZ7hzxLp0+Nik/l6teCK5H81xlHgaNP7bv6U92Q13Q yGOg== X-Gm-Message-State: AJcUukeQU2EqziCQhMXeIykPKbUC3Yk+wEgwwO5BP5QfLlKSN8gxZoFA 57aInlLYJmgrNQFADde4EP/M6cKGLw== X-Google-Smtp-Source: ALg8bN6e8KVwqNmWuD2+mv6m+i9V/tPt7IIa84QhDbQHy757WAEgnxX53troWneQEumJ7MTM7XBGAw== X-Received: by 2002:a1c:570d:: with SMTP id l13mr7865560wmb.139.1547646208950; Wed, 16 Jan 2019 05:43:28 -0800 (PST) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y13sm34636460wme.2.2019.01.16.05.43.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 05:43:28 -0800 (PST) From: Slavomir Kaslev To: linux-trace-devel@vger.kernel.org Cc: rostedt@goodmis.org, ykaradzhov@vmware.com, tstoyanov@vmware.com Subject: [PATCH v4 8/8] trace-cmd: Use splice(2) for vsock sockets if available Date: Wed, 16 Jan 2019 15:43:07 +0200 Message-Id: <20190116134307.4185-9-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190116134307.4185-1-kaslevs@vmware.com> References: <20190116134307.4185-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Detect if splice(2) reading is supported for vsock sockets (Linux 4.20 and later) and use it, or fallback to read/write-ing otherwise. Signed-off-by: Slavomir Kaslev --- tracecmd/trace-record.c | 59 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 1622b5e..cd80462 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -2658,12 +2658,61 @@ static int open_vsock(unsigned int cid, unsigned int port) return sd; } + +static int try_splice_read_vsock(void) +{ + int ret, sd, brass[2]; + + sd = socket(AF_VSOCK, SOCK_STREAM, 0); + if (sd < 0) + return sd; + + ret = pipe(brass); + if (ret < 0) + goto out_close_sd; + + /* + * On kernels that don't support splice reading from vsock sockets + * this will fail with EINVAL, or ENOTCONN otherwise. + * Technically, it should never succeed but if it does, claim splice + * reading is supported. + */ + ret = splice(sd, NULL, brass[1], NULL, 10, 0); + if (ret < 0) + ret = errno != EINVAL; + else + ret = 1; + + close(brass[0]); + close(brass[1]); +out_close_sd: + close(sd); + return ret; +} + +static bool can_splice_read_vsock(void) +{ + static bool initialized, res; + + if (initialized) + return res; + + res = try_splice_read_vsock() > 0; + initialized = true; + return res; +} + #else static inline int open_vsock(unsigned int cid, unsigned int port) { die("vsock is not supported"); return -1; } + +static bool can_splice_read_vsock(void) +{ + return false; +} #endif static int do_accept(int sd) @@ -2868,13 +2917,16 @@ create_recorder_instance(struct buffer_instance *instance, const char *file, int if (instance->flags & BUFFER_FL_GUEST) { int sd; + unsigned int flags; sd = open_vsock(instance->cid, instance->client_ports[cpu]); if (sd < 0) die("Failed to connect to agent"); - return tracecmd_create_recorder_virt( - file, cpu, recorder_flags | TRACECMD_RECORD_NOSPLICE, sd); + flags = recorder_flags; + if (!can_splice_read_vsock()) + flags |= TRACECMD_RECORD_NOSPLICE; + return tracecmd_create_recorder_virt(file, cpu, flags, sd); } if (brass) @@ -2928,7 +2980,8 @@ static int create_recorder(struct buffer_instance *instance, int cpu, if (instance->flags & BUFFER_FL_AGENT) { fd = do_accept(instance->fds[cpu]); - flags |= TRACECMD_RECORD_NOSPLICE; + if (!can_splice_read_vsock()) + flags |= TRACECMD_RECORD_NOSPLICE; } else { fd = connect_port(host, instance->client_ports[cpu]); }