aboutsummaryrefslogtreecommitdiff
path: root/lib/trace-cmd
diff options
context:
space:
mode:
authorSteven Rostedt (Google) <rostedt@goodmis.org>2022-11-15 15:48:48 -0500
committerSteven Rostedt (Google) <rostedt@goodmis.org>2022-12-06 18:53:49 -0500
commit2610bdcde43a63e3a9b2afb2ededab1183acf5fe (patch)
tree7608074ceed9dfb505dd564e4968bffe9407f0d4 /lib/trace-cmd
parent1f75010a25939c0c4e1d99df7c40e364e4206e9b (diff)
downloadtrace-cmd-2610bdcde43a63e3a9b2afb2ededab1183acf5fe.tar.gz
trace-cmd library: Use tracefs_cpu for recorder helpers
Use the API from libtracefs on tracefs_cpu that is used for reading from the trace_pipe_raw files for the recorder. Link: https://lore.kernel.org/linux-trace-devel/20221115154848.21fc8698@gandalf.local.home Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Diffstat (limited to 'lib/trace-cmd')
-rw-r--r--lib/trace-cmd/include/private/trace-cmd-private.h6
-rw-r--r--lib/trace-cmd/trace-recorder.c330
2 files changed, 66 insertions, 270 deletions
diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h
index ef35c370..271f0541 100644
--- a/lib/trace-cmd/include/private/trace-cmd-private.h
+++ b/lib/trace-cmd/include/private/trace-cmd-private.h
@@ -371,9 +371,9 @@ struct tracecmd_recorder *tracecmd_create_recorder(const char *file, int cpu, un
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);
-struct tracecmd_recorder *tracecmd_create_buffer_recorder_maxkb(const char *file, int cpu, unsigned flags, const char *buffer, int maxkb);
+struct tracecmd_recorder *tracecmd_create_buffer_recorder_fd(int fd, int cpu, unsigned flags, struct tracefs_instance *instance);
+struct tracecmd_recorder *tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags, struct tracefs_instance *instance);
+struct tracecmd_recorder *tracecmd_create_buffer_recorder_maxkb(const char *file, int cpu, unsigned flags, struct tracefs_instance *instance, int maxkb);
int tracecmd_start_recording(struct tracecmd_recorder *recorder, unsigned long sleep);
void tracecmd_stop_recording(struct tracecmd_recorder *recorder);
diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c
index c343aadf..f387091f 100644
--- a/lib/trace-cmd/trace-recorder.c
+++ b/lib/trace-cmd/trace-recorder.c
@@ -32,20 +32,17 @@
#define POLL_TIMEOUT_MS 1000
struct tracecmd_recorder {
+ struct tracefs_cpu *tcpu;
int fd;
int fd1;
int fd2;
- int trace_fd;
- int brass[2];
- int pipe_size;
int page_size;
+ int subbuf_size;
int cpu;
int stop;
int max;
int pages;
int count;
- unsigned fd_flags;
- unsigned trace_fd_flags;
unsigned flags;
};
@@ -94,14 +91,7 @@ void tracecmd_free_recorder(struct tracecmd_recorder *recorder)
append_file(recorder->page_size, recorder->fd1, recorder->fd2);
}
close:
- if (recorder->brass[0] >= 0)
- close(recorder->brass[0]);
-
- if (recorder->brass[1] >= 0)
- close(recorder->brass[1]);
-
- if (recorder->trace_fd >= 0)
- close(recorder->trace_fd);
+ tracefs_cpu_close(recorder->tcpu);
if (recorder->fd1 >= 0)
close(recorder->fd1);
@@ -114,44 +104,22 @@ void tracecmd_free_recorder(struct tracecmd_recorder *recorder)
static void set_nonblock(struct tracecmd_recorder *recorder)
{
- long flags;
-
- /* Do not block on reads */
- flags = fcntl(recorder->trace_fd, F_GETFL);
- fcntl(recorder->trace_fd, F_SETFL, flags | O_NONBLOCK);
-
- /* Do not block on streams */
- recorder->fd_flags |= SPLICE_F_NONBLOCK;
+ tracefs_cpu_stop(recorder->tcpu);
}
-struct tracecmd_recorder *
-tracecmd_create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags,
- const char *buffer, int maxkb)
+static struct tracecmd_recorder *
+create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags,
+ struct tracefs_instance *instance, int maxkb, int tfd)
{
struct tracecmd_recorder *recorder;
- char *path = NULL;
- int pipe_size = 0;
- int ret;
+ bool nonblock = false;
recorder = malloc(sizeof(*recorder));
if (!recorder)
return NULL;
- recorder->cpu = cpu;
recorder->flags = flags;
- recorder->fd_flags = SPLICE_F_MOVE;
-
- if (!(recorder->flags & TRACECMD_RECORD_BLOCK_SPLICE))
- 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;
- recorder->brass[1] = -1;
-
recorder->page_size = getpagesize();
if (maxkb) {
int kb_per_page = recorder->page_size >> 10;
@@ -174,47 +142,18 @@ tracecmd_create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags,
recorder->fd1 = fd;
recorder->fd2 = fd2;
- 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);
-
- if (recorder->trace_fd < 0)
- goto out_free;
- }
+ if (recorder->flags & TRACECMD_RECORD_POLL)
+ nonblock = true;
- if (!(recorder->flags & (TRACECMD_RECORD_NOSPLICE |
- TRACECMD_RECORD_NOBRASS))) {
- ret = pipe(recorder->brass);
- if (ret < 0)
- goto out_free;
-
- ret = fcntl(recorder->brass[0], F_GETPIPE_SZ, &pipe_size);
- /*
- * F_GETPIPE_SZ was introduced in 2.6.35, ftrace was introduced
- * in 2.6.31. If we are running on an older kernel, just fall
- * back to using page_size for splice(). It could also return
- * success, but not modify pipe_size.
- */
- if (ret > 0 && !pipe_size)
- pipe_size = ret;
- else if (ret < 0)
- pipe_size = recorder->page_size;
-
- recorder->pipe_size = pipe_size;
- }
+ if (tfd >= 0)
+ recorder->tcpu = tracefs_cpu_alloc_fd(tfd, recorder->page_size, nonblock);
+ else
+ recorder->tcpu = tracefs_cpu_open(instance, cpu, nonblock);
- if (recorder->flags & TRACECMD_RECORD_POLL)
- set_nonblock(recorder);
+ if (!recorder->tcpu)
+ goto out_free;
+ recorder->subbuf_size = tracefs_cpu_read_size(recorder->tcpu);
return recorder;
out_free:
@@ -222,62 +161,31 @@ tracecmd_create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags,
return NULL;
}
-static void verify_splice(const char *file, unsigned *flags)
+struct tracecmd_recorder *
+tracecmd_create_buffer_recorder_fd2(int fd, int fd2, int cpu, unsigned flags,
+ struct tracefs_instance *instance, int maxkb)
{
- int brass[2];
- int ret;
- int fd;
-
- fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
- if (fd < 0)
- return; /* Will fail by the caller too */
-
- if (pipe(brass) < 0)
- goto fail_pipe;
-
- ret = splice(brass[0], NULL, fd, NULL, 0, SPLICE_F_NONBLOCK);
- if (ret < 0)
- goto fail_splice;
-
- out_pipe:
- close(brass[0]);
- close(brass[1]);
- out:
- close(fd);
- return;
-
- fail_pipe:
- tracecmd_warning("Failed opening pipe, trying read/write");
- *flags |= TRACECMD_RECORD_NOSPLICE;
- goto out;
-
- fail_splice:
- tracecmd_warning("Failed splice to file, trying read/write");
- *flags |= TRACECMD_RECORD_NOSPLICE;
- goto out_pipe;
+ return create_buffer_recorder_fd2(fd, fd2, cpu, flags, instance, maxkb, -1);
}
struct tracecmd_recorder *
-tracecmd_create_buffer_recorder_fd(int fd, int cpu, unsigned flags, const char *buffer)
+tracecmd_create_buffer_recorder_fd(int fd, int cpu, unsigned flags, struct tracefs_instance *instance)
{
- return tracecmd_create_buffer_recorder_fd2(fd, -1, cpu, flags, buffer, 0);
+ return tracecmd_create_buffer_recorder_fd2(fd, -1, cpu, flags, instance, 0);
}
static struct tracecmd_recorder *
__tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags,
- const char *buffer)
+ struct tracefs_instance *instance, int tfd)
{
struct tracecmd_recorder *recorder;
int fd;
- if (!(flags & TRACECMD_RECORD_NOSPLICE))
- verify_splice(file, &flags);
-
fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
if (fd < 0)
return NULL;
- recorder = tracecmd_create_buffer_recorder_fd(fd, cpu, flags, buffer);
+ recorder = create_buffer_recorder_fd2(fd, -1, cpu, flags, instance, 0, tfd);
if (!recorder) {
close(fd);
unlink(file);
@@ -288,7 +196,7 @@ __tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags,
struct tracecmd_recorder *
tracecmd_create_buffer_recorder_maxkb(const char *file, int cpu, unsigned flags,
- const char *buffer, int maxkb)
+ struct tracefs_instance *instance, int maxkb)
{
struct tracecmd_recorder *recorder = NULL;
char *file2;
@@ -297,7 +205,7 @@ tracecmd_create_buffer_recorder_maxkb(const char *file, int cpu, unsigned flags,
int fd2;
if (!maxkb)
- return tracecmd_create_buffer_recorder(file, cpu, flags, buffer);
+ return tracecmd_create_buffer_recorder(file, cpu, flags, instance);
len = strlen(file);
file2 = malloc(len + 3);
@@ -314,7 +222,7 @@ tracecmd_create_buffer_recorder_maxkb(const char *file, int cpu, unsigned flags,
if (fd2 < 0)
goto err;
- recorder = tracecmd_create_buffer_recorder_fd2(fd, fd2, cpu, flags, buffer, maxkb);
+ recorder = tracecmd_create_buffer_recorder_fd2(fd, fd2, cpu, flags, instance, maxkb);
if (!recorder)
goto err2;
out:
@@ -333,9 +241,9 @@ tracecmd_create_buffer_recorder_maxkb(const char *file, int cpu, unsigned flags,
struct tracecmd_recorder *
tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags,
- const char *buffer)
+ struct tracefs_instance *instance)
{
- return __tracecmd_create_buffer_recorder(file, cpu, flags, buffer);
+ return __tracecmd_create_buffer_recorder(file, cpu, flags, instance, -1);
}
/**
@@ -350,53 +258,23 @@ 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;
+ return __tracecmd_create_buffer_recorder(file, cpu, flags, NULL, trace_fd);
}
struct tracecmd_recorder *tracecmd_create_recorder_fd(int fd, int cpu, unsigned flags)
{
- const char *tracing;
-
- tracing = tracefs_tracing_dir();
- if (!tracing) {
- errno = ENODEV;
- return NULL;
- }
-
- return tracecmd_create_buffer_recorder_fd(fd, cpu, flags, tracing);
+ return tracecmd_create_buffer_recorder_fd(fd, cpu, flags, NULL);
}
struct tracecmd_recorder *tracecmd_create_recorder(const char *file, int cpu, unsigned flags)
{
- const char *tracing;
-
- tracing = tracefs_tracing_dir();
- if (!tracing) {
- errno = ENODEV;
- return NULL;
- }
-
- return tracecmd_create_buffer_recorder(file, cpu, flags, tracing);
+ return tracecmd_create_buffer_recorder(file, cpu, flags, NULL);
}
struct tracecmd_recorder *
tracecmd_create_recorder_maxkb(const char *file, int cpu, unsigned flags, int maxkb)
{
- const char *tracing;
-
- tracing = tracefs_tracing_dir();
- if (!tracing) {
- errno = ENODEV;
- return NULL;
- }
-
- return tracecmd_create_buffer_recorder_maxkb(file, cpu, flags, tracing, maxkb);
+ return tracecmd_create_buffer_recorder_maxkb(file, cpu, flags, NULL, maxkb);
}
static inline void update_fd(struct tracecmd_recorder *recorder, int size)
@@ -437,101 +315,13 @@ static inline void update_fd(struct tracecmd_recorder *recorder, int size)
* Returns -1 on error.
* or bytes of data read.
*/
-static long splice_data(struct tracecmd_recorder *recorder)
-{
- long total_read = 0;
- long read;
- long ret;
-
- read = splice(recorder->trace_fd, NULL, recorder->brass[1], NULL,
- recorder->pipe_size, recorder->trace_fd_flags);
- if (read < 0) {
- if (errno == EAGAIN || errno == EINTR || errno == ENOTCONN)
- return 0;
-
- tracecmd_warning("recorder error in splice input");
- return -1;
- } else if (read == 0)
- return 0;
-
- again:
- ret = splice(recorder->brass[0], NULL, recorder->fd, NULL,
- read, recorder->fd_flags);
- if (ret < 0) {
- if (errno != EAGAIN && errno != EINTR) {
- tracecmd_warning("recorder error in splice output");
- return -1;
- }
- return total_read;
- } else
- update_fd(recorder, ret);
- total_read = ret;
- read -= ret;
- if (read)
- goto again;
-
- return total_read;
-}
-
-/*
- * Returns -1 on error.
- * or bytes of data read.
- */
-static long direct_splice_data(struct tracecmd_recorder *recorder)
-{
- struct pollfd pfd = {
- .fd = recorder->trace_fd,
- .events = POLLIN,
- };
- long read;
- int ret;
-
- /*
- * splice(2) in Linux used to not check O_NONBLOCK flag of pipe file
- * descriptors before [1]. To avoid getting blocked in the splice(2)
- * call below after the user had requested to stop tracing, we poll(2)
- * here. This poll() is not necessary on newer kernels.
- *
- * [1] https://github.com/torvalds/linux/commit/ee5e001196d1345b8fee25925ff5f1d67936081e
- */
- ret = poll(&pfd, 1, POLL_TIMEOUT_MS);
- if (ret < 0)
- return -1;
-
- if (!(pfd.revents | POLLIN))
- return 0;
-
- read = splice(recorder->trace_fd, NULL, recorder->fd, NULL,
- recorder->pipe_size, recorder->fd_flags);
- if (read < 0) {
- if (errno == EAGAIN || errno == EINTR || errno == ENOTCONN)
- return 0;
-
- tracecmd_warning("recorder error in splice input");
- return -1;
- }
-
- return read;
-}
-
-/*
- * Returns -1 on error.
- * or bytes of data read.
- */
static long read_data(struct tracecmd_recorder *recorder)
{
- char buf[recorder->page_size];
+ char buf[recorder->subbuf_size];
long left;
long r, w;
- r = read(recorder->trace_fd, buf, recorder->page_size);
- if (r < 0) {
- if (errno == EAGAIN || errno == EINTR || errno == ENOTCONN)
- return 0;
-
- tracecmd_warning("recorder error in read input");
- return -1;
- }
+ r = tracefs_cpu_read(recorder->tcpu, buf, false);
left = r;
do {
@@ -548,20 +338,34 @@ static long read_data(struct tracecmd_recorder *recorder)
return r;
}
+/*
+ * Returns -1 on error.
+ * or bytes of data read.
+ */
+static long direct_splice_data(struct tracecmd_recorder *recorder)
+{
+ return tracefs_cpu_pipe(recorder->tcpu, recorder->fd, false);
+}
+
static long move_data(struct tracecmd_recorder *recorder)
{
+ long ret;
+
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);
+ ret = tracefs_cpu_write(recorder->tcpu, recorder->fd, false);
+ if (ret > 0)
+ update_fd(recorder, ret);
+ return ret;
}
long tracecmd_flush_recording(struct tracecmd_recorder *recorder)
{
- char buf[recorder->page_size];
+ char buf[recorder->subbuf_size];
long total = 0;
long wrote = 0;
long ret;
@@ -569,28 +373,17 @@ long tracecmd_flush_recording(struct tracecmd_recorder *recorder)
set_nonblock(recorder);
do {
- ret = move_data(recorder);
- if (ret < 0)
- return ret;
- total += ret;
- } while (ret);
-
- /* splice only reads full pages */
- do {
- ret = read(recorder->trace_fd, buf, recorder->page_size);
- if (ret > 0) {
- write(recorder->fd, buf, ret);
+ ret = tracefs_cpu_flush_write(recorder->tcpu, recorder->fd);
+ if (ret > 0)
wrote += ret;
- }
-
} while (ret > 0);
/* Make sure we finish off with a page size boundary */
- wrote &= recorder->page_size - 1;
+ wrote &= recorder->subbuf_size - 1;
if (wrote) {
- memset(buf, 0, recorder->page_size);
- write(recorder->fd, buf, recorder->page_size - wrote);
- total += recorder->page_size;
+ memset(buf, 0, recorder->subbuf_size);
+ write(recorder->fd, buf, recorder->subbuf_size - wrote);
+ total += recorder->subbuf_size;
}
return total;
@@ -615,10 +408,13 @@ int tracecmd_start_recording(struct tracecmd_recorder *recorder, unsigned long s
read = 0;
do {
ret = move_data(recorder);
- if (ret < 0)
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
return ret;
+ }
read += ret;
- } while (ret);
+ } while (ret > 0 && !recorder->stop);
} while (!recorder->stop);
/* Flush out the rest */