fix io_uring tun device reads

Well that's an interesting one!
Apparently if you issue multiple concurrent preadv calls on
a TUN device using io_uring, the TUN device falls over.

Possibly corrupting memory along the way.
Which might be why the kernel hung on shutdown...
This commit is contained in:
Josh Bleecher Snyder
2021-06-03 17:27:36 -07:00
parent 78dbd02718
commit 9559752cb5
2 changed files with 12 additions and 10 deletions

View File

@@ -568,7 +568,7 @@ func (t *Wrapper) write(buf []byte, offset int) (int, error) {
func (t *Wrapper) read(buf []byte, offset int) (n int, err error) {
// TODO: upstream has graceful shutdown error handling here.
buff := buf[offset-4:]
const useIOUring = false
const useIOUring = true
if useIOUring {
n, err = t.ring.Read(buff[:])
} else {

View File

@@ -277,7 +277,7 @@ type File struct {
close sync.Once
file *os.File // must keep file from being GC'd
fd C.int
readReqs [8]*C.goreq
readReqs [1]*C.goreq // Whoops! The kernel apparently cannot handle more than 1 concurrent preadv calls on a tun device!
writeReqs [8]*C.goreq
writeReqC chan int // indices into reqs
}
@@ -299,10 +299,11 @@ func NewFile(file *os.File) (*File, error) {
}
// Initialize buffers
for _, reqs := range []*[8]*C.goreq{&u.readReqs, &u.writeReqs} {
for i := range reqs {
reqs[i] = C.initializeReq(bufferSize)
}
for i := range &u.readReqs {
u.readReqs[i] = C.initializeReq(bufferSize)
}
for i := range &u.writeReqs {
u.writeReqs[i] = C.initializeReq(bufferSize)
}
// Initialize read half.
@@ -413,10 +414,11 @@ func (u *File) Close() error {
u.fd = 0
// Free buffers
for _, reqs := range []*[8]*C.goreq{&u.readReqs, &u.writeReqs} {
for _, r := range reqs {
C.freeReq(r)
}
for _, r := range u.readReqs {
C.freeReq(r)
}
for _, r := range u.writeReqs {
C.freeReq(r)
}
})
return nil