From e2c866265299cb152d149d037a65b6434b6937cb Mon Sep 17 00:00:00 2001 From: Juerg Ritter Date: Sun, 9 Jun 2024 16:45:16 +0200 Subject: [PATCH] rework drm representation --- sysfs/class_drm_card.go | 108 +++++++++++++++++++++++++++-------- sysfs/class_drm_card_port.go | 94 ------------------------------ sysfs/class_drm_card_test.go | 32 ++++++++--- testdata/fixtures.ttar | 28 +++++++++ 4 files changed, 135 insertions(+), 127 deletions(-) delete mode 100644 sysfs/class_drm_card_port.go diff --git a/sysfs/class_drm_card.go b/sysfs/class_drm_card.go index d0c12a227..147b7a2e2 100644 --- a/sysfs/class_drm_card.go +++ b/sysfs/class_drm_card.go @@ -11,58 +11,118 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package sysfs import ( - "errors" + "fmt" "path/filepath" - "syscall" "github.com/prometheus/procfs/internal/util" ) -type ClassDrmCard struct { +const drmClassPath = "class/drm" + +// DrmCard contains info from files in /sys/class/drm for a +// single DRM Card device. +type DrmCard struct { Name string - Enable uint64 Driver string + Ports map[string]DrmCardPort +} + +// DrmCardPort contains info from files in +// /sys/class/drm//- +// for a single port of one DrmCard device. +type DrmCardPort struct { + Name string + Status string + Dpms string + Enabled string } -func (fs FS) ClassDrmCard() ([]ClassDrmCard, error) { +// DrmCardClass is a collection of every Card device in +// /sys/class/drm. +// +// The map keys are the names of the InfiniBand devices. +type DrmCardClass map[string]DrmCard + +// DrmCardClass returns infos for all Drm devices read from +// /sys/class/drm. +func (fs FS) DrmCardClass() (DrmCardClass, error) { + cards, err := filepath.Glob(fs.sys.Path("class/drm/card[0-9]")) + if err != nil { - return nil, err + return nil, fmt.Errorf("failed to list DRM card ports at %q: %w", cards, err) + } + + drmCardClass := make(DrmCardClass, len(cards)) + for _, c := range cards { + card, err := fs.parseDrmCard(filepath.Base(c)) + if err != nil { + return nil, err + } + + drmCardClass[card.Name] = *card + } + + return drmCardClass, nil +} + +// Parse one DrmCard. +func (fs FS) parseDrmCard(name string) (*DrmCard, error) { + path := fs.sys.Path(drmClassPath, name) + card := DrmCard{Name: name} + + // Read the kernel module of the card + cardDriverPath, err := filepath.EvalSymlinks(filepath.Join(path, "device/driver")) + if err != nil { + return nil, fmt.Errorf("failed to read driver: %w", err) } + card.Driver = filepath.Base(cardDriverPath) - stats := make([]ClassDrmCard, 0, len(cards)) - for _, card := range cards { - cardStats, err := parseClassDrmCard(card) + portsPath, err := filepath.Glob(filepath.Join(path, filepath.Base(path)+"-*-*")) + + if err != nil { + return nil, fmt.Errorf("failed to list DRM card ports at %q: %w", portsPath, err) + } + + card.Ports = make(map[string]DrmCardPort, len(portsPath)) + for _, d := range portsPath { + port, err := parseDrmCardPort(d) if err != nil { - if errors.Is(err, syscall.ENODATA) { - continue - } return nil, err } - cardStats.Name = filepath.Base(card) - stats = append(stats, cardStats) + + card.Ports[port.Name] = *port } - return stats, nil + + return &card, nil } -func parseClassDrmCard(port string) (ClassDrmCard, error) { - cardEnable, err := util.ReadIntFromFile(filepath.Join(port, "device/enable")) +func parseDrmCardPort(port string) (*DrmCardPort, error) { + portStatus, err := util.SysReadFile(filepath.Join(port, "status")) if err != nil { - return ClassDrmCard{}, err + return nil, err + } + + drmCardPort := DrmCardPort{Name: filepath.Base(port), Status: portStatus} + + portDpms, err := util.SysReadFile(filepath.Join(port, "dpms")) + if err != nil { + return nil, err } - cardDriverPath, err := filepath.EvalSymlinks(filepath.Join(port, "device/driver")) + drmCardPort.Dpms = portDpms + + portEnabled, err := util.SysReadFile(filepath.Join(port, "enabled")) if err != nil { - return ClassDrmCard{}, err + return nil, err } + drmCardPort.Enabled = portEnabled - return ClassDrmCard{ - Enable: uint64(cardEnable), - Driver: filepath.Base(cardDriverPath), - }, nil + return &drmCardPort, nil } diff --git a/sysfs/class_drm_card_port.go b/sysfs/class_drm_card_port.go deleted file mode 100644 index e6d2a3e6a..000000000 --- a/sysfs/class_drm_card_port.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2018 The Prometheus 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. - -//go:build !windows -// +build !windows - -package sysfs - -import ( - "errors" - "path/filepath" - "strings" - "syscall" - - "github.com/prometheus/procfs/internal/util" -) - -type ClassDrmCardPort struct { - Name string - Card string - Status uint64 - Dpms uint64 - Enabled uint64 -} - -func (fs FS) ClassDrmCardPort() ([]ClassDrmCardPort, error) { - ports, err := filepath.Glob(fs.sys.Path("class/drm/card[0-9]*-*")) - if err != nil { - return nil, err - } - - stats := make([]ClassDrmCardPort, 0, len(ports)) - for _, port := range ports { - portStats, err := parseClassDrmCardPort(port) - if err != nil { - if errors.Is(err, syscall.ENODATA) { - continue - } - return nil, err - } - portStats.Name = strings.SplitN(filepath.Base(port), "-", 2)[1] - portStats.Card = strings.SplitN(filepath.Base(port), "-", 2)[0] - stats = append(stats, portStats) - } - return stats, nil -} - -func parseClassDrmCardPort(port string) (ClassDrmCardPort, error) { - portStatusString, err := util.SysReadFile(filepath.Join(port, "status")) - if err != nil { - return ClassDrmCardPort{}, err - } - - portStatus := 0 - if portStatusString == "connected" { - portStatus = 1 - } - - portDpmsString, err := util.SysReadFile(filepath.Join(port, "dpms")) - if err != nil { - return ClassDrmCardPort{}, err - } - - portDpms := 0 - if portDpmsString == "On" { - portDpms = 1 - } - - portEnabledString, err := util.SysReadFile(filepath.Join(port, "enabled")) - if err != nil { - return ClassDrmCardPort{}, err - } - - portEnabled := 0 - if portEnabledString == "enabled" { - portEnabled = 1 - } - - return ClassDrmCardPort{ - Status: uint64(portStatus), - Dpms: uint64(portDpms), - Enabled: uint64(portEnabled), - }, nil -} diff --git a/sysfs/class_drm_card_test.go b/sysfs/class_drm_card_test.go index d0e48f7f7..c1bcc78cd 100644 --- a/sysfs/class_drm_card_test.go +++ b/sysfs/class_drm_card_test.go @@ -17,8 +17,9 @@ package sysfs import ( - "reflect" "testing" + + "github.com/google/go-cmp/cmp" ) func TestClassDRMCard(t *testing.T) { @@ -27,25 +28,38 @@ func TestClassDRMCard(t *testing.T) { t.Fatal(err) } - drmCardTest, err := fs.ClassDrmCard() + got, err := fs.DrmCardClass() if err != nil { t.Fatal(err) } - classDrmCard := []ClassDrmCard{ - { + want := DrmCardClass{ + "card0": DrmCard{ Name: "card0", - Enable: 1, Driver: "amdgpu", + Ports: map[string]DrmCardPort{}, }, - { + "card1": DrmCard{ Name: "card1", - Enable: 1, Driver: "i915", + Ports: map[string]DrmCardPort{ + "card1-DP-1": { + Name: "card1-DP-1", + Dpms: "Off", + Enabled: "disabled", + Status: "disconnected", + }, + "card1-DP-5": { + Name: "card1-DP-5", + Dpms: "On", + Enabled: "enabled", + Status: "connected", + }, + }, }, } - if !reflect.DeepEqual(classDrmCard, drmCardTest) { - t.Errorf("Result not correct: want %v, have %v", classDrmCard, drmCardTest) + if diff := cmp.Diff(want, got); diff != "" { + t.Fatalf("unexpected DRMCard class (-want +got):\n%s", diff) } } diff --git a/testdata/fixtures.ttar b/testdata/fixtures.ttar index 2362c4b54..52e657857 100644 --- a/testdata/fixtures.ttar +++ b/testdata/fixtures.ttar @@ -4958,6 +4958,34 @@ Mode: 755 Directory: fixtures/sys/class/drm/card1/card1-DP-1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/class/drm/card1/card1-DP-1/connector_id +Lines: 1 +103 +Mode: 444 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/class/drm/card1/card1-DP-1/dpms +Lines: 1 +Off +Mode: 444 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/class/drm/card1/card1-DP-1/edid +Lines: 0 +Mode: 444 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/class/drm/card1/card1-DP-1/enabled +Lines: 1 +disabled +Mode: 444 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/class/drm/card1/card1-DP-1/modes +Lines: 0 +Mode: 444 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/class/drm/card1/card1-DP-1/status +Lines: 1 +disconnected +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/drm/card1/card1-DP-5 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -