Use bpf_prog_stream_open() in its default blocking mode when following a program stream. This lets bpftool wait for later output instead of exiting as soon as it drains the currently buffered bytes. Flush each chunk as it arrives so redirected output is not held in stdio buffers while the next read blocks. Fall back to BPF_PROG_STREAM_READ_BY_FD when the open command returns EINVAL. The bpf() syscall uses EINVAL for unknown commands, so this keeps a new bpftool compatible with kernels that provide program streams but predate their file descriptor interface. Signed-off-by: Kumar Kartikeya Dwivedi --- tools/bpf/bpftool/prog.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index a9f730d407a9..6b43cb43b27e 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -1125,14 +1125,27 @@ prog_tracelog_stream(int prog_fd, enum prog_tracelog_mode mode) FILE *file = mode == TRACE_STDOUT ? stdout : stderr; int stream_id = mode == TRACE_STDOUT ? 1 : 2; char buf[512]; - int ret; - - ret = 0; - do { - ret = bpf_prog_stream_read(prog_fd, stream_id, buf, sizeof(buf), NULL); - if (ret > 0) - fwrite(buf, sizeof(buf[0]), ret, file); - } while (ret > 0); + int fd, ret; + + fd = bpf_prog_stream_open(prog_fd, stream_id, NULL); + if (fd == -EINVAL) { + do { + ret = bpf_prog_stream_read(prog_fd, stream_id, buf, sizeof(buf), NULL); + if (ret > 0) + fwrite(buf, sizeof(buf[0]), ret, file); + } while (ret > 0); + } else { + if (fd < 0) + return -1; + do { + ret = read(fd, buf, sizeof(buf)); + if (ret > 0) { + fwrite(buf, sizeof(buf[0]), ret, file); + fflush(file); + } + } while (ret > 0); + close(fd); + } fflush(file); return ret ? -1 : 0; -- 2.53.0