mirror of
https://github.com/slackhq/nebula.git
synced 2026-05-16 04:47:38 +02:00
overlay/tio: KeepAlive poll-path readv/writev buffers too
The Poll fallback (used when IFF_VNET_HDR can't be enabled) has the same unsafe-pointer-via-uintptr pattern as Offload.rawWrite: readOne/writeOne build a [2]syscall.Iovec on the stack, pass it to syscall.Syscall as uintptr, and the kernel then DMAs in/out of the to/from slices whose Base pointers the iovec holds. Escape analysis can't see that use, so under GC pressure the backing memory could be collected or moved mid-syscall. Add runtime.KeepAlive on the iovec and the user buffer around both the SYS_READV and SYS_WRITEV syscalls. Same pattern and rationale as the prior commit on the offload path.
This commit is contained in:
@@ -3,6 +3,7 @@ package tio
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -120,6 +121,13 @@ func (t *Poll) readOne(to []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
n, _, errno := syscall.Syscall(syscall.SYS_READV, uintptr(t.fd), uintptr(unsafe.Pointer(&iovecs[0])), 2)
|
n, _, errno := syscall.Syscall(syscall.SYS_READV, uintptr(t.fd), uintptr(unsafe.Pointer(&iovecs[0])), 2)
|
||||||
|
// Pin the iovec + destination buffer backing array across the syscall.
|
||||||
|
// Without these the Go runtime may move/GC them while the kernel is
|
||||||
|
// still writing via DMA (we pass the iovec as uintptr, which hides it
|
||||||
|
// from escape analysis). Same class of bug as rawWrite in the Offload
|
||||||
|
// path.
|
||||||
|
runtime.KeepAlive(iovecs)
|
||||||
|
runtime.KeepAlive(to)
|
||||||
if errno == 0 {
|
if errno == 0 {
|
||||||
bytesRead := int(n)
|
bytesRead := int(n)
|
||||||
if bytesRead < 4 {
|
if bytesRead < 4 {
|
||||||
@@ -166,6 +174,10 @@ func (t *Poll) Write(from []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
n, _, errno := syscall.Syscall(syscall.SYS_WRITEV, uintptr(t.fd), uintptr(unsafe.Pointer(&iovecs[0])), 2)
|
n, _, errno := syscall.Syscall(syscall.SYS_WRITEV, uintptr(t.fd), uintptr(unsafe.Pointer(&iovecs[0])), 2)
|
||||||
|
// Pin the iovec + source buffer backing array across the syscall.
|
||||||
|
// See readOne's KeepAlive comment for rationale.
|
||||||
|
runtime.KeepAlive(iovecs)
|
||||||
|
runtime.KeepAlive(from)
|
||||||
if errno == 0 {
|
if errno == 0 {
|
||||||
return int(n) - 4, nil
|
return int(n) - 4, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user