diff --git a/link/link.go b/link/link.go index 9e8ca49c6..9c34616c9 100644 --- a/link/link.go +++ b/link/link.go @@ -119,7 +119,7 @@ func wrapRawLink(raw *RawLink) (_ Link, err error) { case UprobeMultiType: return &uprobeMultiLink{*raw}, nil case PerfEventType: - return nil, fmt.Errorf("recovering perf event fd: %w", ErrNotSupported) + return &perfEventLink{*raw, nil}, nil case TCXType: return &tcxLink{*raw}, nil case NetfilterType: diff --git a/link/perf_event.go b/link/perf_event.go index 89eab233b..1d8feb58c 100644 --- a/link/perf_event.go +++ b/link/perf_event.go @@ -99,30 +99,16 @@ type perfEventLink struct { func (pl *perfEventLink) isLink() {} -// Pinning requires the underlying perf event FD to stay open. -// -// | PerfEvent FD | BpfLink FD | Works | -// |--------------|------------|-------| -// | Open | Open | Yes | -// | Closed | Open | No | -// | Open | Closed | No (Pin() -> EINVAL) | -// | Closed | Closed | No (Pin() -> EINVAL) | -// -// There is currently no pretty way to recover the perf event FD -// when loading a pinned link, so leave as not supported for now. -func (pl *perfEventLink) Pin(string) error { - return fmt.Errorf("perf event link pin: %w", ErrNotSupported) -} - -func (pl *perfEventLink) Unpin() error { - return fmt.Errorf("perf event link unpin: %w", ErrNotSupported) -} - func (pl *perfEventLink) Close() error { if err := pl.fd.Close(); err != nil { return fmt.Errorf("perf link close: %w", err) } + // when created from pinned link + if pl.pe == nil { + return nil + } + if err := pl.pe.Close(); err != nil { return fmt.Errorf("perf event close: %w", err) } @@ -136,6 +122,11 @@ func (pl *perfEventLink) Update(prog *ebpf.Program) error { var _ PerfEvent = (*perfEventLink)(nil) func (pl *perfEventLink) PerfEvent() (*os.File, error) { + // when created from pinned link + if pl.pe == nil { + return nil, ErrNotSupported + } + fd, err := pl.pe.fd.Dup() if err != nil { return nil, err