From patchwork Tue Jun 18 14:39:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001869 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 076521902 for ; Tue, 18 Jun 2019 14:40:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EAF5028470 for ; Tue, 18 Jun 2019 14:40:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DEFAD2847D; Tue, 18 Jun 2019 14:40:10 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 5E4E6286DA for ; Tue, 18 Jun 2019 14:40:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729161AbfFROkK (ORCPT ); Tue, 18 Jun 2019 10:40:10 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:55282 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728572AbfFROkK (ORCPT ); Tue, 18 Jun 2019 10:40:10 -0400 Received: by mail-wm1-f68.google.com with SMTP id g135so3580077wme.4 for ; Tue, 18 Jun 2019 07:40:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=h3zHanV9Lcef9Grtff/alPeCfWAomyQ2iLYAuQfEf6c=; b=IdRbV+/y5RCFIMZxcRKdD1zG/oIrZkjeZKcqbUeT1TlYaFLbcfwsev6p7RYbhyyB62 jfY3lsSCTL9qSa1Y3R40JXNfMkyfQ8phuNA/DHVIk2Ln23KZTrPKMZBsQrTRdEHslpFD 6Hd10wBTLQ+38WEoNsYsOagF0emL/DQI9f0YqcqgjqGFvUcfo06ezpdlBvwjvaCLqNl9 gU1mT87DbDsaJy9Pl6XTTWcc5F3r04dpMhsBpXyj898JJe6zhsVD5vSJR+ohEDi1raLY iVbmIsAe+zHkd3kqpAnC9Ty/b2/1Diz9BbEvhgyppnlJeab6py/qyqg5K/YvS+Wb9R8Y gG8A== 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=h3zHanV9Lcef9Grtff/alPeCfWAomyQ2iLYAuQfEf6c=; b=bpH685thi/yTaxATsnshuAa2B5JC/tEMMpBEGpMg4zk2MuTU88Tka5maJgJI9t5YNZ 9eHPFP0Nh+hjAIsLCaqzghNRaMsUMMJy4J6Rnkz0LXUIvzqRQ5+6sxiSZxHfbhnjK4fj 0QwC+mtcSGA3ja8ND4O/ItfvWPEHNurZ58VwkHcCRvo1FdKUaOuYLl68b7hvxueKmf6z KaKFuaaAvyKnqj2UOoF3kmhhNl8azcxQwYk7UJ0rvoLozEdkhDhOQX9AVhYiGC7plvSE DlALKbRl58+M8WMp5vkRA9ullea4L20hPKO6Z/aINKah7xX0RP6v9dfNF8CxmKcFJea3 RZ1Q== X-Gm-Message-State: APjAAAXw6VD1nkNvJPRqFQ3rXQ4+NHvFugXiZj4JHV2F56tM5RFh7ya1 W91WCzycqm9ly0VGH/QIJQ== X-Google-Smtp-Source: APXvYqwPpQFpd8zCGo5AvYd2r1AjMYprcCaDQahw/IbVSztRmOFZLkuUDgX0jeGq1FZViWE56g1EJQ== X-Received: by 2002:a1c:be0a:: with SMTP id o10mr3991578wmf.91.1560868807762; Tue, 18 Jun 2019 07:40:07 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.06 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:07 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 01/13] trace-cmd: Make ports unsigned int Date: Tue, 18 Jun 2019 17:39:46 +0300 Message-Id: <20190618143958.2865-2-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev Switch ports data type to unsigned int since vsocket ports are 32 bit unsigned integers and sometimes cause overflow when stored in int variables. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- include/trace-cmd/trace-cmd.h | 2 +- tracecmd/trace-listen.c | 10 +++++----- tracecmd/trace-msg.c | 32 ++++++++++++++++++++++---------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 6f62ab9..923015e 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -328,7 +328,7 @@ int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle); /* for server */ int tracecmd_msg_initial_setting(struct tracecmd_msg_handle *msg_handle); int tracecmd_msg_send_port_array(struct tracecmd_msg_handle *msg_handle, - int *ports); + unsigned *ports); int tracecmd_msg_read_data(struct tracecmd_msg_handle *msg_handle, int ofd); int tracecmd_msg_collect_data(struct tracecmd_msg_handle *msg_handle, int ofd); bool tracecmd_msg_done(struct tracecmd_msg_handle *msg_handle); diff --git a/tracecmd/trace-listen.c b/tracecmd/trace-listen.c index 3106022..e34df08 100644 --- a/tracecmd/trace-listen.c +++ b/tracecmd/trace-listen.c @@ -517,10 +517,10 @@ static int *create_all_readers(const char *node, const char *port, { int use_tcp = msg_handle->flags & TRACECMD_MSG_FL_USE_TCP; char buf[BUFSIZ]; - int *port_array; + unsigned int *port_array; int *pid_array; - int start_port; - int udp_port; + unsigned int start_port; + unsigned int udp_port; int cpus = msg_handle->cpu_count; int cpu; int pid; @@ -528,11 +528,11 @@ static int *create_all_readers(const char *node, const char *port, if (!pagesize) return NULL; - port_array = malloc(sizeof(int) * cpus); + port_array = malloc(sizeof(*port_array) * cpus); if (!port_array) return NULL; - pid_array = malloc(sizeof(int) * cpus); + pid_array = malloc(sizeof(*pid_array) * cpus); if (!pid_array) { free(port_array); return NULL; diff --git a/tracecmd/trace-msg.c b/tracecmd/trace-msg.c index e2dd188..74c0bc1 100644 --- a/tracecmd/trace-msg.c +++ b/tracecmd/trace-msg.c @@ -161,12 +161,26 @@ static int make_tinit(struct tracecmd_msg_handle *msg_handle, return 0; } -static int write_ints(char *buf, size_t buf_len, int *arr, int arr_len) +/* test a to u */ +static int tatou(const char *s, unsigned int *res) +{ + long r; + + r = atol(s); + if (r >= 0 && r <= UINT_MAX) { + *res = (unsigned int)r; + return 0; + } + return -1; +} + +static int write_uints(char *buf, size_t buf_len, + unsigned int *arr, int arr_len) { int i, ret, tot = 0; for (i = 0; i < arr_len; i++) { - ret = snprintf(buf, buf_len, "%d", arr[i]); + ret = snprintf(buf, buf_len, "%u", arr[i]); if (ret < 0) return ret; @@ -184,15 +198,15 @@ static int write_ints(char *buf, size_t buf_len, int *arr, int arr_len) return tot; } -static int make_rinit(struct tracecmd_msg *msg, int cpus, int *ports) +static int make_rinit(struct tracecmd_msg *msg, int cpus, unsigned int *ports) { int data_size; - data_size = write_ints(NULL, 0, ports, cpus); + data_size = write_uints(NULL, 0, ports, cpus); msg->buf = malloc(data_size); if (!msg->buf) return -ENOMEM; - write_ints(msg->buf, data_size, ports, cpus); + write_uints(msg->buf, data_size, ports, cpus); msg->rinit.cpus = htonl(cpus); msg->hdr.size = htonl(ntohl(msg->hdr.size) + data_size); @@ -442,7 +456,7 @@ int tracecmd_msg_send_init_data(struct tracecmd_msg_handle *msg_handle, } cpus = ntohl(msg.rinit.cpus); - ports = malloc_or_die(sizeof(*ports) * cpus); + ports = malloc(sizeof(*ports) * cpus); if (!ports) { ret = -ENOMEM; goto out; @@ -450,13 +464,11 @@ int tracecmd_msg_send_init_data(struct tracecmd_msg_handle *msg_handle, buf_end = msg.buf + buf_len; for (i = 0, p = msg.buf; i < cpus; i++, p++) { - if (p >= buf_end) { + if (p >= buf_end || tatou(p, &ports[i])) { free(ports); ret = -EINVAL; goto error; } - - ports[i] = atoi(p); p = strchr(p, '\0'); } @@ -588,7 +600,7 @@ error: } int tracecmd_msg_send_port_array(struct tracecmd_msg_handle *msg_handle, - int *ports) + unsigned int *ports) { struct tracecmd_msg msg; int ret; From patchwork Tue Jun 18 14:39:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001871 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 622771395 for ; Tue, 18 Jun 2019 14:40:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 52CF228470 for ; Tue, 18 Jun 2019 14:40:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 475B3286DA; Tue, 18 Jun 2019 14:40:12 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 414A728470 for ; Tue, 18 Jun 2019 14:40:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729167AbfFROkL (ORCPT ); Tue, 18 Jun 2019 10:40:11 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:52960 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725919AbfFROkK (ORCPT ); Tue, 18 Jun 2019 10:40:10 -0400 Received: by mail-wm1-f67.google.com with SMTP id s3so3599374wms.2 for ; Tue, 18 Jun 2019 07:40:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=COOWTVQCpqGdT0L9mfdnyqo+LJmZ13WzicSw1A2mcT0=; b=Xv3b1WhqrI9jPo84T2PYFLsvlVdm6rliH9wPkxpvy0gOxUYw908B9P42QPt4zc856r xcCPGl7Ek2pp76r8MFaEPJ1v4xTgXwtlyXHxa/v74NHCdByMj3eXW1yq640rnRzsPtVP 3yuFAJe7RNK+VIxOESHR8kYjoFIh54Mkiy3h217UmdKlgf69ugVYujur2vjrAY1E6B16 fSXLR254U06kLNJ+SS2bYk+PyE/YPtEJtharg816kStbBdO3AMexAA4OsmnK+GtuanmV CO9Es3WS0oY3oUxgQoln85dq573WFFF5K1rdF4cbe/ab2v5UBJW1JXdHjL7Ryf14OYIP 2pzA== 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=COOWTVQCpqGdT0L9mfdnyqo+LJmZ13WzicSw1A2mcT0=; b=qG/9Wc6q12odQju/yZ1NxDL7lHHUP3Yt72gAk2+whxXIV028O8iVSVkFMjgV7wCtm5 XnmSpMBCb0gq8dqPR79EKMJdfHc9OLRmtOwmV5+82+3H2J2bXB8pnM1RWykOpWnbsGci UgKJ2ndutEYSEg1BzvW+08pdzT3Ik6CsBB9nMZoWrGn5/IxiCIvheFK3YlW9rBQKeDt1 wiF2X4esKaseQEdlC7xcsmkpiydBY2BHU5/edU4MkQngjXt1Te18TpdXdgjAzRtuVm0Q zop4jw89Sr83+XRgLbXtGQHMWbKuRC0mVXaCiANCeMI4IbofQRogyAgELz5OkhE1Bo6W IquA== X-Gm-Message-State: APjAAAXMSIt56i8e+zREeDtf+DtoOk70MIsnlZs7UhEkET4s4BU6FQly y92bfAQJPm4mTuX1rplPHnCmbfI= X-Google-Smtp-Source: APXvYqxNDN+N8ashxGlMm5HUlMEYFfSdR5kYDE3DZmuYG8u7zHEBYUyUgh4sQuGhrGXjDBko0B92pQ== X-Received: by 2002:a1c:10f:: with SMTP id 15mr4078773wmb.142.1560868808892; Tue, 18 Jun 2019 07:40:08 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.07 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:08 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 02/13] trace-cmd: Detect if vsockets are available Date: Tue, 18 Jun 2019 17:39:47 +0300 Message-Id: <20190618143958.2865-3-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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 vsockets 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 Signed-off-by: Slavomir Kaslev (VMware) --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index d34c615..ba726ee 100644 --- a/Makefile +++ b/Makefile @@ -204,6 +204,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 Tue Jun 18 14:39:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001873 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 189FA1902 for ; Tue, 18 Jun 2019 14:40:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 081A328470 for ; Tue, 18 Jun 2019 14:40:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F0941286DA; Tue, 18 Jun 2019 14:40:12 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 7BF8728470 for ; Tue, 18 Jun 2019 14:40:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729174AbfFROkM (ORCPT ); Tue, 18 Jun 2019 10:40:12 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:52964 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728572AbfFROkM (ORCPT ); Tue, 18 Jun 2019 10:40:12 -0400 Received: by mail-wm1-f67.google.com with SMTP id s3so3599520wms.2 for ; Tue, 18 Jun 2019 07:40:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hk6cusv+uK9Vs9ucOV0chmDxi5bH1nrn5N/xtNmAzhs=; b=YfyPnH9rt0gd44sMxeadDgDTKCtsNlzZeC19BSz8mhT+mQT7SJBm8CKspj1m37Sqv/ QAnBCInSzWV+CR4q5Ij5c5wCjSu6NuOmfsVRJhSFibDinrdRrFk8e7Fw9aavfdwJqiKd RpUkd+Csj7zDC9lc7Qcy13f+9EyYOkmyUlPSnivKpN1FF3CCdNX1ht0dRo1W6Blk3t2y OWGF3/NZJVOwGcRogcBRzbcihUWccwGM4FoAHJdBvXuaVVyMCboLnMaTn27m0/5VZi6H P5O+p9bxO83DdqCn2vjS1o9vgAaoTQo3GGkH04rX9dB4uRDE+vSe/CU2UII4mBg8WRRd agKA== 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=hk6cusv+uK9Vs9ucOV0chmDxi5bH1nrn5N/xtNmAzhs=; b=HHzgr+epY8GyRe6csxixdTykagZ0oVGX711QV3FwBzk2NvV7Q38TeHHtG7fn20F/6P WkO7YymqQlGdWlILFUfw8ZCjLuVPLDYpHE67+LsW4XQCOLQTDnJIG7q8EpxjBdjs3UGR 22RjSDRVpKzjCTE0szHVhI2kTSTiygOIBMn433zW6cxSYJTFEFo0bgecg9XrzDogcMkG RPitcKGCeGM0ZT5icXb+Sdc2ocm3j9NWDNLKWlJ9ornLS4bx2xLukZLHitTXh6u3Ui2V 3YVwj/yx7eLIzMxf2HSn+MfbhcDNmBR8vdjLgeDSPvGG3amCHM+GVZd02Y+0lGzt8ckN IeAg== X-Gm-Message-State: APjAAAX0QXZ+aoEH0StMC/klvN2WMnnRdfnaVR/bKWH8NWob/RWOqjY6 LrVGSVe5HlOADhadPdBXZrrdSHY= X-Google-Smtp-Source: APXvYqydp+YdzX3RshxbLe/59U8sovZuimPmOzGXDz0FPo6yZHqJ/X4774xEJL9gjjsb8dk6WE6eRA== X-Received: by 2002:a1c:3942:: with SMTP id g63mr3605832wma.61.1560868809964; Tue, 18 Jun 2019 07:40:09 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.08 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:09 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 03/13] trace-cmd: Add tracecmd_create_recorder_virt() function Date: Tue, 18 Jun 2019 17:39:48 +0300 Message-Id: <20190618143958.2865-4-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev Add tracecmd_create_recorder_virt() which creates tracecmd_recorder recording tracing data from the trace_fd parameter instead of from the local systems tracefs. It will be used for recording tracing data coming from VMs. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- include/trace-cmd/trace-cmd.h | 1 + lib/trace-cmd/trace-recorder.c | 61 +++++++++++++++++++++++++--------- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 923015e..28b5b38 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -281,6 +281,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 0bd0657..0ea7a87 100644 --- a/lib/trace-cmd/trace-recorder.c +++ b/lib/trace-cmd/trace-recorder.c @@ -154,16 +154,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); @@ -183,13 +189,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; } @@ -200,8 +202,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; @@ -264,6 +267,34 @@ 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); +} + +/** + * tracecmd_create_recorder_virt - Create a recorder reading tracing data + * from the trace_fd file descriptor instead of from the local tracefs + * @file: output filename where tracing data will be written + * @cpu: which CPU is being traced + * @flags: flags configuring the recorder (see TRACECMD_RECORDER_* enums) + * @trace_fd: file descriptor from where tracing data will be read + */ +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 Tue Jun 18 14:39:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001875 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 BFB2A14BB for ; Tue, 18 Jun 2019 14:40:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AE9F828470 for ; Tue, 18 Jun 2019 14:40:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A2C7628825; Tue, 18 Jun 2019 14:40:15 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 D117428470 for ; Tue, 18 Jun 2019 14:40:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729220AbfFROkO (ORCPT ); Tue, 18 Jun 2019 10:40:14 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:55532 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725919AbfFROkO (ORCPT ); Tue, 18 Jun 2019 10:40:14 -0400 Received: by mail-wm1-f67.google.com with SMTP id a15so3581503wmj.5 for ; Tue, 18 Jun 2019 07:40:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=zMoolKfl078lBlX2PU/tiitUWSDsEGlNd9hgMjhjn1U=; b=J2ge9WNU9fjW94NtTpyj5sH/Lo41zwemHP69GtN9aIOkBxuZvX28j8HgCciEGhuoph EoK/yLklKIa0qasQtXSsh3u2AL+3yEPPVpaebIeDyLYBGHanIH69iS7MLXTe5GLWHcGJ n/bOvi03c+Pm3Kz0fT4fEkxD51NIgJDMXO//YRPOugVmanj60cI5o+iXt3x+RtchzB1R iqbAU2RfrNS9T1mzu4rSiCYPSzOtnho93ZqjgO31U/+EeQAR14HYMe2Xp+qgzORJcCez NOIKjoVuDLUUugR++LtC0v4b3xHav/RO4wjnE1hMlxIXNMGc9Gc+0aJtN6oCXLBNlbIA SR4w== 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=zMoolKfl078lBlX2PU/tiitUWSDsEGlNd9hgMjhjn1U=; b=W6LwetgNpaPi2PbXWW61XxlzmEkMT3a9gbAS8hzjRDJY6wzTmYnReRpjmDiPFN9qE9 uZ7WOFvqGzeZleVhAbtQL356ElTj6bwk2yPpgnJO7exi+Pue0rsYq5VfUdULox8xMBZo InI7cTUySHuCLpolRnSnDye660pMj3KSEsK/qDsY1cZpO8GDcgiOtA+uqW0M7TAFSX6F +oezJCmmcWGMYSa1bO39Nq27rNJjCmYyRqiNBci3rcBwT05d6NVLycvhC2gAz5k0uRjM /ua7Xas0Y+yQAeJO6kYoOrSUOmmi6GsNBLfTrhg5phLWhOXc+xKRhEtLsdIyQtg+jAT3 VkbQ== X-Gm-Message-State: APjAAAX4IZE3ueWG++BOaSVcArxRMzEwfl8fABolyiDO3r9qxbbmiyVh ANVxRbseni0ieJK6Gv5Sm1o65eE= X-Google-Smtp-Source: APXvYqzd9DpGdpZS/ySWfwHYmqBqmYRMm7TCsBj6my2HuMbXvFcW4+M86Yi8gYNiq1w8rCQXNZ40lg== X-Received: by 2002:a1c:df46:: with SMTP id w67mr3847035wmg.69.1560868810950; Tue, 18 Jun 2019 07:40:10 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.10 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:10 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 04/13] trace-cmd: Add VM tracing protocol messages Date: Tue, 18 Jun 2019 17:39:49 +0300 Message-Id: <20190618143958.2865-5-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev Add TRACE_REQ and TRACE_RESP messages used for initiating guest VM tracing and CLOSE_RESP message used for acknowledging stop recording request. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- include/trace-cmd/trace-cmd.h | 14 ++ tracecmd/trace-msg.c | 234 +++++++++++++++++++++++++++++++++- 2 files changed, 245 insertions(+), 3 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 28b5b38..db5baa8 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -324,7 +324,9 @@ 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); int tracecmd_msg_send_close_msg(struct tracecmd_msg_handle *msg_handle); +int tracecmd_msg_send_close_resp_msg(struct tracecmd_msg_handle *msg_handle); int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle); +int tracecmd_msg_wait_close_resp(struct tracecmd_msg_handle *msg_handle); /* for server */ int tracecmd_msg_initial_setting(struct tracecmd_msg_handle *msg_handle); @@ -335,6 +337,18 @@ 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); + /* --- Plugin handling --- */ extern struct tep_plugin_option trace_ftrace_options[]; diff --git a/tracecmd/trace-msg.c b/tracecmd/trace-msg.c index 74c0bc1..69c7c5f 100644 --- a/tracecmd/trace-msg.c +++ b/tracecmd/trace-msg.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,17 @@ 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 flags; + be32 cpus; + be32 page_size; +} __attribute__((packed)); + struct tracecmd_msg_header { be32 size; be32 cmd; @@ -71,7 +83,10 @@ struct tracecmd_msg_header { C(RINIT, 2, sizeof(struct tracecmd_msg_rinit)), \ C(SEND_DATA, 3, 0), \ C(FIN_DATA, 4, 0), \ - C(NOT_SUPP, 5, 0), + C(NOT_SUPP, 5, 0), \ + C(TRACE_REQ, 6, sizeof(struct tracecmd_msg_trace_req)), \ + C(TRACE_RESP, 7, sizeof(struct tracecmd_msg_trace_resp)),\ + C(CLOSE_RESP, 8, 0), #undef C #define C(a,b,c) MSG_##a = b @@ -103,6 +118,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; }; char *buf; } __attribute__((packed)); @@ -625,6 +642,14 @@ int tracecmd_msg_send_close_msg(struct tracecmd_msg_handle *msg_handle) return tracecmd_msg_send(msg_handle->fd, &msg); } +int tracecmd_msg_send_close_resp_msg(struct tracecmd_msg_handle *msg_handle) +{ + struct tracecmd_msg msg; + + tracecmd_msg_init(MSG_CLOSE_RESP, &msg); + return tracecmd_msg_send(msg_handle->fd, &msg); +} + int tracecmd_msg_data_send(struct tracecmd_msg_handle *msg_handle, const char *buf, int size) { @@ -745,7 +770,7 @@ int tracecmd_msg_collect_data(struct tracecmd_msg_handle *msg_handle, int ofd) return tracecmd_msg_wait_close(msg_handle); } -int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle) +static int tracecmd_msg_wait_for_cmd(struct tracecmd_msg_handle *msg_handle, enum tracecmd_msg_cmd cmd) { struct tracecmd_msg msg; int ret = -1; @@ -756,7 +781,7 @@ int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle) if (ret < 0) goto error; - if (ntohl(msg.hdr.cmd) == MSG_CLOSE) + if (ntohl(msg.hdr.cmd) == cmd) return 0; error_operation(&msg); @@ -771,3 +796,206 @@ error: msg_free(&msg); return ret; } + +int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle) +{ + return tracecmd_msg_wait_for_cmd(msg_handle, MSG_CLOSE); +} + +int tracecmd_msg_wait_close_resp(struct tracecmd_msg_handle *msg_handle) +{ + return tracecmd_msg_wait_for_cmd(msg_handle, MSG_CLOSE_RESP); +} + +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 < 0) + 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; + ssize_t buf_len; + + ret = tracecmd_msg_recv(msg_handle->fd, &msg); + if (ret < 0) + return ret; + + if (ntohl(msg.hdr.cmd) != MSG_TRACE_REQ) { + ret = -ENOTSUP; + goto out; + } + + nr_args = ntohl(msg.trace_req.argc); + if (nr_args <= 0) { + ret = -EINVAL; + goto out; + } + + buf_len = ntohl(msg.hdr.size) - MSG_HDR_LEN - ntohl(msg.hdr.cmd_size); + buf_end = (char *)msg.buf + buf_len; + if (buf_len <= 0 && ((char *)msg.buf)[buf_len-1] != '\0') { + ret = -EINVAL; + goto out; + } + + args = calloc(nr_args, sizeof(*args)); + if (!args) { + ret = -ENOMEM; + goto out; + } + + for (i = 0, p = msg.buf; i < nr_args; i++, p++) { + if (p >= buf_end) { + ret = -EINVAL; + goto out_args; + } + args[i] = p; + p = strchr(p, '\0'); + } + + *argc = nr_args; + *argv = args; + + /* + * On success we're passing msg.buf to the caller through argv[0] so we + * reset it here before calling msg_free(). + */ + msg.buf = NULL; + msg_free(&msg); + return 0; + +out_args: + free(args); +out: + error_operation(&msg); + if (ret == -EOPNOTSUPP) + handle_unexpected_msg(msg_handle, &msg); + msg_free(&msg); + return ret; +} + +static int make_trace_resp(struct tracecmd_msg *msg, + int page_size, int nr_cpus, unsigned int *ports) +{ + int data_size; + + data_size = write_uints(NULL, 0, ports, nr_cpus); + msg->buf = malloc(data_size); + if (!msg->buf) + return -ENOMEM; + write_uints(msg->buf, data_size, ports, nr_cpus); + + msg->hdr.size = htonl(ntohl(msg->hdr.size) + data_size); + msg->trace_resp.cpus = htonl(nr_cpus); + msg->trace_resp.page_size = htonl(page_size); + + 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; + char *p, *buf_end; + ssize_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 = -ENOTSUP; + goto out; + } + + buf_len = msg_buf_len(&msg); + if (buf_len <= 0) { + ret = -EINVAL; + 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; + } + + buf_end = msg.buf + buf_len; + for (i = 0, p = msg.buf; i < *nr_cpus; i++, p++) { + if (p >= buf_end || tatou(p, &(*ports)[i])) { + free(*ports); + ret = -EINVAL; + goto out; + } + p = strchr(p, '\0'); + } + + msg_free(&msg); + return 0; + +out: + error_operation(&msg); + if (ret == -EOPNOTSUPP) + handle_unexpected_msg(msg_handle, &msg); + msg_free(&msg); + return ret; +} From patchwork Tue Jun 18 14:39:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001877 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 4E43B1902 for ; Tue, 18 Jun 2019 14:40:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3DC8228470 for ; Tue, 18 Jun 2019 14:40:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 320A02847D; Tue, 18 Jun 2019 14:40:16 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 8F5E7286DA for ; Tue, 18 Jun 2019 14:40:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729256AbfFROkP (ORCPT ); Tue, 18 Jun 2019 10:40:15 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36898 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729189AbfFROkP (ORCPT ); Tue, 18 Jun 2019 10:40:15 -0400 Received: by mail-wm1-f68.google.com with SMTP id f17so3556353wme.2 for ; Tue, 18 Jun 2019 07:40:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=oJOgkzmQN1HXFBK+rbOKVXI83jDLMEAY88QIXU9NN7A=; b=lUsqSKUGsBgacDG+T5+6/+PfnbIWk48IMQBAeagydKVJ9xBIVvGB3/c7I/zSpiiF8b 9vPZ+2Jc9WzKQrZLkYVOWnfcTbnekEqoTWuKXUqjX+KIda9WyQXqaCKASGo0yI6VdzDE Df+SMwq1aS6jTWqI++yiSITUmgWq72aW7WeteKuWACO9UOnHwqgIwPDN7wN4BzOLR9b2 THDV47kjSLF/MUCeDzfVsUSawEsyV5Dzfnu1xsH9uRnsnRifonQjFv5KVUWztbNJy2yP NyFryD68zi7eFMrd2AUBxRHioPjcPo8qhaP3l9RnNYJJ14mZ0ltbeDmQ3kxcHJGBMQeD ruVg== 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=oJOgkzmQN1HXFBK+rbOKVXI83jDLMEAY88QIXU9NN7A=; b=Ws45iJq75Hxa7UsbxbexZHVQKVdj07rTnX6OnrvzGsJUktwMgII90n3LVqW2gtk0Nr WCqQ4EGty1oumIaeYJITmZAmpJgcVaWv6MG4giLERgn4s2kjxOzSQHJqOuKYKWhUiCBO y715iavOXGrkhyUXmqV4p9QOZ0BM4U4GWk+lSQw+Fb8E00XF4EIHFTNek/arEnxgqWH7 o6mOYcMX9GoJWKtya8I9SuTD2ASY/BYVOZMMJWl2bGBwl0wtfwTxYxczlGHLXUt+PZ6o 0queWTUNRLdrTSbxM3ftGd9fVpoRQFjnDYVemEIMvF3QeYCOjo1kegK/IQFRouJPqiOg B/kw== X-Gm-Message-State: APjAAAUx48tig2XscLHByBa8pf6xf1Ak7EMdHwOTymKA9haYA6cdn4Th WrxqGj2nIQQ3u2xVNi/nj4Xh2UE= X-Google-Smtp-Source: APXvYqz5GG/WfiYvUhRseU0jEbtMLdE90d3X2+XHLzSx9zH/GvSx3mcTLa5H3IXBLNxUCD2vn05jnw== X-Received: by 2002:a1c:7503:: with SMTP id o3mr3936506wmc.170.1560868812047; Tue, 18 Jun 2019 07:40:12 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.10 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:11 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 05/13] trace-cmd: Add buffer instance flags for tracing in guest and agent context Date: Tue, 18 Jun 2019 17:39:50 +0300 Message-Id: <20190618143958.2865-6-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev 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 Signed-off-by: Slavomir Kaslev (VMware) --- tracecmd/include/trace-local.h | 5 +++ tracecmd/trace-record.c | 58 ++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index 1cad3cc..302f749 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 { @@ -200,6 +202,9 @@ extern struct buffer_instance *first_instance; #define for_all_instances(i) for (i = first_instance; i; \ i = i == &top_instance ? buffer_instances : (i)->next) +#define is_agent(instance) ((instance)->flags & BUFFER_FL_AGENT) +#define is_guest(instance) ((instance)->flags & BUFFER_FL_GUEST) + struct buffer_instance *create_instance(const char *name); void add_instance(struct buffer_instance *instance, int cpu_count); char *get_instance_file(struct buffer_instance *instance, const char *file); diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 5dc6f17..4198db7 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -822,6 +822,9 @@ static void __clear_trace(struct buffer_instance *instance) FILE *fp; char *path; + if (is_guest(instance)) + return; + /* reset the trace */ path = get_instance_file(instance, "trace"); fp = fopen(path, "w"); @@ -1339,6 +1342,9 @@ set_plugin_instance(struct buffer_instance *instance, const char *name) char *path; char zero = '0'; + if (is_guest(instance)) + return; + path = get_instance_file(instance, "current_tracer"); fp = fopen(path, "w"); if (!fp) { @@ -1435,6 +1441,9 @@ static void disable_func_stack_trace_instance(struct buffer_instance *instance) int size; int ret; + if (is_guest(instance)) + return; + path = get_instance_file(instance, "current_tracer"); ret = stat(path, &st); tracecmd_put_tracing_file(path); @@ -1628,6 +1637,9 @@ reset_events_instance(struct buffer_instance *instance) int i; int ret; + if (is_guest(instance)) + return; + if (use_old_event_method()) { /* old way only had top instance */ if (!is_top_instance(instance)) @@ -1940,6 +1952,9 @@ static void write_tracing_on(struct buffer_instance *instance, int on) int ret; int fd; + if (is_guest(instance)) + return; + fd = open_tracing_on(instance); if (fd < 0) return; @@ -1959,6 +1974,9 @@ static int read_tracing_on(struct buffer_instance *instance) char buf[10]; int ret; + if (is_guest(instance)) + return -1; + fd = open_tracing_on(instance); if (fd < 0) return fd; @@ -2105,6 +2123,9 @@ static void update_pid_filters(struct buffer_instance *instance) int ret; int fd; + if (is_guest(instance)) + return; + fd = open_instance_fd(instance, "set_event_pid", O_WRONLY | O_CLOEXEC | O_TRUNC); if (fd < 0) @@ -2200,6 +2221,9 @@ static void set_mask(struct buffer_instance *instance) int fd; int ret; + if (is_guest(instance)) + return; + if (!instance->cpumask) return; @@ -2230,6 +2254,9 @@ static void enable_events(struct buffer_instance *instance) { struct event_list *event; + if (is_guest(instance)) + return; + for (event = instance->events; event; event = event->next) { if (!event->neg) update_event(event, event->filter, 0, '1'); @@ -2253,6 +2280,9 @@ static void set_clock(struct buffer_instance *instance) char *content; char *str; + if (is_guest(instance)) + return; + if (!instance->clock) return; @@ -2282,6 +2312,9 @@ static void set_max_graph_depth(struct buffer_instance *instance, char *max_grap char *path; int ret; + if (is_guest(instance)) + return; + path = get_instance_file(instance, "max_graph_depth"); reset_save_file(path, RESET_DEFAULT_PRIO); tracecmd_put_tracing_file(path); @@ -2507,6 +2540,9 @@ static void expand_event_instance(struct buffer_instance *instance) struct event_list *compressed_list = instance->events; struct event_list *event; + if (is_guest(instance)) + return; + reset_event_list(instance); while (compressed_list) { @@ -3394,6 +3430,9 @@ static void set_funcs(struct buffer_instance *instance) int set_notrace = 0; int ret; + if (is_guest(instance)) + 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"); @@ -3690,6 +3729,9 @@ static void set_buffer_size_instance(struct buffer_instance *instance) int ret; int fd; + if (is_guest(instance)) + return; + if (!buffer_size) return; @@ -3900,6 +3942,9 @@ static void make_instances(void) int ret; for_each_instance(instance) { + if (is_guest(instance)) + continue; + path = get_instance_dir(instance); ret = stat(path, &st); if (ret < 0) { @@ -3921,7 +3966,7 @@ void tracecmd_remove_instances(void) for_each_instance(instance) { /* Only delete what we created */ - if (instance->flags & BUFFER_FL_KEEP) + if (is_guest(instance) || (instance->flags & BUFFER_FL_KEEP)) continue; if (instance->tracing_on_fd > 0) { close(instance->tracing_on_fd); @@ -4003,7 +4048,7 @@ static void check_function_plugin(void) static int __check_doing_something(struct buffer_instance *instance) { - return (instance->flags & BUFFER_FL_PROFILE) || + return is_guest(instance) || (instance->flags & BUFFER_FL_PROFILE) || instance->plugin || instance->events; } @@ -4025,6 +4070,9 @@ update_plugin_instance(struct buffer_instance *instance, { const char *plugin = instance->plugin; + if (is_guest(instance)) + return; + if (!plugin) return; @@ -4124,6 +4172,9 @@ static void record_stats(void) int cpu; for_all_instances(instance) { + if (is_guest(instance)) + continue; + s_save = instance->s_save; s_print = instance->s_print; for (cpu = 0; cpu < instance->cpu_count; cpu++) { @@ -4150,6 +4201,9 @@ static void destroy_stats(void) int cpu; for_all_instances(instance) { + if (is_guest(instance)) + 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 Tue Jun 18 14:39:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001887 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 3733C1395 for ; Tue, 18 Jun 2019 14:40:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 216A928470 for ; Tue, 18 Jun 2019 14:40:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 152D8286DA; Tue, 18 Jun 2019 14:40:21 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 073262847D for ; Tue, 18 Jun 2019 14:40:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729381AbfFROkS (ORCPT ); Tue, 18 Jun 2019 10:40:18 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36711 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729204AbfFROkS (ORCPT ); Tue, 18 Jun 2019 10:40:18 -0400 Received: by mail-wm1-f68.google.com with SMTP id u8so3563629wmm.1 for ; Tue, 18 Jun 2019 07:40:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VEeBN5feoz9qsVmJzn297A28j4b5gkDJpHLbMyfK244=; b=e6ivfkUpryW4WI2z6UdbP09bKWIOBXOFQub1BluVZp1F23J01it0XNnw65SBwGO8UV zqeObKbEqeZVNNMpQkyu4jZCvRone4kOyGSi1wb0N1WYwtWt1hKgUIVKk156kXczbgfU v3LJfgc4Sxw/eVFHiTKs7QBsIUh/wgJD4ZdijPHDaSk1PtnKpLsTpNGKdKSIPSDooPqs XJCSV89ceUGpHXidOxEG7V/NmHeZSccq8OHGaplZ8U5KPkjrOwy6EFQqtupevqtlLDOz dlowvv5v2ZlzhaudzZ1zc7ymWAs26zK/gplAK9+k6PLQmta5/CsfYlL4bPrRZdKUXHh4 JKiw== 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=VEeBN5feoz9qsVmJzn297A28j4b5gkDJpHLbMyfK244=; b=EqF4PqY/j6vJURUIC2tUQrfMhcDnu37mNMC6IbRKC9sIibl+3ZQwZrkqgTKBzdBVwG 8/5JNIR1cpiA2iTEDdxuo5xUUjsSjO1ewpEFtEMjitPLAmsetKPDMqMvM1bMB0M8XvTf asUMSV1CXkW7Yy5PacAHEcspwQnTNKdq6toTSAQsO8sqjvwDQnXW4VP35IaRL28k+xT/ KV48gCplt1be21kpjoWXgYF/V4Q//r86BVw1fDpKy6qrzuSbsdUY6emD7XLOqemK7AAy ar8yhSYqb+kW5tiLFBvzOEucAbR2Bvd8A8ThZlu8Xey2yrjB9BlaUNkylrIcg/mOOR/6 sP9w== X-Gm-Message-State: APjAAAWrmeMyHuZAIVPAVyw/c2BDZp9zoXyEn9r6TNEOch1hD24YTfPJ 7Ndtg8OirzopTxmmavhASw== X-Google-Smtp-Source: APXvYqwFStXIr/EAad3mRMnSMVEl8gyV57DZesgX/U4mvBCEOxwO/P5Ftzuva3tQnKVglTg17dIhMA== X-Received: by 2002:a1c:1947:: with SMTP id 68mr3846526wmz.165.1560868813312; Tue, 18 Jun 2019 07:40:13 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.12 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:12 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 06/13] trace-cmd: Add VM kernel tracing over vsockets transport Date: Tue, 18 Jun 2019 17:39:51 +0300 Message-Id: <20190618143958.2865-7-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev This patch adds VM tracing over vsockets. The new `trace-cmd agent` command needs run on each guest we want to trace: you@guest2 # trace-cmd agent Then `trace-cmd record` on the host can collect data from both the host and several guests simultaneously: you@host $ trace-cmd record -A guest1 -e irq -e sched \ -A guest2 -p function -e all Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- lib/trace-cmd/trace-recorder.c | 20 +- tracecmd/Makefile | 4 + tracecmd/include/trace-local.h | 16 + tracecmd/trace-agent.c | 263 ++++++++++++++ tracecmd/trace-cmd.c | 3 + tracecmd/trace-record.c | 606 ++++++++++++++++++++++++++++++--- tracecmd/trace-usage.c | 13 +- 7 files changed, 873 insertions(+), 52 deletions(-) create mode 100644 tracecmd/trace-agent.c diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index 0ea7a87..d57a5d6 100644 --- a/lib/trace-cmd/trace-recorder.c +++ b/lib/trace-cmd/trace-recorder.c @@ -382,11 +382,11 @@ static long splice_data(struct tracecmd_recorder *recorder) read = splice(recorder->trace_fd, NULL, recorder->brass[1], NULL, recorder->pipe_size, SPLICE_F_MOVE); if (read < 0) { - if (errno != EAGAIN && errno != EINTR) { - warning("recorder error in splice input"); - return -1; - } - return 0; + if (errno == EAGAIN || errno == EINTR || errno == ENOTCONN) + return 0; + + warning("recorder error in splice input"); + return -1; } else if (read == 0) return 0; @@ -421,11 +421,11 @@ static long read_data(struct tracecmd_recorder *recorder) r = read(recorder->trace_fd, buf, recorder->page_size); if (r < 0) { - if (errno != EAGAIN && errno != EINTR) { - warning("recorder error in read output"); - return -1; - } - return 0; + if (errno == EAGAIN || errno == EINTR || errno == ENOTCONN) + return 0; + + warning("recorder error in read input"); + return -1; } left = r; diff --git a/tracecmd/Makefile b/tracecmd/Makefile index bcd437a..a2c0a76 100644 --- a/tracecmd/Makefile +++ b/tracecmd/Makefile @@ -33,6 +33,10 @@ 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)) diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index 302f749..2872747 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; @@ -192,6 +201,13 @@ struct buffer_instance { int tracing_on_fd; int buffer_size; int cpu_count; + + int argc; + char **argv; + + unsigned int cid; + unsigned 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..e1dfddf --- /dev/null +++ b/tracecmd/trace-agent.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * 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" + +#define GET_LOCAL_CID 0x7b9 + +static int get_local_cid(unsigned int *cid) +{ + int fd, ret = 0; + + fd = open("/dev/vsock", O_RDONLY); + if (fd < 0) + return -errno; + + if (ioctl(fd, GET_LOCAL_CID, cid)) + ret = -errno; + + close(fd); + return ret; +} + +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 -errno; + + setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); + + if (bind(sd, (struct sockaddr *)&addr, sizeof(addr))) + return -errno; + + if (listen(sd, SOMAXCONN)) + return -errno; + + 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 -errno; + + if (addr.svm_family != AF_VSOCK) + return -errno; + + 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; + + for (i = 0; i < nr; i++) { + fd = make_vsock(VMADDR_PORT_ANY); + if (fd < 0) + die("Failed to open vsocket"); + + ret = get_vsock_port(fd, &port); + if (ret < 0) + die("Failed to get vsocket address"); + + fds[i] = fd; + ports[i] = port; + } +} + +static void agent_handle(int sd, int nr_cpus, int page_size) +{ + struct tracecmd_msg_handle *msg_handle; + unsigned int *ports; + char **argv = NULL; + int argc = 0; + int *fds; + int ret; + + fds = calloc(nr_cpus, sizeof(*fds)); + ports = calloc(nr_cpus, sizeof(*ports)); + if (!fds || !ports) + die("Failed to allocate memory"); + + msg_handle = tracecmd_msg_handle_alloc(sd, 0); + if (!msg_handle) + die("Failed to allocate message handle"); + + ret = tracecmd_msg_recv_trace_req(msg_handle, &argc, &argv); + if (ret < 0) + die("Failed to receive trace request"); + + make_vsocks(nr_cpus, fds, ports); + + ret = tracecmd_msg_send_trace_resp(msg_handle, nr_cpus, page_size, ports); + if (ret < 0) + die("Failed to send trace response"); + + trace_record_agent(msg_handle, nr_cpus, fds, argc, argv); + + free(argv[0]); + free(argv); + free(ports); + free(fds); + 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 pid_t do_fork() +{ + /* in debug mode, we do not fork off children */ + if (debug) + return 0; + + return fork(); +} + +static void agent_serve(unsigned int port) +{ + int sd, cd, nr_cpus; + unsigned int cid; + 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 vsocket"); + + if (!get_local_cid(&cid)) + printf("listening on @%u:%u\n", cid, port); + + for (;;) { + cd = accept(sd, NULL, NULL); + if (cd < 0) { + if (errno == EINTR) + continue; + die("accept"); + } + + if (handler_pid) + goto busy; + + pid = do_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); + } +} + +enum { + DO_DEBUG = 255 +}; + +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, '?'}, + {"debug", no_argument, NULL, DO_DEBUG}, + {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; + case DO_DEBUG: + debug = true; + break; + default: + usage(argv); + } + } + + if (optind < argc-1) + 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 4198db7..dfad8f2 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -33,6 +33,9 @@ #include #include #include +#ifdef VSOCK +#include +#endif #include "version.h" #include "trace-local.h" @@ -75,8 +78,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; @@ -521,6 +522,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); @@ -626,6 +643,25 @@ static void delete_thread_data(void) } } +static void tell_guests_to_stop(void) +{ + struct buffer_instance *instance; + + /* Send close message to guests */ + for_all_instances(instance) { + if (is_guest(instance)) + tracecmd_msg_send_close_msg(instance->msg_handle); + } + + /* Wait for guests to acknowledge */ + for_all_instances(instance) { + if (is_guest(instance)) { + tracecmd_msg_wait_close_resp(instance->msg_handle); + tracecmd_msg_handle_close(instance->msg_handle); + } + } +} + static void stop_threads(enum trace_type type) { int ret; @@ -647,6 +683,11 @@ static void stop_threads(enum trace_type type) ret = trace_stream_read(pids, recorder_threads, NULL); } while (ret > 0); } +} + +static void wait_threads() +{ + int i; for (i = 0; i < recorder_threads; i++) { if (pids[i].pid > 0) { @@ -2618,14 +2659,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; @@ -2652,7 +2693,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("Can not open /proc"); + + while ((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) @@ -2699,6 +2923,17 @@ create_recorder_instance(struct buffer_instance *instance, const char *file, int struct tracecmd_recorder *record; char *path; + if (is_guest(instance)) { + int fd; + + fd = open_vsock(instance->cid, instance->client_ports[cpu]); + if (fd < 0) + die("Failed to connect to agent"); + + return tracecmd_create_recorder_virt( + file, cpu, recorder_flags | TRACECMD_RECORD_NOSPLICE, fd); + } + if (brass) return create_recorder_instance_pipe(instance, cpu, brass); @@ -2723,7 +2958,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); @@ -2742,19 +2977,23 @@ static int create_recorder(struct buffer_instance *instance, int cpu, instance->cpu_count = 0; } - if (client_ports) { - char *path; + if ((instance->client_ports && !is_guest(instance)) || is_agent(instance)) { + unsigned int flags = recorder_flags; + char *path = NULL; + int fd; - connect_port(cpu); - if (instance->name) + if (is_agent(instance)) + fd = do_accept(instance->fds[cpu]); + else + fd = connect_port(host, instance->client_ports[cpu]); + if (fd < 0) + die("Failed connecting to client"); + if (instance->name && !is_agent(instance)) 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); @@ -2792,7 +3031,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; @@ -2835,8 +3075,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); /* @@ -2854,13 +3094,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"); } @@ -2911,7 +3152,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; @@ -2981,11 +3222,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; } @@ -2998,7 +3239,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) { @@ -3025,28 +3266,99 @@ 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, ret, nr_cpus, page_size; + unsigned int *ports; + + sd = open_vsock(instance->cid, instance->port); + if (sd < 0) + die("Failed to connect to vsocket @%u:%u", + instance->cid, instance->port); + + msg_handle = tracecmd_msg_handle_alloc(sd, 0); + if (!msg_handle) + die("Failed to allocate message handle"); + + ret = tracecmd_msg_send_trace_req(msg_handle, instance->argc, instance->argv); + if (ret < 0) + die("Failed to send trace request"); + + ret = tracecmd_msg_recv_trace_resp(msg_handle, &nr_cpus, &page_size, &ports); + if (ret < 0) + 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 (is_guest(instance)) + 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 (is_agent(instance)) { + setup_agent(instance, ctx); + } else if (is_guest(instance)) { + setup_guest(instance); + } else if (host) { instance->msg_handle = setup_connection(instance, ctx); if (!instance->msg_handle) die("Failed to make connection"); @@ -3235,6 +3547,44 @@ static void add_options(struct tracecmd_output *handle, struct common_record_con add_version(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) { struct tracecmd_option **buffer_options; @@ -3246,7 +3596,9 @@ static void record_data(struct common_record_context *ctx) int i; for_all_instances(instance) { - if (instance->msg_handle) + if (is_guest(instance)) + write_guest_file(instance); + else if (host && instance->msg_handle) finish_network(instance->msg_handle); else local = true; @@ -4478,6 +4830,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); @@ -4646,6 +4999,65 @@ 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_RECORD_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, *arg; + int i, ret; + + /* Short or long arg */ + if (!(c & 0x80)) { + ptr = strchr(opts, c); + if (!ptr) + return; /* Not found? */ + ret = asprintf(&arg, "-%c", c); + if (ret < 0) + die("Can not allocate argument"); + add_argv(instance, arg, false); + if (ptr[1] == ':') { + arg = strdup(optarg); + if (!arg) + die("Can not allocate arguments"); + add_argv(instance, arg, false); + } + return; + } + for (i = 0; long_options[i].name; i++) { + if (c != long_options[i].val) + continue; + 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, @@ -4659,6 +5071,7 @@ static void parse_record_options(int argc, char *pids; char *pid; char *sav; + int name_counter = 0; int neg_event = 0; init_common_record_context(ctx, curr_cmd); @@ -4688,10 +5101,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' && is_guest(ctx->instance)) { + add_arg(ctx->instance, c, opts, long_options, optarg); + continue; + } + switch (c) { case 'h': usage(argv); @@ -4744,6 +5167,28 @@ 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 (cid == -1) + die("guest %s not found", optarg); + if (port == -1) + port = TRACE_AGENT_DEFAULT_PORT; + if (!name || !*name) + asprintf(&name, "unnamed-%d", name_counter++); + + 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; @@ -4814,6 +5259,8 @@ static void parse_record_options(int argc, ctx->disable = 1; break; case 'o': + if (IS_RECORD_AGENT(ctx)) + die("-o incompatible with agent recording"); if (host) die("-o incompatible with -N"); if (IS_START(ctx)) @@ -4875,6 +5322,8 @@ static void parse_record_options(int argc, case 'N': if (!IS_RECORD(ctx)) die("-N only available with record"); + if (IS_RECORD_AGENT(ctx)) + die("-N incompatible with agent recording"); if (ctx->output) die("-N incompatible with -o"); host = optarg; @@ -4974,6 +5423,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 (is_guest(instance)) + add_argv(instance, "--date", true); + } + } + if (!ctx->filtered && ctx->instance->filter_mod) add_func(&ctx->instance->filter_funcs, ctx->instance->filter_mod, "*"); @@ -5004,7 +5463,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++) { @@ -5036,12 +5496,30 @@ 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 (is_agent(instance)) { + tracecmd_msg_send_close_resp_msg(instance->msg_handle); + 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 (is_guest(instance)) + continue; + if (host && instance->msg_handle) + continue; + return true; + } + return false; +} + /* * This function contains common code for the following commands: * record, start, stream, profile. @@ -5070,7 +5548,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); @@ -5087,14 +5564,16 @@ static void record_trace(int argc, char **argv, page_size = getpagesize(); - fset = set_ftrace(!ctx->disable, ctx->total_disable); + if (!is_guest(ctx->instance)) + 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_RECORD_AGENT(ctx))) ctx->date2ts = get_date_to_ts(); for_all_instances(instance) { @@ -5131,9 +5610,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 && is_agent(ctx->instance)) { + 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 */ @@ -5145,6 +5628,7 @@ static void record_trace(int argc, char **argv, trace_or_sleep(type); } + tell_guests_to_stop(); tracecmd_disable_tracing(); if (!latency) stop_threads(type); @@ -5154,6 +5638,9 @@ static void record_trace(int argc, char **argv, if (!keep) tracecmd_disable_all_tracing(0); + if (!latency) + wait_threads(); + if (IS_RECORD(ctx)) { record_data(ctx); delete_thread_data(); @@ -5290,3 +5777,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"; + memmove(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 406384c..da34ea2 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -233,11 +233,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 vsocket for trace clients", + " %s agent -p port[-D]\n" + " Creates a vsocket 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 Tue Jun 18 14:39:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001879 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 18F9B1395 for ; Tue, 18 Jun 2019 14:40:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 09C3528470 for ; Tue, 18 Jun 2019 14:40:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F236B286DA; Tue, 18 Jun 2019 14:40:16 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 93AA928470 for ; Tue, 18 Jun 2019 14:40:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729189AbfFROkQ (ORCPT ); Tue, 18 Jun 2019 10:40:16 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:55538 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725919AbfFROkQ (ORCPT ); Tue, 18 Jun 2019 10:40:16 -0400 Received: by mail-wm1-f67.google.com with SMTP id a15so3581740wmj.5 for ; Tue, 18 Jun 2019 07:40:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=zSroMduFjINHwGCFkDKv6ls67YiaZxOPtxbmALrcnJ0=; b=AJkelRXgrKA9+hR9BIQrqdpPN0hiL0AxdTRc/jqF3OPtFQSPAN0t3OVNiCVe5Vseet x+Axu+4QRJjRKK6Xi72oIE6fAhEf2mqLkdjLDtVZ52wjIiGESJBKbqPs9LvwtZm3crCt y0WS/yzSwgEcfzQJVt5yjgfGNYeo2vZSVzSk+qaVJ3zOuhkL9YmeJC2hMTZqLHEe9aug NA5GWv07DXj8ScjXyiDr7a837AYk6NsVFqQiOGD+pGTf0rBuPdndxUkZL+o342Lqmt99 uKlmBkYHGxtlwrfzUVi7gHRw+6JJHKExobjBSoxLIbqslwAF2N7Ud9qfyN5Ar4Jibjli EspA== 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=zSroMduFjINHwGCFkDKv6ls67YiaZxOPtxbmALrcnJ0=; b=sPy0s+PoIhzF3xfgJY6njsvDOtEULPhM0Rmbrydh5PdtAHzb7bzksHX2OJpcaqECRv QOSZcYYQQ7Oq5VqF0yr9HBcWHrq/4Hg6XiYw+LVBMNgo92O3wPZspHPC8sPadXPMwwMx C7X1zKQiJt2aBmkiSFnj9BEXg/c+O1F09+IQbZwVTuazLQIKhjV1DNHAEjYdA5jFUkH5 6jweNxPXUxICWQiqbYeWHtFoF/Pwwhz7fslpWmZqolkYwwd4i5rQ5byrqirWwVIAA/46 S7w1tJVPEksD5ZHvVJ/Btajv1AkgGRrB8JhJ66BVEZmvgg62hW6KBkMDgJy7EETMWMZs lNWw== X-Gm-Message-State: APjAAAXAkzx2I3MJLjwyHAh2pXrMH5irLNE3yjZ21O0VEFa5uwwr9pe4 JZjocmBxn9YKuk9QjpoDMfHQtt8= X-Google-Smtp-Source: APXvYqxV/76W5Dj/3TdI1nYAgNz5+CxyR/2sl3apS3FT1KwWM3Kv/QeBN7XgLU+ED9XoeicJtZIJAw== X-Received: by 2002:a1c:a483:: with SMTP id n125mr3914123wme.3.1560868814269; Tue, 18 Jun 2019 07:40:14 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.13 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:13 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 07/13] trace-cmd: Use splice(2) for vsockets if available Date: Tue, 18 Jun 2019 17:39:52 +0300 Message-Id: <20190618143958.2865-8-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev Detect if splice(2) reading is supported for vsockets (Linux 4.20 and later) and use it, or fallback to read/write-ing otherwise. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- tracecmd/trace-record.c | 56 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index dfad8f2..f6e5c7e 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -2715,12 +2715,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 vsockets + * 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) @@ -2925,13 +2974,16 @@ create_recorder_instance(struct buffer_instance *instance, const char *file, int if (is_guest(instance)) { int fd; + unsigned int flags; fd = open_vsock(instance->cid, instance->client_ports[cpu]); if (fd < 0) die("Failed to connect to agent"); - return tracecmd_create_recorder_virt( - file, cpu, recorder_flags | TRACECMD_RECORD_NOSPLICE, fd); + flags = recorder_flags; + if (!can_splice_read_vsock()) + flags |= TRACECMD_RECORD_NOSPLICE; + return tracecmd_create_recorder_virt(file, cpu, flags, fd); } if (brass) From patchwork Tue Jun 18 14:39:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001881 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 3C34B1395 for ; Tue, 18 Jun 2019 14:40:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2D70028470 for ; Tue, 18 Jun 2019 14:40:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2192228825; Tue, 18 Jun 2019 14:40:19 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 12F4128470 for ; Tue, 18 Jun 2019 14:40:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729157AbfFROkR (ORCPT ); Tue, 18 Jun 2019 10:40:17 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:39137 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728572AbfFROkR (ORCPT ); Tue, 18 Jun 2019 10:40:17 -0400 Received: by mail-wr1-f66.google.com with SMTP id x4so14288242wrt.6 for ; Tue, 18 Jun 2019 07:40:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RUcBoUQNQrgcKDeseDcABNoAkO9CRuGl+8Gvj7tg0ew=; b=YnmPlaeADoYLE3JJykLbpdi0NDlM9Yuo1qy/WrfUGlqvHEio/b6bmSOY8XS3FYP0UH eILO2uj/xQzqX+oySRlF6gTtXrzZoF6rwgtcLfYpiWUqqyI7vKPz5Fd4ZA+ZbXZVnMr6 kED43+NEU/5sC1Yj0BIPAT4GM/q5BOtzKb8462oZrLFRD3wDxNXZ0uFBJfeO4S6E3Tlx qluw7yHO4qODn6XALI1VI+lF/IwNXI6GGhNU+6qpgKzXyz0SYE4rFPhWD8HOf5K6aKRt /zlZrGfOvAyoqCzJeBEHZyAvEO27hV6cNewo3L2y3PGgMUzq13J9OyEXxS/Zv2iwYg/c VNhQ== 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=RUcBoUQNQrgcKDeseDcABNoAkO9CRuGl+8Gvj7tg0ew=; b=fNVe+HzaTuRmducQMdC+cany1zdI8lf60brGZ/x/h8Wx2+IiyXzDf939dca7OZs7RM sV6OTqVeEXBbnzCGqZk4sBbKLpVitPBtiCV6fXXKkJrboSRjdTuEfV9tK6AtYMm7cSwl ridtHBC6+DI/BB/0Kl1XhTkq1027zPUv0Q+d1bSpcTCyN6LlCt2dw4EtXcpKTIBBWqB9 LYPHqsxtpIZCskada8KNVFdpisI4RZWNY7DfiJyZknl2Ca97aAJhpkWjUIVXub8qDq64 j/nI0NlMGGoAE05K7EKEKCbhhXIVj/C13GyFYucrCVa41wJ4ErsH7++ZQl5BXaIPuGPx xLZA== X-Gm-Message-State: APjAAAWjb7l6SkC3ZPdqaTk5hBIEZpxaZFwrB/5RvdcaSmY6rTVYynl0 6+MXiu0pC+0CDBNf7Pm3olN1jM8= X-Google-Smtp-Source: APXvYqzfGL5Pb7gUYgoGsch7UzjNcLOwyMdIrSndndzkksOXcPrrrqyTM1Hw5l7stPxga5ZvVl0hgw== X-Received: by 2002:adf:fb47:: with SMTP id c7mr45303868wrs.116.1560868815290; Tue, 18 Jun 2019 07:40:15 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.14 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:14 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 08/13] trace-cmd: Switch stop recording signal to SIGUSR1 Date: Tue, 18 Jun 2019 17:39:53 +0300 Message-Id: <20190618143958.2865-9-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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 Using Ctrl-C to stop trace-cmd recording from the command line delivers SIGINT to all its child processes. Switch internal recording stop notification to SIGUSR1 so that notifying recording child processes can be delayed in order to do proper flushing when doing remote VM tracing. Also remove the flush() function, which is only used by trace-cmd listen, and use finish() instead without changing listener's behavior. Signed-off-by: Slavomir Kaslev (VMware) --- tracecmd/trace-record.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index f6e5c7e..d98cd39 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -673,7 +673,7 @@ static void stop_threads(enum trace_type type) /* Tell all threads to finish up */ for (i = 0; i < recorder_threads; i++) { if (pids[i].pid > 0) { - kill(pids[i].pid, SIGINT); + kill(pids[i].pid, SIGUSR1); } } @@ -2653,12 +2653,6 @@ static void finish(int sig) finished = 1; } -static void flush(int sig) -{ - if (recorder) - tracecmd_stop_recording(recorder); -} - static int connect_port(const char *host, unsigned int port) { struct addrinfo hints; @@ -3013,7 +3007,6 @@ static int create_recorder(struct buffer_instance *instance, int cpu, pid_t pid; if (type != TRACE_TYPE_EXTRACT) { - signal(SIGUSR1, flush); pid = fork(); if (pid < 0) @@ -3022,6 +3015,9 @@ static int create_recorder(struct buffer_instance *instance, int cpu, if (pid) return pid; + signal(SIGINT, SIG_DFL); + signal(SIGUSR1, finish); + if (rt_prio) set_prio(rt_prio); From patchwork Tue Jun 18 14:39:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001885 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 C412B1902 for ; Tue, 18 Jun 2019 14:40:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B336228470 for ; Tue, 18 Jun 2019 14:40:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A80DB28825; Tue, 18 Jun 2019 14:40:20 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 06954286DA for ; Tue, 18 Jun 2019 14:40:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728572AbfFROkT (ORCPT ); Tue, 18 Jun 2019 10:40:19 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:34058 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725919AbfFROkT (ORCPT ); Tue, 18 Jun 2019 10:40:19 -0400 Received: by mail-wr1-f67.google.com with SMTP id k11so14307002wrl.1 for ; Tue, 18 Jun 2019 07:40:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lTsQwcQ9zxDSxAxhw/DojYbvncZ+2fQLbOSfTsDR3hc=; b=RUmyHAAWznNYdac3/9jo3fRIGnNuoZY1yXb8j+MUzOAOYEoTKgdp8Xv/1EFB1QZk3P heyAv84BacxMuzHjDEG0gZgajvcqRXcYvJCwcCdPTZxnoi0un3xLFu5K5ybJNOcL3wkH ng/IOcJIo/Kx4naPUKO33vzDEX2TLD64eTuJMi9xK5Xs9qHrVK4MswSy+CErF8/D73gT RHIm0+l0/2+rqWhMVUd52UNjod73jLv8ufWSbtlr6J5DkkynuC/5PT8SzGVocAwDUWlq FY/4M5rjbqt9mib1L+j/oR2dEL8vBEYtxsq9iYnOqb9cQh7kpL7lWJquP6fmXFZ0+t7K TK+w== 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=lTsQwcQ9zxDSxAxhw/DojYbvncZ+2fQLbOSfTsDR3hc=; b=And8BX63G+tbA7I38rbdxUFha7KycveSbevuUFcdLMAKQUN62e+mNPikxaKPyYHqW9 RzW9dzBpHO4xPr5T44mCdp+/2C6Yua3nyQEFTLVFF7ZeGtNQC6p7uiU3iIu68mbGzOYW 8nE9N4TOknI10NiXril4NN8dMFlZaopL8uooq3I1dOPtM69SZwNQzwjPcgnUHRDij/tl X4oLKrX+RsTXZj7/HbuiLoFvKQDT7Rh2fz24uoxWVDkm6vorz8ZsH2XEMtghTXogsV3y OXOzJ2rlciLjcViMlyGPUMbvk+QfZSn2N3AC6hGhtbi40qOZl3+zrhF0LBYaE0JZ2akz a1DQ== X-Gm-Message-State: APjAAAUyRBRS6Vs6xZIBz3UgbQ16OXRYMllSKhdPanTP/RlQlmxXCR4b dJcsuD2MZSLSIiAvslJ/H4y6Kl4= X-Google-Smtp-Source: APXvYqz0ep6U8WI7OsqSBZStPg+0a7lNjDEumyL9SPlAwe3LIBhEY7J9Ih8UvhcAGY7llcJw0sWp1A== X-Received: by 2002:a5d:5702:: with SMTP id a2mr39334559wrv.89.1560868816545; Tue, 18 Jun 2019 07:40:16 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.15 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:15 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 09/13] trace-cmd: Add `trace-cmd setup-guest` command Date: Tue, 18 Jun 2019 17:39:54 +0300 Message-Id: <20190618143958.2865-10-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev Add `trace-cmd setup-guest` command that creates the necessary FIFOs for tracing a guest over FIFOs instead of vsockets. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- tracecmd/Makefile | 1 + tracecmd/include/trace-local.h | 6 ++ tracecmd/trace-cmd.c | 1 + tracecmd/trace-setup-guest.c | 178 +++++++++++++++++++++++++++++++++ tracecmd/trace-usage.c | 8 ++ 5 files changed, 194 insertions(+) create mode 100644 tracecmd/trace-setup-guest.c diff --git a/tracecmd/Makefile b/tracecmd/Makefile index a2c0a76..46af5cc 100644 --- a/tracecmd/Makefile +++ b/tracecmd/Makefile @@ -35,6 +35,7 @@ TRACE_CMD_OBJS += trace-msg.o ifeq ($(VSOCK_DEFINED), 1) TRACE_CMD_OBJS += trace-agent.o +TRACE_CMD_OBJS += trace-setup-guest.o endif ALL_OBJS := $(TRACE_CMD_OBJS:%.o=$(bdir)/%.o) diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index 2872747..93da7da 100644 --- a/tracecmd/include/trace-local.h +++ b/tracecmd/include/trace-local.h @@ -14,6 +14,10 @@ #define TRACE_AGENT_DEFAULT_PORT 823 +#define GUEST_PIPE_NAME "trace-pipe-cpu" +#define GUEST_DIR_FMT "/var/lib/trace-cmd/virt/%s" +#define GUEST_FIFO_FMT GUEST_DIR_FMT "/" GUEST_PIPE_NAME "%d" + extern int debug; extern int quiet; @@ -68,6 +72,8 @@ void trace_listen(int argc, char **argv); void trace_agent(int argc, char **argv); +void trace_setup_guest(int argc, char **argv); + void trace_restore(int argc, char **argv); void trace_clear(int argc, char **argv); diff --git a/tracecmd/trace-cmd.c b/tracecmd/trace-cmd.c index 3ae5e2e..4da82b4 100644 --- a/tracecmd/trace-cmd.c +++ b/tracecmd/trace-cmd.c @@ -85,6 +85,7 @@ struct command commands[] = { {"listen", trace_listen}, #ifdef VSOCK {"agent", trace_agent}, + {"setup-guest", trace_setup_guest}, #endif {"split", trace_split}, {"restore", trace_restore}, diff --git a/tracecmd/trace-setup-guest.c b/tracecmd/trace-setup-guest.c new file mode 100644 index 0000000..a6f58dc --- /dev/null +++ b/tracecmd/trace-setup-guest.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 VMware Inc, Slavomir Kaslev + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "trace-local.h" +#include "trace-msg.h" + +static int make_dir(const char *path, mode_t mode) +{ + char buf[PATH_MAX+2], *p; + + strncpy(buf, path, sizeof(buf)); + if (buf[PATH_MAX]) + return -E2BIG; + + for (p = buf; *p; p++) { + p += strspn(p, "/"); + p += strcspn(p, "/"); + *p = '\0'; + if (mkdir(buf, mode) < 0 && errno != EEXIST) + return -errno; + *p = '/'; + } + + return 0; +} + +static int make_fifo(const char *path, mode_t mode) +{ + struct stat st; + + if (!stat(path, &st)) { + if (S_ISFIFO(st.st_mode)) + return 0; + return -EEXIST; + } + + if (mkfifo(path, mode)) + return -errno; + return 0; +} + +static int make_guest_dir(const char *guest) +{ + char path[PATH_MAX]; + + snprintf(path, sizeof(path), GUEST_DIR_FMT, guest); + return make_dir(path, 0750); +} + +static int make_guest_fifo(const char *guest, int cpu, mode_t mode) +{ + static const char *exts[] = {".in", ".out"}; + char path[PATH_MAX]; + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(exts); i++) { + snprintf(path, sizeof(path), GUEST_FIFO_FMT "%s", + guest, cpu, exts[i]); + ret = make_fifo(path, mode); + if (ret < 0) + break; + } + + return ret; +} + +static int make_guest_fifos(const char *guest, int nr_cpus, mode_t mode) +{ + int i, ret = 0; + mode_t mask; + + mask = umask(0); + for (i = 0; i < nr_cpus; i++) { + ret = make_guest_fifo(guest, i, mode); + if (ret < 0) + break; + } + umask(mask); + + return ret; +} + +static void do_setup_guest(const char *guest, int nr_cpus, mode_t mode, gid_t gid) +{ + gid_t save_egid; + int ret; + + if (gid != -1) { + save_egid = getegid(); + ret = setegid(gid); + if (ret < 0) + pdie("failed to set effective group ID"); + } + + ret = make_guest_dir(guest); + if (ret < 0) + pdie("failed to create guest directory for %s", guest); + + ret = make_guest_fifos(guest, nr_cpus, mode); + if (ret < 0) + pdie("failed to create FIFOs for %s", guest); + + if (gid != -1) { + ret = setegid(save_egid); + if (ret < 0) + pdie("failed to restore effective group ID"); + } +} + +void trace_setup_guest(int argc, char **argv) +{ + struct group *group; + mode_t mode = 0660; + int nr_cpus = -1; + gid_t gid = -1; + char *guest; + + if (argc < 2) + usage(argv); + + if (strcmp(argv[1], "setup-guest") != 0) + usage(argv); + + for (;;) { + int c, option_index = 0; + static struct option long_options[] = { + {"help", no_argument, NULL, '?'}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long(argc-1, argv+1, "+hc:p:g:", + long_options, &option_index); + if (c == -1) + break; + switch (c) { + case 'h': + usage(argv); + break; + case 'c': + nr_cpus = atoi(optarg); + break; + case 'p': + mode = strtol(optarg, NULL, 8); + break; + case 'g': + group = getgrnam(optarg); + if (!group) + pdie("group %s does not exist", optarg); + gid = group->gr_gid; + break; + default: + usage(argv); + } + } + + if (optind != argc-2) + usage(argv); + + guest = argv[optind+1]; + + if (nr_cpus <= 0) + pdie("invalid number of cpus for guest %s", guest); + + do_setup_guest(guest, nr_cpus, mode, gid); +} diff --git a/tracecmd/trace-usage.c b/tracecmd/trace-usage.c index da34ea2..0d1b58e 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -248,6 +248,14 @@ static struct usage_help usage_help[] = { " -p port number to listen on.\n" " -D run in daemon mode.\n" }, + { + "setup-guest", + "create FIFOs for tracing guest VMs", + " %s setup-guest -c cpus[-p perm][-g group] guest\n" + " -c number of guest virtual CPUs\n" + " -p FIFOs permissions (default: 0660)\n" + " -g FIFOs group owner\n" + }, #endif { "list", From patchwork Tue Jun 18 14:39:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001883 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 4CAD514BB for ; Tue, 18 Jun 2019 14:40:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E2C428470 for ; Tue, 18 Jun 2019 14:40:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 330A7288F4; Tue, 18 Jun 2019 14:40:20 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 D123628470 for ; Tue, 18 Jun 2019 14:40:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729383AbfFROkT (ORCPT ); Tue, 18 Jun 2019 10:40:19 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:39142 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728572AbfFROkT (ORCPT ); Tue, 18 Jun 2019 10:40:19 -0400 Received: by mail-wr1-f67.google.com with SMTP id x4so14288413wrt.6 for ; Tue, 18 Jun 2019 07:40:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wRhE2USNkyWhVFESY7aZ28+NJrvuNFHOu+uZjWk5Vnk=; b=XtkwFDuTUMWtqwmghV0NTwRq/S0yPkyRTvaRkigxGCE7jaKvO/NDhY6rV3RUTBGxEO xFN/FtBOTS4ljbcORLWaZmc/maD+23rTNiYS97XFTgF0LHJR5AFvl6Tf5S1Zmj9IEIAJ RfXCLw15+StA2r5P7G1SDbTeeVL30PwWTBIp/FXfpi9pnc01JaIT6/Ym1Lh1pnhxx6Bw XXrHggehv9EW3+NIK8Az8/thlMKRvOwtfC5dQ7MnnS3lo0Sb74JrmKrghur6YmAumAkE dXhdT4L0JosLCLL3gqEzK4L5/7wSW0UBNP4JXAdzoAPn+eryEkTExm9TsawQKRTajav5 NXmQ== 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=wRhE2USNkyWhVFESY7aZ28+NJrvuNFHOu+uZjWk5Vnk=; b=k8c3YC7j8dgUo7aYvZ88etGAWE5UYh704gEfzbEhJaBiAJwwxX3DY3F8GDNg4RfGbd 7tBfcAn6msF4z5F/pSiEGIa59SsguTBVR+GD2tlk/5kK+1W+gl1wqi68vsm0X1HIQrLe gPXssnJcAPnrvHmea6GPC2rO0DSlCwVF5Twtl7ChbF7cjgacRsUo9tNsAVeWKClUOIKa r6n1s8xFtXhlRclNa1y1UqF1QrzwqkhGVDG3BYal3alB/Kv2at5VreTEbEuIhFkon6zL fvo56uT5TMu+Xde0dAOwhuv6y1Er6YE6IFACzvZuha3qvWzdfjFs8t1U9UBHh6XnsvQS r+Lg== X-Gm-Message-State: APjAAAWYHN4STrtPdlGUVrNSgRF0F8S9G+33dZH1FD34cqembJTupYgZ D/kN7ckUxQ2p5tmy72jM1aAGyac= X-Google-Smtp-Source: APXvYqxbXLATIfiGcFwTFlGevXd30wx7WAKqa0ti9gfhsEzgOea/48iM3oMg2oMFFHXvO8EHmFv/sA== X-Received: by 2002:a5d:4752:: with SMTP id o18mr12496507wrs.74.1560868817624; Tue, 18 Jun 2019 07:40:17 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.16 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:16 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 10/13] trace-cmd: Try to autodetect number of guest CPUs in setup-guest if not specified Date: Tue, 18 Jun 2019 17:39:55 +0300 Message-Id: <20190618143958.2865-11-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev When no number of guest CPUs is provided with the -c flag to `trace-cmd setup-guest`, try to autodetect it using virsh for libvirt managed guests. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- tracecmd/trace-setup-guest.c | 21 +++++++++++++++++++++ tracecmd/trace-usage.c | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tracecmd/trace-setup-guest.c b/tracecmd/trace-setup-guest.c index a6f58dc..a55a37d 100644 --- a/tracecmd/trace-setup-guest.c +++ b/tracecmd/trace-setup-guest.c @@ -93,6 +93,24 @@ static int make_guest_fifos(const char *guest, int nr_cpus, mode_t mode) return ret; } +static int get_guest_cpu_count(const char *guest) +{ + const char *cmd_fmt = "virsh vcpucount --maximum '%s' 2>/dev/null"; + int nr_cpus = -1; + char cmd[1024]; + FILE *f; + + snprintf(cmd, sizeof(cmd), cmd_fmt, guest); + f = popen(cmd, "r"); + if (!f) + return -errno; + + fscanf(f, "%d", &nr_cpus); + pclose(f); + + return nr_cpus; +} + static void do_setup_guest(const char *guest, int nr_cpus, mode_t mode, gid_t gid) { gid_t save_egid; @@ -171,6 +189,9 @@ void trace_setup_guest(int argc, char **argv) guest = argv[optind+1]; + if (nr_cpus <= 0) + nr_cpus = get_guest_cpu_count(guest); + if (nr_cpus <= 0) pdie("invalid number of cpus for guest %s", guest); diff --git a/tracecmd/trace-usage.c b/tracecmd/trace-usage.c index 0d1b58e..a2a520c 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -251,7 +251,7 @@ static struct usage_help usage_help[] = { { "setup-guest", "create FIFOs for tracing guest VMs", - " %s setup-guest -c cpus[-p perm][-g group] guest\n" + " %s setup-guest [-c cpus][-p perm][-g group] guest\n" " -c number of guest virtual CPUs\n" " -p FIFOs permissions (default: 0660)\n" " -g FIFOs group owner\n" From patchwork Tue Jun 18 14:39:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001889 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 10B8614BB for ; Tue, 18 Jun 2019 14:40:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 00C3A28470 for ; Tue, 18 Jun 2019 14:40:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E9316286DA; Tue, 18 Jun 2019 14:40:21 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 7B6BC28470 for ; Tue, 18 Jun 2019 14:40:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729386AbfFROkV (ORCPT ); Tue, 18 Jun 2019 10:40:21 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:53254 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729204AbfFROkV (ORCPT ); Tue, 18 Jun 2019 10:40:21 -0400 Received: by mail-wm1-f67.google.com with SMTP id x15so3586513wmj.3 for ; Tue, 18 Jun 2019 07:40:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XApiP+OIlkdKJZK+FAewYYlbfnTXOGInFV7ZMbKcgOs=; b=YdNIrEXOP5g7lzvAqUsg0hg+ERUA/GZ7APhQp9IJqN+i7wL/P2dG/DC3/hkCbCOxK3 hk3QCGlIbgh9j3Felr5vhTCYb872bHVZpUtmehRKS7I7cS6KndMz49e1McrKMno3TemB oK6WeRnRW/yxLqXz4GsNzE3LIQr1IN5qupFD3TuGpb7L6O4Hppqy7VZs/wAS7ukOimQG Zt3wCiJKkLRaeCvVrYKN48w2pw9E68uolFD3vCD9QBo9CmwY+GK9oq7KKUTVMsk29SxO rWPLFsLruteRs42th75R4Nf8AQmMDM2ZUMnDesuko60lLJdl6271dhESbBUIyD2Prb6s /l1w== 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=XApiP+OIlkdKJZK+FAewYYlbfnTXOGInFV7ZMbKcgOs=; b=Dz/56CvPRcKm1fxji+lWwuSb2Se7vErchyWDInXdrbQDv88HcYEzTlketyf0tpg2At 7lUiuXQ3EWImm2B79me+S30GtKxbCmErliJltmnbtieQi+fD0hV5N2RGUldFJGAzifhN YNryF2JC4Ivzw6pLNuAzutgFrobC5yySYaFotKXnBVYAJ6CXGuNVv167J0RFbGd/DRD9 QCsJOAHnA4GKL2BFdoCd4Syd9X90O8GvCVW1PVDHPogNVSgcE5+NN9euR+GUuvEbZdHm 68dwOT7IDE1Knt2g8R8MuusLPU48n/DyY5UaSF3svWEvcuJvx6+tuTRcxgtWmB4LVk4w LMug== X-Gm-Message-State: APjAAAVIpKJy1P86UphivX+NxJznq/Oq3jK+KxUZljXrebjN7EELKEB6 ita67tKNslMqBl9uTxNfJ4Z2rBg= X-Google-Smtp-Source: APXvYqy89aXTITYyY/jTRg3AUkGp5PxHn4JIJe+yiBYLZ3/bOUb2j550mq/HgboeHATg1bof2pUamw== X-Received: by 2002:a1c:eb0a:: with SMTP id j10mr4297016wmh.1.1560868818739; Tue, 18 Jun 2019 07:40:18 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.17 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:17 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 11/13] trace-cmd: Add setup-guest flag for attaching FIFOs to the guest VM config Date: Tue, 18 Jun 2019 17:39:56 +0300 Message-Id: <20190618143958.2865-12-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev This patch adds a flag for attaching the newly created FIFOs for guest tracing as virtio serial devices to libvirt managed guests. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- tracecmd/trace-setup-guest.c | 54 ++++++++++++++++++++++++++++++++++-- tracecmd/trace-usage.c | 3 +- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/tracecmd/trace-setup-guest.c b/tracecmd/trace-setup-guest.c index a55a37d..ae2fecb 100644 --- a/tracecmd/trace-setup-guest.c +++ b/tracecmd/trace-setup-guest.c @@ -111,7 +111,45 @@ static int get_guest_cpu_count(const char *guest) return nr_cpus; } -static void do_setup_guest(const char *guest, int nr_cpus, mode_t mode, gid_t gid) +static int attach_guest_fifos(const char *guest, int nr_cpus) +{ + const char *cmd_fmt = + "virsh attach-device --config '%s' '%s' >/dev/null 2>/dev/null"; + const char *xml_fmt = + "\n" + " \n" + " \n" + ""; + char tmp_path[PATH_MAX], path[PATH_MAX]; + char cmd[PATH_MAX], xml[PATH_MAX]; + int i, fd, ret = 0; + + strcpy(tmp_path, "/tmp/pipexmlXXXXXX"); + fd = mkstemp(tmp_path); + if (fd < 0) + return fd; + + for (i = 0; i < nr_cpus; i++) { + snprintf(path, sizeof(path), GUEST_FIFO_FMT, guest, i); + snprintf(xml, sizeof(xml), xml_fmt, path, GUEST_PIPE_NAME, i); + pwrite(fd, xml, strlen(xml), 0); + + snprintf(cmd, sizeof(cmd), cmd_fmt, guest, tmp_path); + errno = 0; + if (system(cmd) != 0) { + ret = -errno; + break; + } + } + + close(fd); + unlink(tmp_path); + + return ret; +} + +static void do_setup_guest(const char *guest, int nr_cpus, + mode_t mode, gid_t gid, bool attach) { gid_t save_egid; int ret; @@ -131,6 +169,12 @@ static void do_setup_guest(const char *guest, int nr_cpus, mode_t mode, gid_t gi if (ret < 0) pdie("failed to create FIFOs for %s", guest); + if (attach) { + ret = attach_guest_fifos(guest, nr_cpus); + if (ret < 0) + pdie("failed to attach FIFOs to %s", guest); + } + if (gid != -1) { ret = setegid(save_egid); if (ret < 0) @@ -140,6 +184,7 @@ static void do_setup_guest(const char *guest, int nr_cpus, mode_t mode, gid_t gi void trace_setup_guest(int argc, char **argv) { + bool attach = false; struct group *group; mode_t mode = 0660; int nr_cpus = -1; @@ -159,7 +204,7 @@ void trace_setup_guest(int argc, char **argv) {NULL, 0, NULL, 0} }; - c = getopt_long(argc-1, argv+1, "+hc:p:g:", + c = getopt_long(argc-1, argv+1, "+hc:p:g:a", long_options, &option_index); if (c == -1) break; @@ -179,6 +224,9 @@ void trace_setup_guest(int argc, char **argv) pdie("group %s does not exist", optarg); gid = group->gr_gid; break; + case 'a': + attach = true; + break; default: usage(argv); } @@ -195,5 +243,5 @@ void trace_setup_guest(int argc, char **argv) if (nr_cpus <= 0) pdie("invalid number of cpus for guest %s", guest); - do_setup_guest(guest, nr_cpus, mode, gid); + do_setup_guest(guest, nr_cpus, mode, gid, attach); } diff --git a/tracecmd/trace-usage.c b/tracecmd/trace-usage.c index a2a520c..ef709cf 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -251,10 +251,11 @@ static struct usage_help usage_help[] = { { "setup-guest", "create FIFOs for tracing guest VMs", - " %s setup-guest [-c cpus][-p perm][-g group] guest\n" + " %s setup-guest [-c cpus][-p perm][-g group][-a] guest\n" " -c number of guest virtual CPUs\n" " -p FIFOs permissions (default: 0660)\n" " -g FIFOs group owner\n" + " -a Attach FIFOs to guest VM config\n" }, #endif { From patchwork Tue Jun 18 14:39:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001893 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 6D96914BB for ; Tue, 18 Jun 2019 14:40:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B5702872F for ; Tue, 18 Jun 2019 14:40:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4F9142881C; Tue, 18 Jun 2019 14:40: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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 0C76E2872F for ; Tue, 18 Jun 2019 14:40:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729079AbfFROkZ (ORCPT ); Tue, 18 Jun 2019 10:40:25 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36725 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725919AbfFROkY (ORCPT ); Tue, 18 Jun 2019 10:40:24 -0400 Received: by mail-wm1-f68.google.com with SMTP id u8so3563986wmm.1 for ; Tue, 18 Jun 2019 07:40:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=94gMuCs4/MZor6v+HejbnssEp6N7JXowfvIjY9qgclE=; b=L+cyvP/EYetP8YDpcsx4UQcGsJJeQeOqIpFbFdZhiEPMbRuEKh/7phthGUx/7yAkGh 6c1jeMXlGUo5rbz4rAoIxAsPZh4HAg7Lfd9kYp3kHq9Ebi5leL7V/97yCqTgpJR002mp jGOVFC4yazJNgGtZCuijfzdKMAcVqpCdYFxuJOfzYexon1ddZZ/Al3tDXrZA45GsJUbU XX7adZG4OxVIz6u1eiKKOBWZBugS/B5oQHW35yoPUYafdDOBcja2N5zBYcXAyuGeRzfM lLNTRbeHcRlBBLMQvuA5KM5cpIcj4kI/uVyaL0NiA30rw+5oyzkuQisXRa7oWTF+Vjhv zZ9w== 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=94gMuCs4/MZor6v+HejbnssEp6N7JXowfvIjY9qgclE=; b=WMJjlFjQ7BRESI9GnLngnyIyVa9fzxMrO3VG2Sv8+TmGoae2CjsgaPYIgMbym0JSXQ Z5Znwp3Bo4Q9bE9PA6A+bc0C+SmRUkA+7fIo0pHXairuU6lw2+f+uwVOy+a9ybB0CHJt wjyllSIcsm486odCx/EtenWzX4GDAZ2V8KnvHWBO5pXDkQE92O67rWODWzh/1kBD+xQh 0e+zmgeSdP8Zn1xMF68em9WfnJHc8RCMLbhTHkvbLhhN4ErD5DYrNIW2ZOxxFwvqLo/C 5UwfWxblCtq/XGoEv04YcGXBPm08ZVo39hCkMiNPQPeTaoY8mN2uxG6kkhGoOgK5MhV0 W7aw== X-Gm-Message-State: APjAAAVK5y5suacySJG1YPaf5dNfxVoANVPdqs+MAvT33MTXhaqJYetV YNpPuFlmAz095hBoChrNNHGftEI= X-Google-Smtp-Source: APXvYqxsVoSqfb856ZVsHF6DBV2gTuT+J1CXSxz3WHM7ALMAMfDzQKOQObtzCEoJW7ferchODmLIFg== X-Received: by 2002:a1c:6154:: with SMTP id v81mr3904374wmb.92.1560868819722; Tue, 18 Jun 2019 07:40:19 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.18 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:19 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 12/13] trace-cmd: Add splice() recording from FIFO without additional pipe buffer Date: Tue, 18 Jun 2019 17:39:57 +0300 Message-Id: <20190618143958.2865-13-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev When `trace-cmd record` is reading tracing data over FIFO we can do a direct splice from the FIFO to the output file descriptor instead of doing two through an additional pipe buffer. This patch implements specialized tracecmd_recorder data transfer version for this case. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- include/trace-cmd/trace-cmd.h | 11 +++-- lib/trace-cmd/trace-recorder.c | 73 ++++++++++++++++++++++++---- tracecmd/include/trace-local.h | 4 +- tracecmd/trace-agent.c | 39 +++++++++++++-- tracecmd/trace-msg.c | 26 ++++++---- tracecmd/trace-record.c | 87 ++++++++++++++++++++++++++++++---- 6 files changed, 201 insertions(+), 39 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index db5baa8..9a984c1 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -274,8 +274,9 @@ struct tracecmd_output *tracecmd_get_output_handle_fd(int fd); enum { TRACECMD_RECORD_NOSPLICE = (1 << 0), /* Use read instead of splice */ - TRACECMD_RECORD_SNAPSHOT = (1 << 1), /* extract from snapshot */ + TRACECMD_RECORD_SNAPSHOT = (1 << 1), /* Extract from snapshot */ TRACECMD_RECORD_BLOCK = (1 << 2), /* Block on splice write */ + TRACECMD_RECORD_NOBRASS = (1 << 3), /* Splice directly without a brass pipe */ }; void tracecmd_free_recorder(struct tracecmd_recorder *recorder); @@ -338,16 +339,16 @@ 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 argc, char **argv, bool use_fifos); int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle, - int *argc, char ***argv); + int *argc, char ***argv, bool *use_fifos); int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle, int nr_cpus, int page_size, - unsigned int *ports); + unsigned int *ports, bool use_fifos); int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, int *nr_cpus, int *page_size, - unsigned int **ports); + unsigned int **ports, bool *use_fifos); /* --- Plugin handling --- */ extern struct tep_plugin_option trace_ftrace_options[]; diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index d57a5d6..bbba14c 100644 --- a/lib/trace-cmd/trace-recorder.c +++ b/lib/trace-cmd/trace-recorder.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,8 @@ # define SPLICE_F_GIFT 8 #endif +#define POLL_TIMEOUT_MS 1000 + struct tracecmd_recorder { int fd; int fd1; @@ -40,6 +43,7 @@ struct tracecmd_recorder { int pages; int count; unsigned fd_flags; + unsigned trace_fd_flags; unsigned flags; }; @@ -127,6 +131,8 @@ tracecmd_create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags, if (!(recorder->flags & TRACECMD_RECORD_BLOCK)) recorder->fd_flags |= SPLICE_F_NONBLOCK; + recorder->trace_fd_flags = SPLICE_F_MOVE; + /* Init to know what to free and release */ recorder->trace_fd = -1; recorder->brass[0] = -1; @@ -171,7 +177,8 @@ tracecmd_create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags, goto out_free; } - if ((recorder->flags & TRACECMD_RECORD_NOSPLICE) == 0) { + if (!(recorder->flags & (TRACECMD_RECORD_NOSPLICE | + TRACECMD_RECORD_NOBRASS))) { ret = pipe(recorder->brass); if (ret < 0) goto out_free; @@ -380,7 +387,7 @@ static long splice_data(struct tracecmd_recorder *recorder) long ret; read = splice(recorder->trace_fd, NULL, recorder->brass[1], NULL, - recorder->pipe_size, SPLICE_F_MOVE); + recorder->pipe_size, recorder->trace_fd_flags); if (read < 0) { if (errno == EAGAIN || errno == EINTR || errno == ENOTCONN) return 0; @@ -409,6 +416,47 @@ static long splice_data(struct tracecmd_recorder *recorder) return total_read; } +/* + * Returns -1 on error. + * or bytes of data read. + */ +static long direct_splice_data(struct tracecmd_recorder *recorder) +{ + struct pollfd pfd = { + .fd = recorder->trace_fd, + .events = POLLIN, + }; + long read; + int ret; + + /* + * splice(2) in Linux used to not check O_NONBLOCK flag of pipe file + * descriptors before [1]. To avoid getting blocked in the splice(2) + * call below after the user had requested to stop tracing, we poll(2) + * here. This poll() is not necessary on newer kernels. + * + * [1] https://github.com/torvalds/linux/commit/ee5e001196d1345b8fee25925ff5f1d67936081e + */ + ret = poll(&pfd, 1, POLL_TIMEOUT_MS); + if (ret < 0) + return -1; + + if (!(pfd.revents | POLLIN)) + return 0; + + read = splice(recorder->trace_fd, NULL, recorder->fd, NULL, + recorder->pipe_size, recorder->fd_flags); + if (read < 0) { + if (errno == EAGAIN || errno == EINTR || errno == ENOTCONN) + return 0; + + warning("recorder error in splice input"); + return -1; + } + + return read; +} + /* * Returns -1 on error. * or bytes of data read. @@ -443,6 +491,17 @@ static long read_data(struct tracecmd_recorder *recorder) return r; } +static long move_data(struct tracecmd_recorder *recorder) +{ + if (recorder->flags & TRACECMD_RECORD_NOSPLICE) + return read_data(recorder); + + if (recorder->flags & TRACECMD_RECORD_NOBRASS) + return direct_splice_data(recorder); + + return splice_data(recorder); +} + static void set_nonblock(struct tracecmd_recorder *recorder) { long flags; @@ -465,10 +524,7 @@ long tracecmd_flush_recording(struct tracecmd_recorder *recorder) set_nonblock(recorder); do { - if (recorder->flags & TRACECMD_RECORD_NOSPLICE) - ret = read_data(recorder); - else - ret = splice_data(recorder); + ret = move_data(recorder); if (ret < 0) return ret; total += ret; @@ -513,10 +569,7 @@ int tracecmd_start_recording(struct tracecmd_recorder *recorder, unsigned long s read = 0; do { - if (recorder->flags & TRACECMD_RECORD_NOSPLICE) - ret = read_data(recorder); - else - ret = splice_data(recorder); + ret = move_data(recorder); if (ret < 0) return ret; read += ret; diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index 93da7da..29d0bf8 100644 --- a/tracecmd/include/trace-local.h +++ b/tracecmd/include/trace-local.h @@ -17,6 +17,7 @@ #define GUEST_PIPE_NAME "trace-pipe-cpu" #define GUEST_DIR_FMT "/var/lib/trace-cmd/virt/%s" #define GUEST_FIFO_FMT GUEST_DIR_FMT "/" GUEST_PIPE_NAME "%d" +#define VIRTIO_FIFO_FMT "/dev/virtio-ports/" GUEST_PIPE_NAME "%d" extern int debug; extern int quiet; @@ -100,7 +101,7 @@ 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); + int argc, char **argv, bool use_fifos); struct hook_list; @@ -214,6 +215,7 @@ struct buffer_instance { unsigned int cid; unsigned int port; int *fds; + bool use_fifos; }; extern struct buffer_instance top_instance; diff --git a/tracecmd/trace-agent.c b/tracecmd/trace-agent.c index e1dfddf..71cb973 100644 --- a/tracecmd/trace-agent.c +++ b/tracecmd/trace-agent.c @@ -100,12 +100,38 @@ static void make_vsocks(int nr, int *fds, unsigned int *ports) } } +static int open_agent_fifos(int nr_cpus, int *fds) +{ + char path[PATH_MAX]; + int i, fd, ret; + + for (i = 0; i < nr_cpus; i++) { + snprintf(path, sizeof(path), VIRTIO_FIFO_FMT, i); + fd = open(path, O_WRONLY); + if (fd < 0) { + ret = -errno; + goto cleanup; + } + + fds[i] = fd; + } + + return 0; + +cleanup: + while (--i >= 0) + close(fds[i]); + + return ret; +} + static void agent_handle(int sd, int nr_cpus, int page_size) { struct tracecmd_msg_handle *msg_handle; unsigned int *ports; char **argv = NULL; int argc = 0; + bool use_fifos; int *fds; int ret; @@ -118,17 +144,22 @@ static void agent_handle(int sd, int nr_cpus, int page_size) if (!msg_handle) die("Failed to allocate message handle"); - ret = tracecmd_msg_recv_trace_req(msg_handle, &argc, &argv); + ret = tracecmd_msg_recv_trace_req(msg_handle, &argc, &argv, &use_fifos); if (ret < 0) die("Failed to receive trace request"); - make_vsocks(nr_cpus, fds, ports); + if (use_fifos && open_agent_fifos(nr_cpus, fds)) + use_fifos = false; + + if (!use_fifos) + make_vsocks(nr_cpus, fds, ports); - ret = tracecmd_msg_send_trace_resp(msg_handle, nr_cpus, page_size, ports); + ret = tracecmd_msg_send_trace_resp(msg_handle, nr_cpus, page_size, + ports, use_fifos); if (ret < 0) die("Failed to send trace response"); - trace_record_agent(msg_handle, nr_cpus, fds, argc, argv); + trace_record_agent(msg_handle, nr_cpus, fds, argc, argv, use_fifos); free(argv[0]); free(argv); diff --git a/tracecmd/trace-msg.c b/tracecmd/trace-msg.c index 69c7c5f..35a48c2 100644 --- a/tracecmd/trace-msg.c +++ b/tracecmd/trace-msg.c @@ -156,6 +156,10 @@ static int msg_write(int fd, struct tracecmd_msg *msg) return __do_write_check(fd, msg->buf, data_size); } +enum msg_trace_flags { + MSG_TRACE_USE_FIFOS = 1 << 0, +}; + static int make_tinit(struct tracecmd_msg_handle *msg_handle, struct tracecmd_msg *msg) { @@ -807,7 +811,7 @@ int tracecmd_msg_wait_close_resp(struct tracecmd_msg_handle *msg_handle) return tracecmd_msg_wait_for_cmd(msg_handle, MSG_CLOSE_RESP); } -static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv) +static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv, bool use_fifos) { size_t args_size = 0; char *p; @@ -817,6 +821,7 @@ static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv) args_size += strlen(argv[i]) + 1; msg->hdr.size = htonl(ntohl(msg->hdr.size) + args_size); + msg->trace_req.flags = use_fifos ? htonl(MSG_TRACE_USE_FIFOS) : htonl(0); msg->trace_req.argc = htonl(argc); msg->buf = calloc(args_size, 1); if (!msg->buf) @@ -830,13 +835,13 @@ static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv) } int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle, - int argc, char **argv) + int argc, char **argv, bool use_fifos) { struct tracecmd_msg msg; int ret; tracecmd_msg_init(MSG_TRACE_REQ, &msg); - ret = make_trace_req(&msg, argc, argv); + ret = make_trace_req(&msg, argc, argv, use_fifos); if (ret < 0) return ret; @@ -849,7 +854,7 @@ int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle, * free(argv); */ int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle, - int *argc, char ***argv) + int *argc, char ***argv, bool *use_fifos) { struct tracecmd_msg msg; char *p, *buf_end, **args; @@ -895,6 +900,7 @@ int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle, *argc = nr_args; *argv = args; + *use_fifos = ntohl(msg.trace_req.flags) & MSG_TRACE_USE_FIFOS; /* * On success we're passing msg.buf to the caller through argv[0] so we @@ -914,8 +920,8 @@ out: return ret; } -static int make_trace_resp(struct tracecmd_msg *msg, - int page_size, int nr_cpus, unsigned int *ports) +static int make_trace_resp(struct tracecmd_msg *msg, int page_size, int nr_cpus, + unsigned int *ports, bool use_fifos) { int data_size; @@ -926,6 +932,7 @@ static int make_trace_resp(struct tracecmd_msg *msg, write_uints(msg->buf, data_size, ports, nr_cpus); msg->hdr.size = htonl(ntohl(msg->hdr.size) + data_size); + msg->trace_resp.flags = use_fifos ? htonl(MSG_TRACE_USE_FIFOS) : htonl(0); msg->trace_resp.cpus = htonl(nr_cpus); msg->trace_resp.page_size = htonl(page_size); @@ -934,13 +941,13 @@ static int make_trace_resp(struct tracecmd_msg *msg, int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle, int nr_cpus, int page_size, - unsigned int *ports) + unsigned int *ports, bool use_fifos) { struct tracecmd_msg msg; int ret; tracecmd_msg_init(MSG_TRACE_RESP, &msg); - ret = make_trace_resp(&msg, page_size, nr_cpus, ports); + ret = make_trace_resp(&msg, page_size, nr_cpus, ports, use_fifos); if (ret < 0) return ret; @@ -949,7 +956,7 @@ int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle, int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, int *nr_cpus, int *page_size, - unsigned int **ports) + unsigned int **ports, bool *use_fifos) { struct tracecmd_msg msg; char *p, *buf_end; @@ -971,6 +978,7 @@ int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, goto out; } + *use_fifos = ntohl(msg.trace_resp.flags) & MSG_TRACE_USE_FIFOS; *nr_cpus = ntohl(msg.trace_resp.cpus); *page_size = ntohl(msg.trace_resp.page_size); *ports = calloc(*nr_cpus, sizeof(**ports)); diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index d98cd39..89e2c52 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -77,6 +77,8 @@ static int buffers; /* Clear all function filters */ static int clear_function_filters; +static bool no_fifos; + static char *host; /* Max size to let a per cpu file get */ @@ -2970,12 +2972,17 @@ create_recorder_instance(struct buffer_instance *instance, const char *file, int int fd; unsigned int flags; - fd = open_vsock(instance->cid, instance->client_ports[cpu]); + if (instance->use_fifos) + fd = instance->fds[cpu]; + else + fd = open_vsock(instance->cid, instance->client_ports[cpu]); if (fd < 0) die("Failed to connect to agent"); flags = recorder_flags; - if (!can_splice_read_vsock()) + if (instance->use_fifos) + flags |= TRACECMD_RECORD_NOBRASS; + else if (!can_splice_read_vsock()) flags |= TRACECMD_RECORD_NOSPLICE; return tracecmd_create_recorder_virt(file, cpu, flags, fd); } @@ -3030,10 +3037,14 @@ static int create_recorder(struct buffer_instance *instance, int cpu, char *path = NULL; int fd; - if (is_agent(instance)) - fd = do_accept(instance->fds[cpu]); - else + if (is_agent(instance)) { + if (instance->use_fifos) + fd = instance->fds[cpu]; + else + fd = do_accept(instance->fds[cpu]); + } else { fd = connect_port(host, instance->client_ports[cpu]); + } if (fd < 0) die("Failed connecting to client"); if (instance->name && !is_agent(instance)) @@ -3314,11 +3325,42 @@ static void finish_network(struct tracecmd_msg_handle *msg_handle) free(host); } +static int open_guest_fifos(const char *guest, int **fds) +{ + char path[PATH_MAX]; + int i, fd, flags; + + for (i = 0; ; i++) { + snprintf(path, sizeof(path), GUEST_FIFO_FMT ".out", guest, i); + + /* O_NONBLOCK so we don't wait for writers */ + fd = open(path, O_RDONLY | O_NONBLOCK); + if (fd < 0) + break; + + /* Success, now clear O_NONBLOCK */ + flags = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + + *fds = realloc(*fds, i + 1); + (*fds)[i] = fd; + } + + return i; +} + static void connect_to_agent(struct buffer_instance *instance) { struct tracecmd_msg_handle *msg_handle; - int sd, ret, nr_cpus, page_size; + int sd, ret, nr_fifos, nr_cpus, page_size; unsigned int *ports; + int i, *fds = NULL; + bool use_fifos = false; + + if (!no_fifos) { + nr_fifos = open_guest_fifos(instance->name, &fds); + use_fifos = nr_fifos > 0; + } sd = open_vsock(instance->cid, instance->port); if (sd < 0) @@ -3329,15 +3371,33 @@ static void connect_to_agent(struct buffer_instance *instance) if (!msg_handle) die("Failed to allocate message handle"); - ret = tracecmd_msg_send_trace_req(msg_handle, instance->argc, instance->argv); + ret = tracecmd_msg_send_trace_req(msg_handle, instance->argc, + instance->argv, use_fifos); if (ret < 0) die("Failed to send trace request"); - ret = tracecmd_msg_recv_trace_resp(msg_handle, &nr_cpus, &page_size, &ports); + ret = tracecmd_msg_recv_trace_resp(msg_handle, &nr_cpus, &page_size, + &ports, &use_fifos); if (ret < 0) die("Failed to receive trace response"); - instance->client_ports = ports; + if (use_fifos) { + if (nr_cpus != nr_fifos) { + warning("number of FIFOs (%d) for guest %s differs " + "from number of virtual CPUs (%d)", + nr_fifos, instance->name, nr_cpus); + nr_cpus = nr_cpus < nr_fifos ? nr_cpus : nr_fifos; + } + free(ports); + instance->fds = fds; + } else { + for (i = 0; i < nr_fifos; i++) + close(fds[i]); + free(fds); + instance->client_ports = ports; + } + + instance->use_fifos = use_fifos; instance->cpu_count = nr_cpus; /* the msg_handle now points to the guest fd */ @@ -4863,6 +4923,7 @@ enum { OPT_funcstack = 254, OPT_date = 255, OPT_module = 256, + OPT_nofifos = 257, }; void trace_stop(int argc, char **argv) @@ -5133,6 +5194,7 @@ static void parse_record_options(int argc, {"date", no_argument, NULL, OPT_date}, {"func-stack", no_argument, NULL, OPT_funcstack}, {"nosplice", no_argument, NULL, OPT_nosplice}, + {"nofifos", no_argument, NULL, OPT_nofifos}, {"profile", no_argument, NULL, OPT_profile}, {"stderr", no_argument, NULL, OPT_stderr}, {"by-comm", no_argument, NULL, OPT_bycomm}, @@ -5421,6 +5483,9 @@ static void parse_record_options(int argc, case OPT_nosplice: recorder_flags |= TRACECMD_RECORD_NOSPLICE; break; + case OPT_nofifos: + no_fifos = true; + break; case OPT_profile: handle_init = trace_init_profile; ctx->instance->flags |= BUFFER_FL_PROFILE; @@ -5828,7 +5893,8 @@ void trace_record(int argc, char **argv) int trace_record_agent(struct tracecmd_msg_handle *msg_handle, int cpus, int *fds, - int argc, char **argv) + int argc, char **argv, + bool use_fifos) { struct common_record_context ctx; char **argv_plus; @@ -5854,6 +5920,7 @@ int trace_record_agent(struct tracecmd_msg_handle *msg_handle, return -EINVAL; ctx.instance->fds = fds; + ctx.instance->use_fifos = use_fifos; ctx.instance->flags |= BUFFER_FL_AGENT; ctx.instance->msg_handle = msg_handle; msg_handle->version = V3_PROTOCOL; From patchwork Tue Jun 18 14:39:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 11001891 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 B72C514BB for ; Tue, 18 Jun 2019 14:40:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A55352847D for ; Tue, 18 Jun 2019 14:40:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9984C28718; Tue, 18 Jun 2019 14:40: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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 385842847D for ; Tue, 18 Jun 2019 14:40:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729394AbfFROkX (ORCPT ); Tue, 18 Jun 2019 10:40:23 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:55555 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729204AbfFROkW (ORCPT ); Tue, 18 Jun 2019 10:40:22 -0400 Received: by mail-wm1-f67.google.com with SMTP id a15so3582318wmj.5 for ; Tue, 18 Jun 2019 07:40:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PH2N4AFbJRZ/0SmO4j9bcgaibrXsk3kHJYVCHlKxxt8=; b=mA0ezHJl+Tj1QC/iciZvUREMWgZ8Nu+hoLXf5UG3eNclZ2ZXbwgLFhCCs2k6go0am2 EyiDREtIvRoIOb0CJ3JYS5IDmNnuFsMyN/7BE75q2YnQ8k89OmIRgOUiJDgxZ8afm2p6 5d4iH5/CVjUjvcGWsmmJfgkDI8Qib6Ul1zIhw+s67W6v2PRttypSe8J8NTPTHCGWzzzp bviJOXV18/zCV30yuBrgfu2g4W2TLOZN8bGEVj+TL7vNphymJUrD4C2XzDdEMSnQPhbH UHfn1Diy2U769EspZWdBYEGXPcygdeFb4KHchYu90q90VTbgIUvo9PE/PCqqTD16NIpc w+6w== 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=PH2N4AFbJRZ/0SmO4j9bcgaibrXsk3kHJYVCHlKxxt8=; b=e5fkL+qFiucdcQEfNq/jQ+DBnWTpdUZ345GoGSWIJzlGA89LuRMwJejlHR896ob8xv NQxtf3NTgaaeuVcpOkIJr4t6B6iBzqOlwKRV4410Dvnr3x1gHU1f1moUkqZwPVQ9Sgum 3+0L++K2Y5KH5WK3NSzmQq8WFTw5xqXerrppv5u0Vop+TBwx6wvSLYESD349YFVVgxmG ssHLP4iKlP301+f4wUs7rHZXG+Eqs2lnkIQzRgnNE4B6A5hkborRMVoUS1Ey7SbGQEN2 AZR/kPzwpVeI8txSzKf7Pe3WITYOB5p0KwWRvN6N2g2atUy730W755l/EAzqQCqy1uuT tgCw== X-Gm-Message-State: APjAAAWbKDZAb3iwo0x9q/SHLVUy1edWqPA9MlXbxpEiPiMttx/pmZCo XtX08kITd0o4L1+yv/LK6y75WvI= X-Google-Smtp-Source: APXvYqxjIj8rAxYIhR9wvV+7WpdRQlf5mEZpbc5kXG05eq+XQW9ZmxnL3I/FW3PZdKhp6TIYvyY2iA== X-Received: by 2002:a1c:7503:: with SMTP id o3mr3937021wmc.170.1560868820883; Tue, 18 Jun 2019 07:40:20 -0700 (PDT) Received: from box.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id y1sm2411808wma.32.2019.06.18.07.40.19 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 18 Jun 2019 07:40:20 -0700 (PDT) From: "Slavomir Kaslev (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v11 13/13] trace-cmd: Add support for tracing VMware Workstation VMs by name Date: Tue, 18 Jun 2019 17:39:58 +0300 Message-Id: <20190618143958.2865-14-slavomir.kaslev@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190618143958.2865-1-slavomir.kaslev@gmail.com> References: <20190618143958.2865-1-slavomir.kaslev@gmail.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: Slavomir Kaslev Read display name and CID of running VMware Workstation guests on startup so that users can refer to them by name when recording. Signed-off-by: Slavomir Kaslev Signed-off-by: Slavomir Kaslev (VMware) --- tracecmd/trace-record.c | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 89e2c52..b242f34 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -2892,6 +2892,75 @@ next: closedir(dir); } +static int load_vmw_guest(const char *vm, char **name, int *cid) +{ + size_t line_len = 0; + char *line = NULL; + char *p; + FILE *f; + + f = fopen(vm, "r"); + if (!f) + return -errno; + + *cid = -1; + *name = NULL; + while (getline(&line, &line_len, f) != -1) { + if (strncmp(line, "displayName = ", 14) == 0) { + p = strrchr(line, '"'); + if (p) + *p = '\0'; + *name = strdup(line + 15); + } else if (strncmp(line, "vmci0.id = ", 11) == 0) { + p = strrchr(line, '"'); + if (p) + *p = '\0'; + *cid = atoi(line + 12); + } + } + + free(line); + fclose(f); + return 0; +} + +static void read_vmw_guests(void) +{ + static bool initialized; + size_t line_len = 0; + char *line = NULL; + ssize_t ret; + FILE *f; + + if (initialized) + return; + + initialized = true; + + f = popen("vmrun list", "r"); + if (!f) + return; + + /* Ignore the first line */ + ret = getline(&line, &line_len, f); + while ((ret = getline(&line, &line_len, f)) != -1) { + struct guest guest = {}; + + if (ret > 0 && line[ret-1] == '\n') + line[ret-1] = '\0'; + if (load_vmw_guest(line, &guest.name, &guest.cid)) + continue; + + guests = realloc(guests, (guests_len + 1) * sizeof(*guests)); + if (!guests) + die("Can not allocate guest buffer"); + guests[guests_len++] = guest; + } + + free(line); + pclose(f); +} + static char *parse_guest_name(char *guest, int *cid, int *port) { size_t i; @@ -2913,6 +2982,7 @@ static char *parse_guest_name(char *guest, int *cid, int *port) *cid = atoi(guest); read_qemu_guests(); + read_vmw_guests(); for (i = 0; i < guests_len; i++) { if ((*cid > 0 && *cid == guests[i].cid) || strcmp(guest, guests[i].name) == 0) {