From: Slavomir Kaslev <kaslevs@vmware.com>
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 [thread overview]
Message-ID: <20190218145449.13360-13-kaslevs@vmware.com> (raw)
In-Reply-To: <20190218145449.13360-1-kaslevs@vmware.com>
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 <kaslevs@vmware.com>
---
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 <stdlib.h>
#include <fcntl.h>
#include <time.h>
+#include <poll.h>
#include <unistd.h>
#include <errno.h>
@@ -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;
--
2.19.1
next prev parent reply other threads:[~2019-02-18 14:55 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-18 14:54 [RFC PATCH v7 00/13] Add VM kernel tracing over vsockets and FIFOs Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 01/13] trace-cmd: Minor cleanup in tracecmd_start_recording() Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 02/13] trace-cmd: Minor cleanup in print_stat() Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 03/13] trace-cmd: Detect if vsockets are available Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 04/13] trace-cmd: Add tracecmd_create_recorder_virt function Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 05/13] trace-cmd: Add TRACE_REQ and TRACE_RESP messages Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 06/13] trace-cmd: Add buffer instance flags for tracing in guest and agent context Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 07/13] trace-cmd: Add VM kernel tracing over vsockets transport Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 08/13] trace-cmd: Use splice(2) for vsockets if available Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 09/13] trace-cmd: Add `trace-cmd setup-guest` command Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 10/13] trace-cmd: Try to autodetect number of guest CPUs in setup-guest if not specified Slavomir Kaslev
2019-02-18 14:54 ` [RFC PATCH v7 11/13] trace-cmd: Add setup-guest flag for attaching FIFOs to the guest VM config Slavomir Kaslev
2019-02-18 14:54 ` Slavomir Kaslev [this message]
2019-02-18 14:54 ` [RFC PATCH v7 13/13] trace-cmd: Add VM tracing over FIFOs transport Slavomir Kaslev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190218145449.13360-13-kaslevs@vmware.com \
--to=kaslevs@vmware.com \
--cc=linux-trace-devel@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=rostedt@vmware.com \
--cc=slavomir.kaslev@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.