Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

btf: don't cache kernel BTF in LoadKernelSpec #676

Merged
merged 1 commit into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions btf/btf.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"math"
"os"
"reflect"
"sync"

"github.com/cilium/ebpf/internal"
"github.com/cilium/ebpf/internal/sys"
Expand Down Expand Up @@ -255,32 +254,11 @@ func indexTypes(types []Type) (map[Type]TypeID, map[essentialName][]Type) {
return typeIDs, typesByName
}

var kernelBTF struct {
sync.Mutex
*Spec
}

// LoadKernelSpec returns the current kernel's BTF information.
//
// Requires a >= 5.5 kernel with CONFIG_DEBUG_INFO_BTF enabled. Returns
// ErrNotSupported if BTF is not enabled.
// Defaults to /sys/kernel/btf/vmlinux and falls back to scanning the file system
// for vmlinux ELFs. Returns an error wrapping ErrNotSupported if BTF is not enabled.
func LoadKernelSpec() (*Spec, error) {
kernelBTF.Lock()
defer kernelBTF.Unlock()

if kernelBTF.Spec != nil {
return kernelBTF.Spec, nil
}

var err error
kernelBTF.Spec, err = loadKernelSpec()
return kernelBTF.Spec, err
}

// loadKernelSpec attempts to load the raw vmlinux BTF blob at
// /sys/kernel/btf/vmlinux and falls back to scanning the file system
// for vmlinux ELFs.
func loadKernelSpec() (*Spec, error) {
fh, err := os.Open("/sys/kernel/btf/vmlinux")
if err == nil {
defer fh.Close()
Expand Down
2 changes: 1 addition & 1 deletion btf/btf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func BenchmarkParseVmlinux(b *testing.B) {
}

func TestParseCurrentKernelBTF(t *testing.T) {
spec, err := loadKernelSpec()
spec, err := LoadKernelSpec()
testutils.SkipIfNotSupported(t, err)
if err != nil {
t.Fatal("Can't load BTF:", err)
Expand Down
36 changes: 30 additions & 6 deletions linker.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ebpf
import (
"errors"
"fmt"
"sync"

"github.com/cilium/ebpf/asm"
"github.com/cilium/ebpf/btf"
Expand Down Expand Up @@ -140,12 +141,9 @@ func applyRelocations(insns asm.Instructions, local, target *btf.Spec) error {
return nil
}

if target == nil {
var err error
target, err = btf.LoadKernelSpec()
if err != nil {
return err
}
target, err := maybeLoadKernelBTF(target)
if err != nil {
return err
}

fixups, err := btf.CORERelocate(local, target, relos)
Expand Down Expand Up @@ -200,3 +198,29 @@ func fixupProbeReadKernel(ins *asm.Instruction) {
ins.Constant = int64(asm.FnProbeReadStr)
}
}

var kernelBTF struct {
sync.Mutex
spec *btf.Spec
}

// maybeLoadKernelBTF loads the current kernel's BTF if spec is nil, otherwise
// it returns spec unchanged.
//
// The kernel BTF is cached for the lifetime of the process.
func maybeLoadKernelBTF(spec *btf.Spec) (*btf.Spec, error) {
if spec != nil {
return spec, nil
}

kernelBTF.Lock()
defer kernelBTF.Unlock()

if kernelBTF.spec != nil {
return kernelBTF.spec, nil
}

var err error
kernelBTF.spec, err = btf.LoadKernelSpec()
return kernelBTF.spec, err
}
13 changes: 4 additions & 9 deletions prog.go
Original file line number Diff line number Diff line change
Expand Up @@ -801,17 +801,12 @@ func findTargetInKernel(spec *btf.Spec, name string, progType ProgramType, attac
return 0, errUnrecognizedAttachType
}

var (
target btf.Type
err error
)
if spec == nil {
spec, err = btf.LoadKernelSpec()
if err != nil {
return 0, fmt.Errorf("load kernel spec: %w", err)
}
spec, err := maybeLoadKernelBTF(spec)
if err != nil {
return 0, fmt.Errorf("load kernel spec: %w", err)
}

var target btf.Type
if isBTFTypeFunc {
var targetFunc *btf.Func
err = spec.TypeByName(typeName, &targetFunc)
Expand Down