[lxc-devel] [lxd/master] lxd/devices: Iterate /sys/class/drm for GPUs
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Aug 16 01:45:22 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 370 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180816/9a3e349d/attachment.bin>
-------------- next part --------------
From 748c327fba668f1c2649c07b3dd56965df668b07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 15 Aug 2018 15:09:11 -0400
Subject: [PATCH] lxd/devices: Iterate /sys/class/drm for GPUs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #4925
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/devices.go | 43 ++++++++++++++++++++++++++++++++++---------
1 file changed, 34 insertions(+), 9 deletions(-)
diff --git a/lxd/devices.go b/lxd/devices.go
index 493b14a06b..5a4758e97e 100644
--- a/lxd/devices.go
+++ b/lxd/devices.go
@@ -166,28 +166,44 @@ func deviceWantsAllGPUs(m map[string]string) bool {
}
func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
- const DRI_PATH = "/sys/bus/pci/devices"
+ const DRM_PATH = "/sys/class/drm/"
var gpus []gpuDevice
var nvidiaDevices []nvidiaGpuDevices
var cards []cardIds
- ents, err := ioutil.ReadDir(DRI_PATH)
+ // Get the list of DRM devices
+ ents, err := ioutil.ReadDir(DRM_PATH)
if err != nil {
+ // No GPUs
if os.IsNotExist(err) {
return nil, nil, nil
}
+
return nil, nil, err
}
- isNvidia := false
+ // Get the list of cards
+ devices := []string{}
for _, ent := range ents {
+ dev, err := filepath.EvalSymlinks(fmt.Sprintf("%s/%s/device", DRM_PATH, ent.Name()))
+ if err != nil {
+ continue
+ }
+
+ if !shared.StringInSlice(dev, devices) {
+ devices = append(devices, dev)
+ }
+ }
+
+ isNvidia := false
+ for _, device := range devices {
// The pci address == the name of the directory. So let's use
// this cheap way of retrieving it.
- pciAddr := ent.Name()
+ pciAddr := filepath.Base(device)
// Make sure that we are dealing with a GPU by looking whether
// the "drm" subfolder exists.
- drm := filepath.Join(DRI_PATH, pciAddr, "drm")
+ drm := filepath.Join(device, "drm")
drmEnts, err := ioutil.ReadDir(drm)
if err != nil {
if os.IsNotExist(err) {
@@ -196,7 +212,7 @@ func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
}
// Retrieve vendor ID.
- vendorIdPath := filepath.Join(DRI_PATH, pciAddr, "vendor")
+ vendorIdPath := filepath.Join(device, "vendor")
vendorId, err := ioutil.ReadFile(vendorIdPath)
if err != nil {
if os.IsNotExist(err) {
@@ -205,7 +221,7 @@ func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
}
// Retrieve device ID.
- productIdPath := filepath.Join(DRI_PATH, pciAddr, "device")
+ productIdPath := filepath.Join(device, "device")
productId, err := ioutil.ReadFile(productIdPath)
if err != nil {
if os.IsNotExist(err) {
@@ -215,7 +231,7 @@ func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
// Store all associated subdevices, e.g. controlD64, renderD128.
// The name of the directory == the last part of the
- // /dev/dri/controlD64 path. So ent.Name() will give us
+ // /dev/dri/controlD64 path. So drmEnt.Name() will give us
// controlD64.
for _, drmEnt := range drmEnts {
vendorTmp := strings.TrimSpace(string(vendorId))
@@ -236,15 +252,18 @@ func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
continue
}
}
+
majMin := strings.TrimSpace(string(majMinByte))
majMinSlice := strings.Split(string(majMin), ":")
if len(majMinSlice) != 2 {
continue
}
+
majorInt, err := strconv.Atoi(majMinSlice[0])
if err != nil {
continue
}
+
minorInt, err := strconv.Atoi(majMinSlice[1])
if err != nil {
continue
@@ -278,6 +297,7 @@ func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
return nil, nil, err
}
+
tmpGpu.nvidia.path = nvidiaPath
tmpGpu.nvidia.major = shared.Major(stat.Rdev)
tmpGpu.nvidia.minor = shared.Minor(stat.Rdev)
@@ -293,8 +313,10 @@ func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
id: tmpGpu.id,
pci: tmpGpu.pci,
}
+
cards = append(cards, tmp)
}
+
gpus = append(gpus, tmpGpu)
}
}
@@ -313,6 +335,7 @@ func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
if err != nil {
return nil, nil, err
}
+
for _, nvidiaEnt := range nvidiaEnts {
if all {
if !strings.HasPrefix(nvidiaEnt.Name(), "nvidia") {
@@ -323,21 +346,23 @@ func deviceLoadGpu(all bool) ([]gpuDevice, []nvidiaGpuDevices, error) {
continue
}
}
+
nvidiaPath := filepath.Join("/dev", nvidiaEnt.Name())
stat := syscall.Stat_t{}
err = syscall.Stat(nvidiaPath, &stat)
if err != nil {
continue
}
+
tmpNividiaGpu := nvidiaGpuDevices{
isCard: !validNvidia.MatchString(nvidiaEnt.Name()),
path: nvidiaPath,
major: shared.Major(stat.Rdev),
minor: shared.Minor(stat.Rdev),
}
+
nvidiaDevices = append(nvidiaDevices, tmpNividiaGpu)
}
-
}
// Since we'll give users to ability to specify and id we need to group
More information about the lxc-devel
mailing list