Files
visor/pkg/pinring/pinring_unsafe.go
Etienne Perot d11f1e9bb7 Defer release of slow-to-release FDs via disabled io_uring ring.
`runsc` creates some FDs that are slow to release (`AF_PACKET` sockets for
networking, KVM FDs for the KVM platform).
By releasing them asynchronously, we free up the sandbox process memory
earlier during teardown, allowing better density of sandboxes to exist.

Also allows faster sandbox recycling for systems like Substrate which spawn
a new sandbox as soon as one exits.

This uses an `io_uring` hack to move the release work to a kworker thread.
The ring is held by the gofer (not the Sentry), is disabled
(`IORING_SETUP_R_DISABLED`), and is unusable anyway due to seccomp filters.

Includes a test to verify this kernel implementation detail.

Benchmarks:

```
$ sudo runsc do --platform=kvm --network=sandbox

        │    before      │   after                              │
        │    sec/op      │   sec/op     vs base                 │
RunscDo     459.5m ± 6%     432.5m ± 4%  -5.88% (p=0.001 n=30)

           │     before       │   after                               │
           │     sec/op       │   sec/op     vs base                  │
OCICreate       155.8m ± 5%      155.0m ± 7%        ~ (p=0.623 n=30)
OCIDelete       8.838m ± 4%      7.713m ± 9%  -12.73% (p=0.000 n=30)
OCIExit        80.511m ± 6%      2.015m ± 7%  -97.50% (p=0.000 n=30)
OCIReady        170.6m ± 6%      171.0m ± 7%        ~ (p=0.708 n=30)
OCIStart        15.51m ± 3%      15.97m ± 5%        ~ (p=0.223 n=30)
OCITotal        261.0m ± 5%      180.8m ± 6%  -30.73% (p=0.000 n=30)
```
2026-08-20 18:27:54 -07:00

47 lines
1.6 KiB
Go

// Copyright 2026 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pinring
import (
"fmt"
"os"
"unsafe"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
)
// NewDisabledIOURing returns a new pin ring for donation to its holder.
// Created with `IORING_SETUP_R_DISABLED` and never enabled.
// It accepts no `io_uring` submissions. Only its FD table is ever used.
func NewDisabledIOURing() (*os.File, error) {
params := linux.IOUringParams{Flags: linux.IORING_SETUP_R_DISABLED}
ring, _, errno := unix.Syscall(unix.SYS_IO_URING_SETUP, 1, uintptr(unsafe.Pointer(&params)), 0)
if errno != 0 {
return nil, fmt.Errorf("io_uring_setup: %w", errno)
}
return os.NewFile(ring, "pin ring"), nil
}
// registerFiles pins `fds` into `ring`'s fixed-file table.
// Can only be called once per `io_uring` ring.
func registerFiles(ring int, fds []int32) error {
if _, _, errno := unix.Syscall6(unix.SYS_IO_URING_REGISTER, uintptr(ring), linux.IORING_REGISTER_FILES, uintptr(unsafe.Pointer(&fds[0])), uintptr(len(fds)), 0, 0); errno != 0 {
return fmt.Errorf("io_uring_register(IORING_REGISTER_FILES): %w", errno)
}
return nil
}