| 39 | } |
| 40 | |
| 41 | func GPUs(ctx context.Context, log slog.Logger, usrLibDir string) ([]Device, []mount.MountPoint, error) { |
| 42 | var ( |
| 43 | afs = GetFS(ctx) |
| 44 | mounter = Mounter(ctx) |
| 45 | devices = []Device{} |
| 46 | binds = []mount.MountPoint{} |
| 47 | ) |
| 48 | |
| 49 | mounts, err := mounter.List() |
| 50 | if err != nil { |
| 51 | return nil, nil, xerrors.Errorf("list mounts: %w", err) |
| 52 | } |
| 53 | |
| 54 | for _, m := range mounts { |
| 55 | if gpuMountRegex.MatchString(m.Path) { |
| 56 | // If we find the GPU in /dev treat it as a device. |
| 57 | if strings.HasPrefix(m.Path, "/dev/") { |
| 58 | // TODO(JonA): We could populate the rest of the fields but it |
| 59 | // doesn't seem like we need them. We'll have to expand |
| 60 | // the FS interface to allow for a real unix stat. |
| 61 | devices = append(devices, Device{ |
| 62 | Path: m.Path, |
| 63 | }) |
| 64 | continue |
| 65 | } |
| 66 | |
| 67 | // If it's not in /dev treat it as a bind mount. |
| 68 | binds = append(binds, m) |
| 69 | // We also want to find any symlinks that point to the target. |
| 70 | // This is important for the nvidia driver as it mounts the driver |
| 71 | // files with the driver version appended to the end, and creates |
| 72 | // symlinks that point to the actual files. |
| 73 | links, err := SameDirSymlinks(afs, m.Path) |
| 74 | if err != nil { |
| 75 | log.Error(ctx, "find symlinks", slog.F("path", m.Path), slog.Error(err)) |
| 76 | } else { |
| 77 | for _, link := range links { |
| 78 | log.Debug(ctx, "found symlink", slog.F("link", link), slog.F("target", m.Path)) |
| 79 | binds = append(binds, mount.MountPoint{ |
| 80 | Path: link, |
| 81 | Opts: []string{"ro"}, |
| 82 | }) |
| 83 | } |
| 84 | } |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | extraGPUS, err := usrLibGPUs(ctx, log, usrLibDir) |
| 89 | if err != nil { |
| 90 | return nil, nil, xerrors.Errorf("find %q gpus: %w", usrLibDir, err) |
| 91 | } |
| 92 | |
| 93 | for _, gpu := range extraGPUS { |
| 94 | var duplicate bool |
| 95 | for _, bind := range binds { |
| 96 | if gpu.Path == bind.Path { |
| 97 | duplicate = true |
| 98 | break |