From patchwork Mon Feb 18 14:54:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818297 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 DE3A31399 for ; Mon, 18 Feb 2019 14:55:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CA9D82B07A for ; Mon, 18 Feb 2019 14:55:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C8BD22B073; Mon, 18 Feb 2019 14:55:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5F98F2B073 for ; Mon, 18 Feb 2019 14:55:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729505AbfBROzA (ORCPT ); Mon, 18 Feb 2019 09:55:00 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:46528 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728893AbfBROzA (ORCPT ); Mon, 18 Feb 2019 09:55:00 -0500 Received: by mail-wr1-f68.google.com with SMTP id i16so10451008wrs.13 for ; Mon, 18 Feb 2019 06:54:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=f381mcVQ+N5PnipoSDp4SrS6oARs5fbXaT6Ys7gW6/c=; b=q6b51pu0Y4fMqnViypMnZOmUm+2daVysKVCRMycaPdSlUOeMALKaScOkw4rma/B1SN Y+C8KRTMJmozd2gQYzeHAozdfmRJUbz9ev0N1y+m2QA6cQczftx4BgF7RoZb1sW6OUPt COc3tYmlrzJQpxPfPa9b486IrbAdYczLGsbrPSh69rEePCnLkk++EfPzMevgSh+nk3Fa cbxoVFFTLc8iDR1toDtWHpBN50krH16ATQwARHZggIgMcrd4xq4c6BFbMMY+1bX9NJ1O ZwMAVJuI7vnqMCJ8vARkrsrDKQ37LWn+D7GvI9n1RMp5Jdt+WDFR40VENozCCru5sCUl SVWA== X-Gm-Message-State: AHQUAua2rCa4VsNhX1730nRULewcfQZTh1YqEEbkBFJlGfxfoYlFfiZj /ihQjJkZKyYBKSvQScY9Tw== X-Google-Smtp-Source: AHgI3Iah3T3AvvMa65vRWChiQ+jgeAAldqUY43Wp+fIHPUSlD3nTjCBlGYVOKT8rex29+FDdhMMacA== X-Received: by 2002:a5d:550f:: with SMTP id b15mr18074830wrv.251.1550501698309; Mon, 18 Feb 2019 06:54:58 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.54.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:54:57 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 01/13] trace-cmd: Minor cleanup in tracecmd_start_recording() Date: Mon, 18 Feb 2019 16:54:37 +0200 Message-Id: <20190218145449.13360-2-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Initialize `struct timespec req` only once instead of on every loop iteration since `sleep` is being constant throughout tracecmd_start_recording() execution. No changes in behavior intended. Signed-off-by: Slavomir Kaslev --- lib/trace-cmd/trace-recorder.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index 0b8d98a..0bd0657 100644 --- a/lib/trace-cmd/trace-recorder.c +++ b/lib/trace-cmd/trace-recorder.c @@ -466,7 +466,10 @@ long tracecmd_flush_recording(struct tracecmd_recorder *recorder) int tracecmd_start_recording(struct tracecmd_recorder *recorder, unsigned long sleep) { - struct timespec req; + struct timespec req = { + .tv_sec = sleep / 1000000, + .tv_nsec = (sleep % 1000000) * 1000, + }; long read = 1; long ret; @@ -474,11 +477,9 @@ int tracecmd_start_recording(struct tracecmd_recorder *recorder, unsigned long s do { /* Only sleep if we did not read anything last time */ - if (!read && sleep) { - req.tv_sec = sleep / 1000000; - req.tv_nsec = (sleep % 1000000) * 1000; + if (!read && sleep) nanosleep(&req, NULL); - } + read = 0; do { if (recorder->flags & TRACECMD_RECORD_NOSPLICE) From patchwork Mon Feb 18 14:54:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818299 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 7C50B1399 for ; Mon, 18 Feb 2019 14:55:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6B9882B091 for ; Mon, 18 Feb 2019 14:55:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5EA5D2B09C; Mon, 18 Feb 2019 14:55:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 06E502B083 for ; Mon, 18 Feb 2019 14:55:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729901AbfBROzB (ORCPT ); Mon, 18 Feb 2019 09:55:01 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:43392 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728893AbfBROzB (ORCPT ); Mon, 18 Feb 2019 09:55:01 -0500 Received: by mail-wr1-f67.google.com with SMTP id d17so4272380wre.10 for ; Mon, 18 Feb 2019 06:55:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=iu4Fyc42UQyrYE5Tk++BlWaRY8br2iwqhsYk9tm7HOQ=; b=thUG4chP4fie40RxZy4T6P810aBc7cyxMbEFGcdREw/T8ti7gxVetjpbPGVQqb8dX3 XP7ES7pcuamwx968LUqg6K1HSyfDcINg+i8GGI0SvrpXJg474o3rUW6ZCzJ1ybrR65bb DAY33NCBmNAoqchUMUph+lh/msJNQ8dY3nopqVL01ZM5Y86xmC+V3AH22zPFnjhkBQ6B h01DYkjKxYfvoPefl7Y6F7WBnA+u8C2Neb4W/bU0xjWwTCkMfVzDEORnaRvFuYwhKwIu XFaKNEMtYlzgXjSfQuSLVF1lQ8dClRB8m3BZ5mzG6/NtrPiGtWA+bdEhCv08AprsqzUc zGJA== X-Gm-Message-State: AHQUAubU+PswCiIuJmnWExlJSjViL+av0lHBHqXJYl62sNLvIqfTUx9X JjwjLS5uVhNxpcfb4T4NaAkal9U= X-Google-Smtp-Source: AHgI3IYYHuq5lq/loQsx6l2aWC1q9c+7XH5rr+l5erDbOHyx2LUYtbY9pqRTfnwcWKTMFF745SyZVw== X-Received: by 2002:adf:f70c:: with SMTP id r12mr16772266wrp.54.1550501699691; Mon, 18 Feb 2019 06:54:59 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.54.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:54:59 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 02/13] trace-cmd: Minor cleanup in print_stat() Date: Mon, 18 Feb 2019 16:54:38 +0200 Message-Id: <20190218145449.13360-3-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Do an early out in print_stat() when `quiet` is set instead of rechecking it on each loop iteration. No changes in behavior intended. Signed-off-by: Slavomir Kaslev --- tracecmd/trace-record.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 8beefab..88b4a55 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -3106,13 +3106,14 @@ static void print_stat(struct buffer_instance *instance) { int cpu; + if (quiet) + return; + if (!is_top_instance(instance)) - if (!quiet) - printf("\nBuffer: %s\n\n", instance->name); + printf("\nBuffer: %s\n\n", instance->name); for (cpu = 0; cpu < instance->cpu_count; cpu++) - if (!quiet) - trace_seq_do_printf(&instance->s_print[cpu]); + trace_seq_do_printf(&instance->s_print[cpu]); } enum { From patchwork Mon Feb 18 14:54:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818301 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 1CCD114E1 for ; Mon, 18 Feb 2019 14:55:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0A7282B094 for ; Mon, 18 Feb 2019 14:55:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F2D052B0A1; Mon, 18 Feb 2019 14:55:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7B9732B09F for ; Mon, 18 Feb 2019 14:55:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728893AbfBROzC (ORCPT ); Mon, 18 Feb 2019 09:55:02 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:40095 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729852AbfBROzC (ORCPT ); Mon, 18 Feb 2019 09:55:02 -0500 Received: by mail-wr1-f66.google.com with SMTP id q1so18696817wrp.7 for ; Mon, 18 Feb 2019 06:55:01 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ebx/6PKF298evGUiQpbCn8tno+rQu+UODpYT6m+zsg0=; b=HlIUzZs1A9w0l+QpPmgeL5iMmxI7IDrmqJBBTFKcu0Dfk5g6UAfPoCyIMVN25BylxR 54u29xsrHZuoLXOdB2EkqcWgA6NaRaIdL9bVZ6XItRLa4ZRkcOcZOY9F6CY2KsnW7i5F Wx12tjv7ne0/lV99a48SOtNPq0snQwDEilC35QFi3NY5iGGB2zfmUXsz14IpP48BCQDl 9/3s6YJG7Duwvg/b5XyX99WXXrecNWDkcZMAlMCye7orV/B6upwh0eJF01OT3VBGlaGF zAY0PiDp2stcztFw3mxWV74wJlsPLCtCcOpyLYO1jBKhmTR2BK6AsuZirr4Xg4mYZ21l L4Cw== X-Gm-Message-State: AHQUAubSVF4xwh5fD9ksSrP60BhykHQwaqskU768FPOX4j98Un27xK8E 2pFoPD2CKzXPACzfQM/sAw== X-Google-Smtp-Source: AHgI3IYZ5kRURiY4zF1l7ylMtEI/MVhYQg6g3p14uXcoktNOWq0K4f6Iou+HEf4FDuBBMBaRcw/zCw== X-Received: by 2002:adf:d845:: with SMTP id k5mr17254192wrl.145.1550501700969; Mon, 18 Feb 2019 06:55:00 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.54.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:00 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 03/13] trace-cmd: Detect if vsockets are available Date: Mon, 18 Feb 2019 16:54:39 +0200 Message-Id: <20190218145449.13360-4-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Steven Rostedt (VMware)" Detect and define VSOCK if 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 --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index b780718..99e4f39 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 Mon Feb 18 14:54:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818315 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 6EB6E1399 for ; Mon, 18 Feb 2019 14:55:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B1FC2B049 for ; Mon, 18 Feb 2019 14:55:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4F56E2B073; Mon, 18 Feb 2019 14:55: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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AB5732B0A9 for ; Mon, 18 Feb 2019 14:55:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730046AbfBROzE (ORCPT ); Mon, 18 Feb 2019 09:55:04 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:38202 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729852AbfBROzE (ORCPT ); Mon, 18 Feb 2019 09:55:04 -0500 Received: by mail-wr1-f67.google.com with SMTP id v13so18685063wrw.5 for ; Mon, 18 Feb 2019 06:55:03 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=M+/It+j7FfoUaH8l9PeGEnMn/KnpXFCDAhrtUlvjwME=; b=b7WViG7aqaY2V01LEsj9SRVwSh4SwGmZJe8e8aq5ipoRdDEEa15nYoQs7Eln9ZsCm1 iO5MZNEEIx4GMnWjxxKE8/JV6LSLGd9h5tAhpdKNl1Ii2nuqLqBJ1+hVU5maeeDjwZ4k CeD7Mpzqd+R7blLnODNgV+0cz+BPc96UpjbheItJtLMaF7rqpyMysB+B/EbtieiNTsn8 rFQL/yBdvWguV/JB71nPXe9kv39hQNkXnkwOGXOcK761OmQtPYqG1MLNdwCibp4gXmJQ ccAoTBn8WhYuStzOutIyqk2eSnhMeDrcF05C9ZYCqAPZFP+8DrcAacwYoUByRvwFsajb MSwg== X-Gm-Message-State: AHQUAuboe5wujfsjIt8xmrdeTN4OSW9ve5q5hpMUK9FjzVdvmXQzqxW3 0JXNYO6vTbu/alDlDVpD7A== X-Google-Smtp-Source: AHgI3IYwkCaRInpsoL2RX6Wt9v2ylYz1K+Ztvck2hZcf30dEawW/Kw6smtZce7o5dXyp1IR8b6jB3w== X-Received: by 2002:adf:deca:: with SMTP id i10mr16177368wrn.312.1550501702280; Mon, 18 Feb 2019 06:55:02 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:01 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 04/13] trace-cmd: Add tracecmd_create_recorder_virt function Date: Mon, 18 Feb 2019 16:54:40 +0200 Message-Id: <20190218145449.13360-5-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add tracecmd_create_recorder_virt function that will be used for tracing VM guests. Signed-off-by: Slavomir Kaslev --- include/trace-cmd/trace-cmd.h | 1 + lib/trace-cmd/trace-recorder.c | 53 ++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index ca4452b..5961355 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -277,6 +277,7 @@ enum { void tracecmd_free_recorder(struct tracecmd_recorder *recorder); struct tracecmd_recorder *tracecmd_create_recorder(const char *file, int cpu, unsigned flags); struct tracecmd_recorder *tracecmd_create_recorder_fd(int fd, int cpu, unsigned flags); +struct tracecmd_recorder *tracecmd_create_recorder_virt(const char *file, int cpu, unsigned flags, int trace_fd); struct tracecmd_recorder *tracecmd_create_recorder_maxkb(const char *file, int cpu, unsigned flags, int maxkb); struct tracecmd_recorder *tracecmd_create_buffer_recorder_fd(int fd, int cpu, unsigned flags, const char *buffer); struct tracecmd_recorder *tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags, const char *buffer); diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index 0bd0657..1b84bb5 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,26 @@ tracecmd_create_buffer_recorder_maxkb(const char *file, int cpu, unsigned flags, goto out; } +struct tracecmd_recorder * +tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags, + const char *buffer) +{ + return __tracecmd_create_buffer_recorder(file, cpu, flags, buffer); +} + +struct tracecmd_recorder * +tracecmd_create_recorder_virt(const char *file, int cpu, unsigned flags, + int trace_fd) +{ + struct tracecmd_recorder *recorder; + + recorder = __tracecmd_create_buffer_recorder(file, cpu, flags, NULL); + if (recorder) + recorder->trace_fd = trace_fd; + + return recorder; +} + struct tracecmd_recorder *tracecmd_create_recorder_fd(int fd, int cpu, unsigned flags) { const char *tracing; From patchwork Mon Feb 18 14:54:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818303 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 071681399 for ; Mon, 18 Feb 2019 14:55:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E6B012B09C for ; Mon, 18 Feb 2019 14:55:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DAB922B09F; Mon, 18 Feb 2019 14:55:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3CFEE2B0AF for ; Mon, 18 Feb 2019 14:55:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730192AbfBROzG (ORCPT ); Mon, 18 Feb 2019 09:55:06 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:50929 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729907AbfBROzF (ORCPT ); Mon, 18 Feb 2019 09:55:05 -0500 Received: by mail-wm1-f66.google.com with SMTP id x7so17591474wmj.0 for ; Mon, 18 Feb 2019 06:55:04 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RXgZSquThHimJvewGfohGUh7Fkzgv8cmOEiMdA0aLos=; b=tMT6LWwKli6G8eCXFLVpXcwGtyUGsi42iVp1FPbV0BFWWPuxWszcIPw4mGmlZ3NdRi 1pLENqoM/gKopAIkJVSsW1TUp+imbPVH218c1/1eYRJcj6MHdY+lSIigESpxRkmIJGKD sgp0rCbnvHQyl9fHS3AFz8WKdVbDfKZa8Dr3fn3Oh2qKxyt0KJxyhrnvRcV/v5EAWZxf f+kBEVjDr7DBpf8hE0CBsxA0YAyRKdAUQ9HDVqFQoH99M0XwmJwkq5JEiRIO/2149n0S fmWtoDoVv3Hkqix/psag6FTyFbS8qrt/USzFADFUL3EAgxkzRoJRQrEjoIdmeumZ89Qj ESmQ== X-Gm-Message-State: AHQUAuauNFN8vlJwVJuGk20c+MoNHzipc7zHbuH+uMIVb+XmpulitEOM fSI5a6EV3bo4JaVSpjKO6A== X-Google-Smtp-Source: AHgI3IbniDSiNeAcq3FqFmjEBETYDPEKiiqJAgI1h044wlvwn7FY/O+iS/lCfNy5bXUrONasiavR2Q== X-Received: by 2002:a1c:7c10:: with SMTP id x16mr15960487wmc.98.1550501703499; Mon, 18 Feb 2019 06:55:03 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:02 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 05/13] trace-cmd: Add TRACE_REQ and TRACE_RESP messages Date: Mon, 18 Feb 2019 16:54:41 +0200 Message-Id: <20190218145449.13360-6-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add TRACE_REQ and TRACE_RESP messages which are used for initiating guest VM tracing. Signed-off-by: Slavomir Kaslev --- include/trace-cmd/trace-cmd.h | 12 ++ tracecmd/trace-msg.c | 211 +++++++++++++++++++++++++++++++++- 2 files changed, 222 insertions(+), 1 deletion(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 5961355..6a21e66 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -331,6 +331,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 51d0ac8..8ce1f98 100644 --- a/tracecmd/trace-msg.c +++ b/tracecmd/trace-msg.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,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; @@ -76,7 +88,9 @@ 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)), #undef C #define C(a,b,c) MSG_##a = b @@ -108,6 +122,8 @@ struct tracecmd_msg { union { struct tracecmd_msg_tinit tinit; struct tracecmd_msg_rinit rinit; + struct tracecmd_msg_trace_req trace_req; + struct tracecmd_msg_trace_resp trace_resp; }; union { struct tracecmd_msg_opt *opt; @@ -723,3 +739,196 @@ error: msg_free(&msg); return ret; } + +static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv) +{ + size_t args_size = 0; + char *p; + int i; + + for (i = 0; i < argc; i++) + args_size += strlen(argv[i]) + 1; + + msg->hdr.size = htonl(ntohl(msg->hdr.size) + args_size); + msg->trace_req.argc = htonl(argc); + msg->buf = calloc(args_size, 1); + if (!msg->buf) + return -ENOMEM; + + p = msg->buf; + for (i = 0; i < argc; i++) + p = stpcpy(p, argv[i]) + 1; + + return 0; +} + +int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle, + int argc, char **argv) +{ + struct tracecmd_msg msg; + int ret; + + tracecmd_msg_init(MSG_TRACE_REQ, &msg); + ret = make_trace_req(&msg, argc, argv); + if (ret < 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; + } + + p = msg.buf; + for (i = 0; i < nr_args; i++) { + if (p >= buf_end) { + ret = -EINVAL; + goto out_args; + } + args[i] = p; + p = strchr(p, '\0'); + if (!p) { + ret = -EINVAL; + goto out_args; + } + p++; + } + + *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 ports_size = nr_cpus * sizeof(*msg->port_array); + int i; + + msg->hdr.size = htonl(ntohl(msg->hdr.size) + ports_size); + msg->trace_resp.cpus = htonl(nr_cpus); + msg->trace_resp.page_size = htonl(page_size); + + msg->port_array = malloc(ports_size); + if (!msg->port_array) + return -ENOMEM; + + for (i = 0; i < nr_cpus; i++) + msg->port_array[i] = htonl(ports[i]); + + return 0; +} + +int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle, + int nr_cpus, int page_size, + unsigned int *ports) +{ + struct tracecmd_msg msg; + int ret; + + tracecmd_msg_init(MSG_TRACE_RESP, &msg); + ret = make_trace_resp(&msg, page_size, nr_cpus, ports); + if (ret < 0) + return ret; + + return tracecmd_msg_send(msg_handle->fd, &msg); +} + +int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, + int *nr_cpus, int *page_size, + unsigned int **ports) +{ + struct tracecmd_msg msg; + 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 = ntohl(msg.hdr.size) - MSG_HDR_LEN - ntohl(msg.hdr.cmd_size); + if (buf_len <= 0 || + buf_len != sizeof(*msg.port_array) * ntohl(msg.trace_resp.cpus)) { + ret = -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; + } + for (i = 0; i < *nr_cpus; i++) + (*ports)[i] = ntohl(msg.port_array[i]); + + 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 Mon Feb 18 14:54:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818305 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 BB6431399 for ; Mon, 18 Feb 2019 14:55:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A972F2B065 for ; Mon, 18 Feb 2019 14:55:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9E2AC2B0A1; Mon, 18 Feb 2019 14:55:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19E6B2B09C for ; Mon, 18 Feb 2019 14:55:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729486AbfBROzG (ORCPT ); Mon, 18 Feb 2019 09:55:06 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:40134 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729852AbfBROzG (ORCPT ); Mon, 18 Feb 2019 09:55:06 -0500 Received: by mail-wm1-f67.google.com with SMTP id t15so9294508wmi.5 for ; Mon, 18 Feb 2019 06:55:05 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bNhbI8A5zOJsUo1DBRgcSYQnXoPahguhhLm9/ue9CDA=; b=hZp3nX3WzwazSctkqys+NM836JKvlnord+zwVtNh81P0SVgTiDh4A6GMcgQmkv3zFT xtmG/9vkwMl3LAd7HcVVP96wBV0Z3jJz6ph1e/Y/pyPECQIUchcWNlXleLQ7T6vfw/y2 Xyr6Z3DnsKIWJHFHDGVhsiZ64VSV+JUTLT+52k+Ay4TQDj63gxh98+/SxUwmA5ayFlWN G3MQenWooDSJ4prV1SOprm7X66Ltmk/LSg4uZMs9YKFR0e/PR35YzITHklXmpggliF7i H683nY9nK2f5UJqtt83ZAT7LURrVvaV9fx6ZQ3cYZgKI/iu++jhfLYIAqcWHTmxyqghP OhFw== X-Gm-Message-State: AHQUAubb2ASIRsZXi7gZeJv0bykHb5xN22Y11+QbXeRg5e7ppBTzmXau kjkGS3ZCzkUaKLr+XW7v8azHVIE= X-Google-Smtp-Source: AHgI3IZE2iNwglY8Gu2AyauMTshfDD6dLyAp3rHr+Lh7+SI2cbfhjFCFaxHwWW1/5X3QYda6KhOuNg== X-Received: by 2002:a1c:9e4a:: with SMTP id h71mr599591wme.82.1550501704615; Mon, 18 Feb 2019 06:55:04 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:03 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 06/13] trace-cmd: Add buffer instance flags for tracing in guest and agent context Date: Mon, 18 Feb 2019 16:54:42 +0200 Message-Id: <20190218145449.13360-7-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add BUFFER_FL_GUEST and BUFFER_FL_AGENT flags to differentiate when trace-record.c is being called to trace guest or the VM tracing agent. Also disable functions talking to the local tracefs when called in recording guest instances context. Signed-off-by: Slavomir Kaslev --- tracecmd/include/trace-local.h | 5 ++++ tracecmd/trace-record.c | 55 ++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index a1a06e9..f43c9d8 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 { @@ -198,6 +200,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 88b4a55..69c8d67 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -781,6 +781,9 @@ static void __clear_trace(struct buffer_instance *instance) FILE *fp; char *path; + if (is_guest(instance)) + return; + /* reset the trace */ path = get_instance_file(instance, "trace"); fp = fopen(path, "w"); @@ -1264,6 +1267,9 @@ set_plugin_instance(struct buffer_instance *instance, const char *name) char *path; char zero = '0'; + if (is_guest(instance)) + return; + path = get_instance_file(instance, "current_tracer"); fp = fopen(path, "w"); if (!fp) { @@ -1360,6 +1366,9 @@ static void disable_func_stack_trace_instance(struct buffer_instance *instance) int size; int ret; + if (is_guest(instance)) + return; + path = get_instance_file(instance, "current_tracer"); ret = stat(path, &st); tracecmd_put_tracing_file(path); @@ -1553,6 +1562,9 @@ reset_events_instance(struct buffer_instance *instance) int i; int ret; + if (is_guest(instance)) + return; + if (use_old_event_method()) { /* old way only had top instance */ if (!is_top_instance(instance)) @@ -1904,6 +1916,9 @@ static void write_tracing_on(struct buffer_instance *instance, int on) int ret; int fd; + if (is_guest(instance)) + return; + fd = open_tracing_on(instance); if (fd < 0) return; @@ -1923,6 +1938,9 @@ static int read_tracing_on(struct buffer_instance *instance) char buf[10]; int ret; + if (is_guest(instance)) + return -1; + fd = open_tracing_on(instance); if (fd < 0) return fd; @@ -2156,6 +2174,9 @@ static void set_mask(struct buffer_instance *instance) int fd; int ret; + if (is_guest(instance)) + return; + if (!instance->cpumask) return; @@ -2186,6 +2207,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'); @@ -2209,6 +2233,9 @@ static void set_clock(struct buffer_instance *instance) char *content; char *str; + if (is_guest(instance)) + return; + if (!instance->clock) return; @@ -2238,6 +2265,9 @@ static void set_max_graph_depth(struct buffer_instance *instance, char *max_grap char *path; int ret; + if (is_guest(instance)) + return; + path = get_instance_file(instance, "max_graph_depth"); reset_save_file(path, RESET_DEFAULT_PRIO); tracecmd_put_tracing_file(path); @@ -2463,6 +2493,9 @@ static void expand_event_instance(struct buffer_instance *instance) struct event_list *compressed_list = instance->events; struct event_list *event; + if (is_guest(instance)) + return; + reset_event_list(instance); while (compressed_list) { @@ -3337,6 +3370,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"); @@ -3633,6 +3669,9 @@ static void set_buffer_size_instance(struct buffer_instance *instance) int ret; int fd; + if (is_guest(instance)) + return; + if (!buffer_size) return; @@ -3830,6 +3869,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) { @@ -3851,7 +3893,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); @@ -3933,7 +3975,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; } @@ -3955,6 +3997,9 @@ update_plugin_instance(struct buffer_instance *instance, { const char *plugin = instance->plugin; + if (is_guest(instance)) + return; + if (!plugin) return; @@ -4054,6 +4099,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++) { @@ -4080,6 +4128,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 Mon Feb 18 14:54:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818313 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 0FEF81399 for ; Mon, 18 Feb 2019 14:55:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ED3882B065 for ; Mon, 18 Feb 2019 14:55:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E13932B073; Mon, 18 Feb 2019 14:55:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C57D2B073 for ; Mon, 18 Feb 2019 14:55:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730294AbfBROzL (ORCPT ); Mon, 18 Feb 2019 09:55:11 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:35542 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729643AbfBROzL (ORCPT ); Mon, 18 Feb 2019 09:55:11 -0500 Received: by mail-wr1-f68.google.com with SMTP id t18so18753582wrx.2 for ; Mon, 18 Feb 2019 06:55:07 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VviaoSv6UuQ7HXmSgAis25hnYlnnK5UZzqXZvr05deA=; b=CTJBrJ3fmd3vY7rQEtJ4ywZ2A3ouUCN38P8nxzLEk8WNbOMLosNUYwulMPtMk+9wtJ nFNsXPZeSYRFxPZRM1oyUVDKGe88Ufzu8/FbxfHYhHIIDp6+Z0zXPQhB0BrCAUHVzsv+ oqBLHeeXBUoybJlBBb0m0SRTkttHRkBsEcatYvp1eSbmh2/dSu6fq0scDvLFWCs1vK3w z0JiK+Rh/gZpl6HKn0/k+iKXxh2vfDzozyQr9jkFnAevvSs2iExv9IcfNPqsWDDQ02tF hNfpD4a9G+Rhp8e/HULVapS3Ga5Ub+MZc8U5UA6MVaACRyEJ2Afppj34J7ye93EqTex3 DpNw== X-Gm-Message-State: AHQUAuZNkA4FY5+dwQfIy+XRN+bUIntQu6G6Nt5DWX9I+srwHKowUDNC 1mmKVMKd/Ne9kW0nHwqFlw+VQkI= X-Google-Smtp-Source: AHgI3IacWY4wGirHqUDKFwLxiv6S22IAPfszN/a0ryLFSrvl96ZZMUzDjsbRrYz4ATXFe44cBiLLMg== X-Received: by 2002:a5d:6542:: with SMTP id z2mr16955155wrv.237.1550501706134; Mon, 18 Feb 2019 06:55:06 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:05 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 07/13] trace-cmd: Add VM kernel tracing over vsockets transport Date: Mon, 18 Feb 2019 16:54:43 +0200 Message-Id: <20190218145449.13360-8-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- tracecmd/Makefile | 6 +- tracecmd/include/trace-local.h | 16 + tracecmd/trace-agent.c | 225 +++++++++++++ tracecmd/trace-cmd.c | 3 + tracecmd/trace-record.c | 596 ++++++++++++++++++++++++++++++--- tracecmd/trace-usage.c | 13 +- 6 files changed, 814 insertions(+), 45 deletions(-) create mode 100644 tracecmd/trace-agent.c diff --git a/tracecmd/Makefile b/tracecmd/Makefile index 3a11024..865b1c6 100644 --- a/tracecmd/Makefile +++ b/tracecmd/Makefile @@ -33,13 +33,17 @@ TRACE_CMD_OBJS += trace-output.o TRACE_CMD_OBJS += trace-usage.o TRACE_CMD_OBJS += trace-msg.o +ifeq ($(VSOCK_DEFINED), 1) +TRACE_CMD_OBJS += trace-agent.o +endif + ALL_OBJS := $(TRACE_CMD_OBJS:%.o=$(bdir)/%.o) all_objs := $(sort $(ALL_OBJS)) all_deps := $(all_objs:$(bdir)/%.o=$(bdir)/.%.d) CONFIG_INCLUDES = -CONFIG_LIBS = +CONFIG_LIBS = -lrt CONFIG_FLAGS = all: $(TARGETS) diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index f43c9d8..95cf512 100644 --- a/tracecmd/include/trace-local.h +++ b/tracecmd/include/trace-local.h @@ -12,6 +12,8 @@ #include "trace-cmd.h" #include "event-utils.h" +#define TRACE_AGENT_DEFAULT_PORT 823 + extern int debug; extern int quiet; @@ -64,6 +66,8 @@ void trace_split(int argc, char **argv); void trace_listen(int argc, char **argv); +void trace_agent(int argc, char **argv); + void trace_restore(int argc, char **argv); void trace_clear(int argc, char **argv); @@ -88,6 +92,10 @@ void trace_list(int argc, char **argv); void trace_usage(int argc, char **argv); +int trace_record_agent(struct tracecmd_msg_handle *msg_handle, + int cpus, int *fds, + int argc, char **argv); + struct hook_list; void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hooks, @@ -176,6 +184,7 @@ struct buffer_instance { struct func_list *notrace_funcs; const char *clock; + unsigned int *client_ports; struct trace_seq *s_save; struct trace_seq *s_print; @@ -190,6 +199,13 @@ struct buffer_instance { int tracing_on_fd; int buffer_size; int cpu_count; + + int argc; + char **argv; + + int cid; + int port; + int *fds; }; extern struct buffer_instance top_instance; diff --git a/tracecmd/trace-agent.c b/tracecmd/trace-agent.c new file mode 100644 index 0000000..0c0873b --- /dev/null +++ b/tracecmd/trace-agent.c @@ -0,0 +1,225 @@ +// 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" + +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 void agent_serve(unsigned int port) +{ + int sd, cd, nr_cpus; + pid_t pid; + + signal(SIGCHLD, handle_sigchld); + + nr_cpus = count_cpus(); + page_size = getpagesize(); + + sd = make_vsock(port); + if (sd < 0) + die("Failed to open vsocket"); + + for (;;) { + cd = accept(sd, NULL, NULL); + if (cd < 0) { + if (errno == EINTR) + continue; + die("accept"); + } + + if (handler_pid) + goto busy; + + pid = fork(); + if (pid == 0) { + close(sd); + signal(SIGCHLD, SIG_DFL); + agent_handle(cd, nr_cpus, page_size); + } + if (pid > 0) + handler_pid = pid; + +busy: + close(cd); + } +} + +void trace_agent(int argc, char **argv) +{ + bool do_daemon = false; + unsigned int port = TRACE_AGENT_DEFAULT_PORT; + + if (argc < 2) + usage(argv); + + if (strcmp(argv[1], "agent") != 0) + usage(argv); + + for (;;) { + int c, option_index = 0; + static struct option long_options[] = { + {"port", required_argument, NULL, 'p'}, + {"help", no_argument, NULL, '?'}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long(argc-1, argv+1, "+hp:D", + long_options, &option_index); + if (c == -1) + break; + switch (c) { + case 'h': + usage(argv); + break; + case 'p': + port = atoi(optarg); + break; + case 'D': + do_daemon = true; + break; + default: + usage(argv); + } + } + + if (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 69c8d67..b401fd9 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -33,6 +33,9 @@ #include #include #include +#ifdef VSOCK +#include +#endif #include "trace-local.h" #include "trace-msg.h" @@ -74,8 +77,6 @@ static int buffers; static int clear_function_filters; static char *host; -static unsigned int *client_ports; -static int sfd; /* Max size to let a per cpu file get */ static int max_kb; @@ -518,6 +519,22 @@ static char *get_temp_file(struct buffer_instance *instance, int cpu) return file; } +static char *get_guest_file(const char *file, const char *guest) +{ + const char *p; + char *out = NULL; + int base_len; + + p = strrchr(file, '.'); + if (p && p != file) + base_len = p - file; + else + base_len = strlen(file); + + asprintf(&out, "%.*s-%s%s", base_len, file, guest, file + base_len); + return out; +} + static void put_temp_file(char *file) { free(file); @@ -623,11 +640,22 @@ static void delete_thread_data(void) } } +static void tell_guests_to_stop(void) +{ + struct buffer_instance *instance; + + for_all_instances(instance) { + if (is_guest(instance)) { + tracecmd_msg_send_close_msg(instance->msg_handle); + tracecmd_msg_handle_close(instance->msg_handle); + } + } +} + static void stop_threads(enum trace_type type) { struct timeval tv = { 0, 0 }; - int ret; - int i; + int i, ret; if (!recorder_threads) return; @@ -645,6 +673,11 @@ static void stop_threads(enum trace_type type) ret = trace_stream_read(pids, recorder_threads, &tv); } while (ret > 0); } +} + +static void wait_threads() +{ + int i; for (i = 0; i < recorder_threads; i++) { if (pids[i].pid > 0) { @@ -2571,14 +2604,14 @@ static void flush(int sig) tracecmd_stop_recording(recorder); } -static void connect_port(int cpu) +static int connect_port(const char *host, unsigned int port) { struct addrinfo hints; struct addrinfo *results, *rp; - int s; + int s, sfd; char buf[BUFSIZ]; - snprintf(buf, BUFSIZ, "%u", client_ports[cpu]); + snprintf(buf, BUFSIZ, "%u", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -2605,7 +2638,190 @@ static void connect_port(int cpu) freeaddrinfo(results); - client_ports[cpu] = sfd; + return sfd; +} + +#ifdef VSOCK +static int open_vsock(unsigned int cid, unsigned int port) +{ + struct sockaddr_vm addr = { + .svm_family = AF_VSOCK, + .svm_cid = cid, + .svm_port = port, + }; + int sd; + + sd = socket(AF_VSOCK, SOCK_STREAM, 0); + if (sd < 0) + return -1; + + if (connect(sd, (struct sockaddr *)&addr, sizeof(addr))) + return -1; + + return sd; +} +#else +static inline int open_vsock(unsigned int cid, unsigned int port) +{ + die("vsock is not supported"); + return -1; +} +#endif + +static int do_accept(int sd) +{ + int cd; + + for (;;) { + cd = accept(sd, NULL, NULL); + if (cd < 0) { + if (errno == EINTR) + continue; + die("accept"); + } + + return cd; + } + + return -1; +} + +static bool is_digits(const char *s) +{ + const char *p; + + for (p = s; *p; p++) + if (!isdigit(*p)) + return false; + + return true; +} + +struct guest { + char *name; + int cid; + int pid; +}; + +static struct guest *guests; +static size_t guests_len; + +static char *get_qemu_guest_name(char *arg) +{ + char *tok, *end = arg; + + while ((tok = strsep(&end, ","))) { + if (strncmp(tok, "guest=", 6) == 0) + return tok + 6; + } + + return arg; +} + +static void read_qemu_guests(void) +{ + static bool initialized; + struct dirent *entry; + char path[PATH_MAX]; + DIR *dir; + + if (initialized) + return; + + initialized = true; + dir = opendir("/proc"); + if (!dir) + die("opendir"); + + for (entry = readdir(dir); entry; entry = readdir(dir)) { + bool is_qemu = false, last_was_name = false; + struct guest guest = {}; + char *p, *arg = NULL; + size_t arg_size = 0; + FILE *f; + + if (!(entry->d_type == DT_DIR && is_digits(entry->d_name))) + continue; + + guest.pid = atoi(entry->d_name); + snprintf(path, sizeof(path), "/proc/%s/cmdline", entry->d_name); + f = fopen(path, "r"); + if (!f) + continue; + + while (getdelim(&arg, &arg_size, 0, f) != -1) { + if (!is_qemu && strstr(arg, "qemu-system-")) { + is_qemu = true; + continue; + } + + if (!is_qemu) + continue; + + if (strcmp(arg, "-name") == 0) { + last_was_name = true; + continue; + } + + if (last_was_name) { + guest.name = strdup(get_qemu_guest_name(arg)); + last_was_name = false; + continue; + } + + p = strstr(arg, "guest-cid="); + if (p) { + guest.cid = atoi(p + 10); + continue; + } + } + + if (!is_qemu) + goto next; + + guests = realloc(guests, (guests_len + 1) * sizeof(*guests)); + if (!guests) + die("Can not allocate guest buffer"); + guests[guests_len++] = guest; + +next: + free(arg); + fclose(f); + } + + closedir(dir); +} + +static char *parse_guest_name(char *guest, int *cid, int *port) +{ + size_t i; + char *p; + + *port = -1; + p = strrchr(guest, ':'); + if (p) { + *p = '\0'; + *port = atoi(p + 1); + } + + *cid = -1; + p = strrchr(guest, '@'); + if (p) { + *p = '\0'; + *cid = atoi(p + 1); + } else if (is_digits(guest)) + *cid = atoi(guest); + + read_qemu_guests(); + for (i = 0; i < guests_len; i++) { + if ((*cid > 0 && *cid == guests[i].cid) || + strcmp(guest, guests[i].name) == 0) { + *cid = guests[i].cid; + return guests[i].name; + } + } + + return guest; } static void set_prio(int prio) @@ -2652,6 +2868,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); @@ -2676,7 +2903,7 @@ static int create_recorder(struct buffer_instance *instance, int cpu, { long ret; char *file; - int pid; + pid_t pid; if (type != TRACE_TYPE_EXTRACT) { signal(SIGUSR1, flush); @@ -2695,19 +2922,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); @@ -2745,7 +2976,8 @@ static void check_first_msg_from_server(struct tracecmd_msg_handle *msg_handle) die("server not tracecmd server"); } -static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle) +static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle, + unsigned int **client_ports) { char buf[BUFSIZ]; ssize_t n; @@ -2788,8 +3020,8 @@ static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle) /* No options */ write(msg_handle->fd, "0", 2); - client_ports = malloc(local_cpu_count * sizeof(*client_ports)); - if (!client_ports) + *client_ports = malloc(local_cpu_count * sizeof(*client_ports)); + if (!*client_ports) die("Failed to allocate client ports for %d cpus", local_cpu_count); /* @@ -2807,13 +3039,14 @@ static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle) if (i == BUFSIZ) die("read bad port number"); buf[i] = 0; - client_ports[cpu] = atoi(buf); + (*client_ports)[cpu] = atoi(buf); } } -static void communicate_with_listener_v3(struct tracecmd_msg_handle *msg_handle) +static void communicate_with_listener_v3(struct tracecmd_msg_handle *msg_handle, + unsigned int **client_ports) { - if (tracecmd_msg_send_init_data(msg_handle, &client_ports) < 0) + if (tracecmd_msg_send_init_data(msg_handle, client_ports) < 0) die("Cannot communicate with server"); } @@ -2864,7 +3097,7 @@ static void check_protocol_version(struct tracecmd_msg_handle *msg_handle) } } -static struct tracecmd_msg_handle *setup_network(void) +static struct tracecmd_msg_handle *setup_network(struct buffer_instance *instance) { struct tracecmd_msg_handle *msg_handle = NULL; struct addrinfo hints; @@ -2934,11 +3167,11 @@ again: close(sfd); goto again; } - communicate_with_listener_v3(msg_handle); + communicate_with_listener_v3(msg_handle, &instance->client_ports); } if (msg_handle->version == V1_PROTOCOL) - communicate_with_listener_v1(msg_handle); + communicate_with_listener_v1(msg_handle, &instance->client_ports); return msg_handle; } @@ -2951,7 +3184,7 @@ setup_connection(struct buffer_instance *instance, struct common_record_context struct tracecmd_msg_handle *msg_handle; struct tracecmd_output *network_handle; - msg_handle = setup_network(); + msg_handle = setup_network(instance); /* Now create the handle through this socket */ if (msg_handle->version == V3_PROTOCOL) { @@ -2978,28 +3211,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 @%d:%d", + 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"); @@ -3172,7 +3476,44 @@ static void add_options(struct tracecmd_output *handle, struct common_record_con tracecmd_add_option(handle, TRACECMD_OPTION_TRACECLOCK, 0, NULL); add_option_hooks(handle); add_uname(handle); +} +static void write_guest_file(struct buffer_instance *instance) +{ + struct tracecmd_output *handle; + int cpu_count = instance->cpu_count; + char *file; + char **temp_files; + int i, fd; + + file = get_guest_file(output_file, instance->name); + fd = open(file, O_RDWR); + if (fd < 0) + die("error opening %s", file); + put_temp_file(file); + + handle = tracecmd_get_output_handle_fd(fd); + if (!handle) + die("error writing to %s", file); + + temp_files = malloc(sizeof(*temp_files) * cpu_count); + if (!temp_files) + die("failed to allocate temp_files for %d cpus", + cpu_count); + + for (i = 0; i < cpu_count; i++) { + temp_files[i] = get_temp_file(instance, i); + if (!temp_files[i]) + die("failed to allocate memory"); + } + + if (tracecmd_write_cpu_data(handle, cpu_count, temp_files) < 0) + die("failed to write CPU data"); + tracecmd_output_close(handle); + + for (i = 0; i < cpu_count; i++) + put_temp_file(temp_files[i]); + free(temp_files); } static void record_data(struct common_record_context *ctx) @@ -3186,7 +3527,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; @@ -4405,6 +4748,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); @@ -4567,6 +4911,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, @@ -4608,10 +5011,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); @@ -4664,6 +5077,26 @@ static void parse_record_options(int argc, add_trigger(event, optarg); break; + case 'A': { + char *name = NULL; + int cid = -1, port = -1; + + if (!IS_RECORD(ctx)) + die("-A is only allowed for record operations"); + + name = parse_guest_name(optarg, &cid, &port); + if (!name || cid == -1) + die("guest %s not found", optarg); + if (port == -1) + port = TRACE_AGENT_DEFAULT_PORT; + + ctx->instance = create_instance(name); + ctx->instance->flags |= BUFFER_FL_GUEST; + ctx->instance->cid = cid; + ctx->instance->port = port; + add_instance(ctx->instance, 0); + break; + } case 'F': test_set_event_pid(); filter_task = 1; @@ -4734,6 +5167,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)) @@ -4795,6 +5230,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; @@ -4891,6 +5328,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, "*"); @@ -4921,7 +5368,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++) { @@ -4953,12 +5401,28 @@ static void finalize_record_trace(struct common_record_context *ctx) if (instance->flags & BUFFER_FL_KEEP) write_tracing_on(instance, instance->tracing_on_init_val); + if (is_agent(instance)) + 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. @@ -4987,7 +5451,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); @@ -5004,14 +5467,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) { @@ -5046,9 +5511,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 */ @@ -5060,6 +5529,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); @@ -5069,6 +5539,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(); @@ -5203,3 +5676,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 9ea1906..e845f50 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -231,11 +231,22 @@ static struct usage_help usage_help[] = { "listen on a network socket for trace clients", " %s listen -p port[-D][-o file][-d dir][-l logfile]\n" " Creates a socket to listen for clients.\n" - " -D create it in daemon mode.\n" + " -p port number to listen on.\n" + " -D run in daemon mode.\n" " -o file name to use for clients.\n" " -d directory to store client files.\n" " -l logfile to write messages to.\n" }, +#ifdef VSOCK + { + "agent", + "listen on a 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 Mon Feb 18 14:54:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818307 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 69EE91399 for ; Mon, 18 Feb 2019 14:55:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 58C532AFFD for ; Mon, 18 Feb 2019 14:55:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4D4832B079; Mon, 18 Feb 2019 14:55: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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DF6962AFFD for ; Mon, 18 Feb 2019 14:55:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729852AbfBROzJ (ORCPT ); Mon, 18 Feb 2019 09:55:09 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:51712 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729832AbfBROzJ (ORCPT ); Mon, 18 Feb 2019 09:55:09 -0500 Received: by mail-wm1-f68.google.com with SMTP id n19so5535477wmi.1 for ; Mon, 18 Feb 2019 06:55:08 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8X22xUNzyBITgd8y0sQOWbINFajpb27+VnnWJtIQNC4=; b=AWPR/Fljo0jEz6qW05+jwotejjXUMz79LT/hoqxHq2hLRax9TTKs9nbyVUB7tTOmHc hZnsfUcjTHcHiYEJhTBN87IVXGrMOi6HF2PLqrn3MZJC4KLWNgYYwWFfdjO1qopUhjfR d0r47ws/MWBqaj1Rxg3ZID24jfWCxvvt/1DoRxj9p815rPaLAb5n9cjXnu4M7mB3pIg6 FgoDULgRzHCcaIs4bxU+evGuSDi1hhu+qNLA4wDWo7GOlznNmPRVPFmZRg79PiXdI4V4 PVXmBltvOoHW2pwedDbq+H4HL33pTpcLhJS5vv2lFrgd7ACCUbTNbKbeJC/B5X7t45vF e+pQ== X-Gm-Message-State: AHQUAuawgIw63ouJgBFUigWUkyb/0COou/bmHuuCYdCu3WniAMRIKrGZ UOa4rpXDHSo12oTm+b33nQ== X-Google-Smtp-Source: AHgI3IYkiJsKfgfI+mLQdK3H8CuXA3eSQrXgVsxoOxNJGUSYsL9KXJmBOOYqeLbrXvE0smjU2QdRIw== X-Received: by 2002:a1c:f509:: with SMTP id t9mr17052007wmh.76.1550501707769; Mon, 18 Feb 2019 06:55:07 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:06 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 08/13] trace-cmd: Use splice(2) for vsockets if available Date: Mon, 18 Feb 2019 16:54:44 +0200 Message-Id: <20190218145449.13360-9-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Detect if splice(2) reading is supported for vsockets (Linux 4.20 and later) and use it, or fallback to read/write-ing otherwise. Signed-off-by: Slavomir Kaslev --- lib/trace-cmd/trace-recorder.c | 6 ++-- tracecmd/trace-record.c | 56 ++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index 1b84bb5..d66f112 100644 --- a/lib/trace-cmd/trace-recorder.c +++ b/lib/trace-cmd/trace-recorder.c @@ -386,10 +386,8 @@ static long splice_data(struct tracecmd_recorder *recorder) ret = splice(recorder->brass[0], NULL, recorder->fd, NULL, read, recorder->fd_flags); if (ret < 0) { - if (errno != EAGAIN && errno != EINTR) { - warning("recorder error in splice output"); - return -1; - } + if (errno != EAGAIN && errno != EINTR) + return ret; return total_read; } else update_fd(recorder, ret); diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index b401fd9..ca97758 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -2660,12 +2660,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) @@ -2870,13 +2919,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 Mon Feb 18 14:54:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Slavomir Kaslev X-Patchwork-Id: 10818309 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 2FA3F1399 for ; Mon, 18 Feb 2019 14:55:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1EB262B076 for ; Mon, 18 Feb 2019 14:55:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1329A2B080; Mon, 18 Feb 2019 14:55:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 73EC52B076 for ; Mon, 18 Feb 2019 14:55:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729643AbfBROzM (ORCPT ); Mon, 18 Feb 2019 09:55:12 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36015 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729832AbfBROzM (ORCPT ); Mon, 18 Feb 2019 09:55:12 -0500 Received: by mail-wm1-f68.google.com with SMTP id j125so17442101wmj.1 for ; Mon, 18 Feb 2019 06:55:10 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+dRklSSFSVx1Dpqn/QDXoUp9fai4osO+QxjC8NjwlMI=; b=NoNCwRu+p8ytH9t8EXUODpdEN60vX9qLB0Bkyy+kv8CqxoLOIBNYJIat5rVMZCgyw/ kUGzb+FtMpwO9Bu1krRIpSNQCetkbpP5VRaVAAh6qfWnxEuvKJwQ/tvd2lQEA5PUMjn2 PgC10wFKfjoZ0/POxvbFbiPgb6F6d422gx9F7gXdhQrqatVPT8/4BS0VTldnDHyS56sC 8VEv8AD/Tfb9znptLDEw5KkLJGncJgK9MBdYP3fFhxe3FtVjA/+F/XvUWaKJgihoYSA0 irpYRPT5A6lyi/NkwxNxW7ZCNca/j3JycxC+x5TGgt9hDE00mT/32clvbhruNu8d7nGw vxEQ== X-Gm-Message-State: AHQUAuY0kab1l5gzumaOsTB5tVGc+/xijEU196brdxvb2S1TkiyURVEW yMiRMcJRKDmRswBA5BPzpQ== X-Google-Smtp-Source: AHgI3Ibh3GxjtkboXHx4SVuZcCZrFyQawaaaLdd1hbWLcXcjvVA+FuDxdNMmjEq6aHkNaQk70dQVww== X-Received: by 2002:a1c:a986:: with SMTP id s128mr5661084wme.44.1550501709593; Mon, 18 Feb 2019 06:55:09 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:08 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 09/13] trace-cmd: Add `trace-cmd setup-guest` command Date: Mon, 18 Feb 2019 16:54:45 +0200 Message-Id: <20190218145449.13360-10-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add `trace-cmd setup-guest` command that creates the necessary FIFOs for tracing a guest over FIFOs instead of vsockets. Signed-off-by: Slavomir Kaslev --- tracecmd/Makefile | 1 + tracecmd/include/trace-local.h | 6 ++ tracecmd/trace-cmd.c | 1 + tracecmd/trace-setup-guest.c | 176 +++++++++++++++++++++++++++++++++ tracecmd/trace-usage.c | 8 ++ 5 files changed, 192 insertions(+) create mode 100644 tracecmd/trace-setup-guest.c diff --git a/tracecmd/Makefile b/tracecmd/Makefile index 865b1c6..d3e3080 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 95cf512..d32ba88 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..ded510e --- /dev/null +++ b/tracecmd/trace-setup-guest.c @@ -0,0 +1,176 @@ +// 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+1], *end, *p; + + end = stpncpy(buf, path, sizeof(buf)); + for (p = buf; p < end; p++) { + for (; p < end && *p == '/'; p++); + for (; p < end && *p != '/'; 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; + int ret; + + ret = stat(path, &st); + if (ret == 0) { + if (S_ISFIFO(st.st_mode)) + return 0; + return -EEXIST; + } + + return mkfifo(path, mode); +} + +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 e845f50..7a8002f 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -246,6 +246,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 Mon Feb 18 14:54: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: 10818311 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 71C1D14E1 for ; Mon, 18 Feb 2019 14:55:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 619302B065 for ; Mon, 18 Feb 2019 14:55:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 561CA2B076; Mon, 18 Feb 2019 14:55:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 95C1E2B079 for ; Mon, 18 Feb 2019 14:55:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729832AbfBROzM (ORCPT ); Mon, 18 Feb 2019 09:55:12 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:39865 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729907AbfBROzM (ORCPT ); Mon, 18 Feb 2019 09:55:12 -0500 Received: by mail-wr1-f65.google.com with SMTP id l5so17607981wrw.6 for ; Mon, 18 Feb 2019 06:55:11 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VI1nGOh4YQXOruxwSs9vvtLfm/uvb9CWUk8ihZF6Ubk=; b=rBWsgVENGr7OEipRTjNss7mFZNR/TLPFOLOV5EU8tUFu1HGbrqCcqjUAbocTO7sy8w +Qr3pFRxL7JM+ycPEpa8lDERLxUkcsfT13OgVAeyR2asBqyRujYuoOLGAWnn0HAvP6vn XipomTw5I6yrdTPKZwjx0cdsQ0o3Z54dWRiJBlpZQa6per+HlcHzy+MsYnONuCWzjPJP uDUXrn+L1y3/cLz3eRSVbSpt8V8oczSMLPr4AZWU7fDYXOddNOrwypA3YXNyG7IthIhF wJGkdD/R50x/RokpMCnzqxr9iEU+ejLp+qJ+rgWXnCtiHxml0Af3b8x2o6qI4aPpKdGF AYOA== X-Gm-Message-State: AHQUAuaA//XNOsFVDKuBQbUpJ3cILxrM0Q/hLXgLUSECqI+m5Z2BQNf+ 5tjiNNVicSYA1WRpIQ2cLA== X-Google-Smtp-Source: AHgI3IYPLMgSH/nzU3KINURhYgu8YqOC2PhjVIf3atJm03Cn2kszRkRIzat6gBSkkvwsl6IlZFtzoQ== X-Received: by 2002:a5d:5506:: with SMTP id b6mr16238262wrv.33.1550501710722; Mon, 18 Feb 2019 06:55:10 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:10 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 10/13] trace-cmd: Try to autodetect number of guest CPUs in setup-guest if not specified Date: Mon, 18 Feb 2019 16:54:46 +0200 Message-Id: <20190218145449.13360-11-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 ded510e..789dc65 100644 --- a/tracecmd/trace-setup-guest.c +++ b/tracecmd/trace-setup-guest.c @@ -91,6 +91,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; @@ -169,6 +187,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 7a8002f..9a13d93 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -249,7 +249,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 Mon Feb 18 14:54: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: 10818317 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 8098917FB for ; Mon, 18 Feb 2019 14:55:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6CDB32B076 for ; Mon, 18 Feb 2019 14:55:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 616462B079; Mon, 18 Feb 2019 14:55: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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EBE812AF9D for ; Mon, 18 Feb 2019 14:55:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731032AbfBROzO (ORCPT ); Mon, 18 Feb 2019 09:55:14 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36019 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729907AbfBROzO (ORCPT ); Mon, 18 Feb 2019 09:55:14 -0500 Received: by mail-wm1-f68.google.com with SMTP id j125so17442264wmj.1 for ; Mon, 18 Feb 2019 06:55:13 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ddAyRPKZEQFhmI/PbM/tQUe91aCAWIcm8aqi3kaSxGQ=; b=n+2pKn/3f9iugvdnYQeAooKqSO+qZw5JkQQNAtzm7Eiw1n2AumWzAcQQKBvuJ6p07D QVVM6Wt1Wfex/i9aNcLJlZ1i4lHHOUMHMWDzSDZ3+WJ54gQkN6qoD5oHAL8nb5IHTrP4 GZNKO6DLl6zMHVsy8gVdFdQS9xoFp7FL8EOL4mW4eTCx3rIOhC3fkQ7kmQx5RW9Fxbiz nJFKfMVa8XGdaw0LiwTs0QbteWHv7AUzO98JUH7PJqTaCc9z5QhKBgexv/YKZWhveGfr jg2oxVGOwpLgIe7ZSf0j+oOiHRaxzHd6xz+zO2okniRaMorS9SxnD5pt8dL+CcEWPgNW T77Q== X-Gm-Message-State: AHQUAuaSf3XBCtBrU7c8p6aMiTxTejicoVeE8lPdMl7Jq599triqSe+e 6/K5GL1xXgUkaHmMnubRXK/oiLc= X-Google-Smtp-Source: AHgI3IbBWzSebuzuRN9VwQMefCNUzWReDHYt88N9cK/lrJbNddWHxkaEurWXu9IGNON0k3Nc0tRkSA== X-Received: by 2002:a1c:4155:: with SMTP id o82mr15606339wma.122.1550501712464; Mon, 18 Feb 2019 06:55:12 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:11 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 11/13] trace-cmd: Add setup-guest flag for attaching FIFOs to the guest VM config Date: Mon, 18 Feb 2019 16:54:47 +0200 Message-Id: <20190218145449.13360-12-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 789dc65..043bca2 100644 --- a/tracecmd/trace-setup-guest.c +++ b/tracecmd/trace-setup-guest.c @@ -109,7 +109,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; @@ -129,6 +167,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) @@ -138,6 +182,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; @@ -157,7 +202,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; @@ -177,6 +222,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); } @@ -193,5 +241,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 9a13d93..bcfd3dc 100644 --- a/tracecmd/trace-usage.c +++ b/tracecmd/trace-usage.c @@ -249,10 +249,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 Mon Feb 18 14:54: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: 10818319 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 E175D14E1 for ; Mon, 18 Feb 2019 14:55:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CE13B2B049 for ; Mon, 18 Feb 2019 14:55:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C092C2B065; Mon, 18 Feb 2019 14:55:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B3DF02B049 for ; Mon, 18 Feb 2019 14:55:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730211AbfBROzQ (ORCPT ); Mon, 18 Feb 2019 09:55:16 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:36397 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730321AbfBROzQ (ORCPT ); Mon, 18 Feb 2019 09:55:16 -0500 Received: by mail-wr1-f66.google.com with SMTP id o17so18716469wrw.3 for ; Mon, 18 Feb 2019 06:55:14 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=u2EwF0qQ8fIwZ8XAhIn8rabEJP9DpcagTnKdKR/HstQ=; b=niNAeqaXIRC5aJ6w1nQLzdqGAaMNv6m2C8ERsBwASaKYgxeH94cPkhIOQ1IKNUfvbm upPwLHngn/+IqaEtKIrbrexF201oZ/ZidavF+fBFRpUowFc0t7ez2G/T7n8pzN+vk7GZ 1KiD+c9fBjbMndf0zqusB7171L9h8Sh7QnDYW/nWrYY6F55CyE4Nck03Ckge/rp46AjR rOlWT7vZ93VmCwgF1xgevS/Y15Sa1UWG7ekfmXXYuqInTIvIVwLyIIkM/HZtAEu4Jakq MxrTRKbCJg29Opkno49WC1+SIqRLN3YvYSGcThJAjzcZDU7wpsWX4FoW2pEBv05ezRjS tLYA== X-Gm-Message-State: AHQUAubOdF5uAql8BiLJHYSCHBi6VNmzaguB4IaH4w6ymHrpbHRR0pNo E0bOik9pGy+KVqzg5PHos446z3M= X-Google-Smtp-Source: AHgI3IbPA9LFkkUzjGdZnWqZJsxtlPzXDBEh1E69+NuAUKSJUjgLFFO+ouh9KGO7L/4atKxXzwWMZg== X-Received: by 2002:adf:f103:: with SMTP id r3mr18553754wro.50.1550501713782; Mon, 18 Feb 2019 06:55:13 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:13 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 12/13] trace-cmd: Add splice() recording from FIFO without additional pipe buffer Date: Mon, 18 Feb 2019 16:54:48 +0200 Message-Id: <20190218145449.13360-13-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- include/trace-cmd/trace-cmd.h | 3 +- lib/trace-cmd/trace-recorder.c | 70 ++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 6a21e66..52962e9 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -270,8 +270,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); diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index d66f112..8058d71 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; @@ -372,7 +379,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) { warning("recorder error in splice input"); @@ -399,6 +406,39 @@ 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; + + 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->trace_fd_flags); + if (read < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; + + warning("recorder error in splice input"); + return -1; + } + + return read; +} + /* * Returns -1 on error. * or bytes of data read. @@ -433,6 +473,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; @@ -440,8 +491,11 @@ static void set_nonblock(struct tracecmd_recorder *recorder) /* Do not block on reads for flushing */ flags = fcntl(recorder->trace_fd, F_GETFL); fcntl(recorder->trace_fd, F_SETFL, flags | O_NONBLOCK); + recorder->trace_fd_flags |= SPLICE_F_NONBLOCK; - /* Do not block on streams for write */ + /* Do not block on pipes for write */ + flags = fcntl(recorder->fd, F_GETFL); + fcntl(recorder->fd, F_SETFL, flags | O_NONBLOCK); recorder->fd_flags |= SPLICE_F_NONBLOCK; } @@ -455,10 +509,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; @@ -503,10 +554,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; From patchwork Mon Feb 18 14:54: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: 10818321 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 3957614E1 for ; Mon, 18 Feb 2019 14:55:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2681B2B065 for ; Mon, 18 Feb 2019 14:55:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1AB942B049; Mon, 18 Feb 2019 14:55: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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2208B2B049 for ; Mon, 18 Feb 2019 14:55:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730321AbfBROzR (ORCPT ); Mon, 18 Feb 2019 09:55:17 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:37577 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729907AbfBROzR (ORCPT ); Mon, 18 Feb 2019 09:55:17 -0500 Received: by mail-wr1-f67.google.com with SMTP id c8so18688182wrs.4 for ; Mon, 18 Feb 2019 06:55:16 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=XlCjSz9ucs33Xk7tc1p0tDIJepIIP7QIMy/b4Z0Nz9I=; b=QxxqR6BG4yrOjhW4eo0QgvqrKDtWaFlg9CLG8vMcaM3BiUP4wKnAiu7+VI3826k76F xMYcwh0NQ/TN24iqDHTbL2guvaCaF7BfHCd0207ZGDXt08xPKof0KVfrOVX7L1Yr21Xz +9ZtK7VqCC1WCEsS5csKRiYHM/XdJr6T22TdryKsgumqq6gwmpv5YmcyJHkv1k/asnjP Ci6mc9Qwf917FVynn5qX912iSh93MYmo6KwngiaSEdifcbGqnCzPyn/LIg49k/JcK0nN cDLZVXedcu7uqkYOGcd2NSGzJK+b6aQ+Bn6xOZsKNuiZCW1ErSZMAjYwUPx4dRTpRv9y /QLA== X-Gm-Message-State: AHQUAubEOLK4VhZdCGP1IDkYSXaOjzI8gEfiNUlpGM/6xxRBCPIECB33 Al87W1RGgBURUSgAFd32iQ== X-Google-Smtp-Source: AHgI3IbkqHfBomecjANmfsn7YsURLn53dWQ47sEZP+padiuWRTojwAJ1JW4EtbKZcHo27eyo0/j28g== X-Received: by 2002:adf:dd4d:: with SMTP id u13mr18637130wrm.284.1550501715096; Mon, 18 Feb 2019 06:55:15 -0800 (PST) Received: from localhost.localdomain ([146.247.46.6]) by smtp.gmail.com with ESMTPSA id n11sm10172528wrw.60.2019.02.18.06.55.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Feb 2019 06:55:14 -0800 (PST) From: Slavomir Kaslev To: rostedt@vmware.com, rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, slavomir.kaslev@gmail.com Subject: [RFC PATCH v7 13/13] trace-cmd: Add VM tracing over FIFOs transport Date: Mon, 18 Feb 2019 16:54:49 +0200 Message-Id: <20190218145449.13360-14-kaslevs@vmware.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com> References: <20190218145449.13360-1-kaslevs@vmware.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP FIFOs offer ~3x the throughput of vsockets. This patch adds support for using FIFOs to stream tracing data back to the host when tracing VMs. Signed-off-by: Slavomir Kaslev --- include/trace-cmd/trace-cmd.h | 8 ++-- tracecmd/include/trace-local.h | 4 +- tracecmd/trace-agent.c | 40 ++++++++++++++-- tracecmd/trace-msg.c | 26 ++++++---- tracecmd/trace-record.c | 87 ++++++++++++++++++++++++++++++---- 5 files changed, 137 insertions(+), 28 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 52962e9..27ba89d 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -333,16 +333,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/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index d32ba88..d7bdb1f 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; @@ -212,6 +213,7 @@ struct buffer_instance { int cid; 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 0c0873b..7389f72 100644 --- a/tracecmd/trace-agent.c +++ b/tracecmd/trace-agent.c @@ -83,12 +83,39 @@ 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 = 0; + + 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; + break; + } + + fds[i] = fd; + } + + if (!ret) + return ret; + + /* We failed to open all FIFOs so clean up and return error */ + 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; @@ -101,17 +128,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 8ce1f98..065a01e 100644 --- a/tracecmd/trace-msg.c +++ b/tracecmd/trace-msg.c @@ -159,6 +159,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, +}; + enum msg_opt_command { MSGOPT_USETCP = 1, }; @@ -740,7 +744,7 @@ error: return ret; } -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; @@ -750,6 +754,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) @@ -763,13 +768,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; @@ -782,7 +787,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; @@ -834,6 +839,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 @@ -853,13 +859,14 @@ 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 ports_size = nr_cpus * sizeof(*msg->port_array); int i; msg->hdr.size = htonl(ntohl(msg->hdr.size) + ports_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); @@ -875,13 +882,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; @@ -890,7 +897,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; ssize_t buf_len; @@ -912,6 +919,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 ca97758..ef6319f 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -76,6 +76,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 */ @@ -2921,12 +2923,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); } @@ -2979,10 +2986,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)) @@ -3263,11 +3274,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) @@ -3278,15 +3320,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 */ @@ -4785,6 +4845,7 @@ enum { OPT_funcstack = 254, OPT_date = 255, OPT_module = 256, + OPT_nofifos = 257, }; void trace_stop(int argc, char **argv) @@ -5048,6 +5109,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}, @@ -5333,6 +5395,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; @@ -5731,7 +5796,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; @@ -5757,6 +5823,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;