fix: require explicit build tags for io_uring backends, add implementation logging

All three io_uring backends (iceber, giouring, raw) now require explicit
build tags — no tag means standard-only. Each backend registers its name
via IOUringImpl so startup logs show compiled implementation alongside
requested/selected backend mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ping QiuandClaude Opus 4.6 committed 2026-03-10 18:19:31 -07:00
1 parent cd1e0afa3b
commit 003b8c2f28
6 files changed
+28 -8

No files matched your search

+5
View File
@@ -23,6 +23,11 @@ import (
// Callers decide whether to fall back to standard or fail.
var ErrIOUringUnavailable = errors.New("batchio: io_uring unavailable")
// IOUringImpl reports the compiled io_uring implementation name.
// Set by each iouring_*_linux.go file. Empty string means no io_uring
// backend was compiled in (standard only).
var IOUringImpl string
// Op represents a single I/O operation: read or write buf at offset.
type Op struct {
Buf []byte
@@ -10,6 +10,8 @@ import (
"github.com/pawelgaczynski/giouring"
)
func init() { IOUringImpl = "giouring" }
// giouringBatchIO implements BatchIO using giouring (direct liburing port).
// No goroutines or channels — direct SQE/CQE ring manipulation.
// Requires kernel 6.0+.
@@ -9,6 +9,8 @@ import (
"github.com/iceber/iouring-go"
)
func init() { IOUringImpl = "iceber" }
// ioUringBatchIO implements BatchIO using Linux io_uring.
// Requires kernel 5.6+ (linked fsync: 5.10+).
type ioUringBatchIO struct {
@@ -1,9 +1,12 @@
//go:build !linux || no_iouring
//go:build !linux || (!iouring_iceber && !iouring_giouring && !iouring_raw)
package batchio
// NewIOUring returns ErrIOUringUnavailable on non-Linux platforms
// or when io_uring is disabled via the no_iouring build tag.
// NewIOUring returns ErrIOUringUnavailable when no io_uring backend is
// compiled in. On Linux, use one of these build tags to enable a backend:
// - iouring_iceber (iceber/iouring-go library)
// - iouring_giouring (pawelgaczynski/giouring library)
// - iouring_raw (raw syscall wrappers, zero deps)
func NewIOUring(ringSize uint) (BatchIO, error) {
return nil, ErrIOUringUnavailable
}
@@ -1,4 +1,4 @@
//go:build linux && !no_iouring && !iouring_iceber && !iouring_giouring
//go:build linux && iouring_raw
package batchio
@@ -10,6 +10,8 @@ import (
"unsafe"
)
func init() { IOUringImpl = "raw" }
// Raw io_uring syscall numbers.
const (
sysIOUringSetup = 425
+10 -4
View File
@@ -1165,25 +1165,31 @@ func (v *BlockVol) Close() error {
// - "auto": tries io_uring, falls back to standard with warning
// - "io_uring": requires io_uring, returns error if unavailable
func newBatchIO(mode IOBackendMode, logger *log.Logger) (batchio.BatchIO, string, error) {
impl := batchio.IOUringImpl // compiled-in implementation ("iceber", "giouring", "raw", or "")
if impl == "" {
impl = "none"
}
switch mode {
case IOBackendIOUring:
bio, err := batchio.NewIOUring(256)
if err != nil {
return nil, "", fmt.Errorf("io_uring requested but unavailable: %w", err)
return nil, "", fmt.Errorf("io_uring requested but unavailable (compiled=%s): %w", impl, err)
}
logger.Printf("io backend: requested=io_uring selected=io_uring")
logger.Printf("io backend: requested=io_uring implementation=%s selected=io_uring", impl)
return bio, "io_uring", nil
case IOBackendAuto:
bio, err := batchio.NewIOUring(256)
if err != nil {
logger.Printf("io backend: requested=auto selected=standard reason=%v", err)
logger.Printf("io backend: requested=auto implementation=%s selected=standard reason=%v", impl, err)
return batchio.NewStandard(), "standard", nil
}
logger.Printf("io backend: requested=auto selected=io_uring")
logger.Printf("io backend: requested=auto implementation=%s selected=io_uring", impl)
return bio, "io_uring", nil
default: // IOBackendStandard or empty
logger.Printf("io backend: requested=standard implementation=%s selected=standard", impl)
return batchio.NewStandard(), "standard", nil
}
}