diff options
author | Steven Rostedt (Google) <rostedt@goodmis.org> | 2022-11-15 15:48:48 -0500 |
---|---|---|
committer | Steven Rostedt (Google) <rostedt@goodmis.org> | 2022-12-06 18:53:49 -0500 |
commit | 2610bdcde43a63e3a9b2afb2ededab1183acf5fe (patch) | |
tree | 7608074ceed9dfb505dd564e4968bffe9407f0d4 /lib/trace-cmd | |
parent | 1f75010a25939c0c4e1d99df7c40e364e4206e9b (diff) | |
download | trace-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.h | 6 | ||||
-rw-r--r-- | lib/trace-cmd/trace-recorder.c | 330 |
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 */ |