I am currently in the process of porting blktrace userspace program into Golang.
Everything works fine except for poll().
http://git.kernel.dk/cgit/blktrace/tree/blktrace.c#n1828
From the blktrace source code linked above, poll() is used to poll the per-cpu buffers from relayfs endpoints (/sys/kernel/debug/block/DEVICE/trace_CPU#_).
The issue I’m having with my implementation is that poll just times out and returns no POLLIN event during normal operation. I am using the same timeout as blktrace (500). I have also run btrace alongside my example code, blktrace poll working as intended and my implementation is getting no POLLIN events.
package main
import (
"fmt"
"log"
"time"
"syscall"
"golang.org/x/sys/unix"
)
func main() {
//change path to your trace0 location
path := "/sys/kernel/debug/block/vda1/trace0"
timeout := 500
f, err := syscall.Open(path, syscall.O_RDONLY|syscall.O_NONBLOCK, 0666)
if err != nil {
log.Fatalf("failed to open %q: %v (%#[2]v)", path, err)
}
defer syscall.Close(f)
start := time.Now()
fds := []unix.PollFd{{Fd: int32(f), Events: unix.POLLIN}}
for true {
n, err := unix.Poll(fds, timeout)
if fds[0].Revents & unix.POLLIN == unix.POLLIN {
fmt.Printf("n=%d err=%v delay=%v flags=%016b (POLLIN=%t)\n",
n, err, time.Since(start), fds[0].Revents, fds[0].Revents&unix.POLLIN != 0)
}
}
}
I changed the code to use syscall.Open due to os.Open adding the fd to epoll (found out during strace debugging), I thought that may have been the issue but it seems not.
Regarding the ‘no POLLIN event during normal operation’ quote, I have noticed that when I have been running btrace alongside my example code, that when I exit btrace I will get POLLIN events.
To note, I have verified the rest of the codebase works. I have read from the buffers using a for loop with read() enclosed, but causes high cpu usage. I have tried tail and inotify solutions, but relayfs endpoints are not seekable so tail wont work with them and inotify does not work for sysfs.
I have also tested the example code against other pollable files blktrace uses (dropped, msg) and both provide POLLIN events as intended. These are debugfs files instead of relay channels though.
Any ideas how I could get this to work, or ideas for another way of polling?
Thanks in advance!