2022-11-23 15:29:18 +00:00
/ * *
# Copyright ( c ) NVIDIA CORPORATION . All rights reserved .
#
# 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 .
* * /
2023-02-22 15:10:28 +00:00
package nvcdi
2022-11-23 15:29:18 +00:00
import (
2022-12-02 13:17:52 +00:00
"fmt"
2022-11-23 15:29:18 +00:00
"path/filepath"
"github.com/NVIDIA/nvidia-container-toolkit/internal/discover"
2023-03-22 12:27:43 +00:00
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
2022-11-23 15:29:18 +00:00
)
type deviceFolderPermissions struct {
2024-04-24 08:47:45 +00:00
logger logger . Interface
devRoot string
nvidiaCDIHookPath string
devices discover . Discover
2022-11-23 15:29:18 +00:00
}
var _ discover . Discover = ( * deviceFolderPermissions ) ( nil )
2023-02-22 15:10:28 +00:00
// newDeviceFolderPermissionHookDiscoverer creates a discoverer that can be used to update the permissions for the parent folders of nested device nodes from the specified set of device specs.
2022-11-23 15:29:18 +00:00
// This works around an issue with rootless podman when using crun as a low-level runtime.
// See https://github.com/containers/crun/issues/1047
2022-12-01 16:21:14 +00:00
// The nested devices that are applicable to the NVIDIA GPU devices are:
// - DRM devices at /dev/dri/*
// - NVIDIA Caps devices at /dev/nvidia-caps/*
2024-04-24 08:47:45 +00:00
func newDeviceFolderPermissionHookDiscoverer ( logger logger . Interface , devRoot string , nvidiaCDIHookPath string , devices discover . Discover ) discover . Discover {
2022-11-23 15:29:18 +00:00
d := & deviceFolderPermissions {
2024-04-24 08:47:45 +00:00
logger : logger ,
devRoot : devRoot ,
nvidiaCDIHookPath : nvidiaCDIHookPath ,
devices : devices ,
2022-11-23 15:29:18 +00:00
}
2023-02-22 15:10:28 +00:00
return d
2022-11-23 15:29:18 +00:00
}
// Devices are empty for this discoverer
func ( d * deviceFolderPermissions ) Devices ( ) ( [ ] discover . Device , error ) {
return nil , nil
}
2022-12-01 16:21:14 +00:00
// Hooks returns a set of hooks that sets the file mode to 755 of parent folders for nested device nodes.
2022-11-23 15:29:18 +00:00
func ( d * deviceFolderPermissions ) Hooks ( ) ( [ ] discover . Hook , error ) {
2023-02-22 15:10:28 +00:00
folders , err := d . getDeviceSubfolders ( )
if err != nil {
return nil , fmt . Errorf ( "failed to get device subfolders: %v" , err )
}
if len ( folders ) == 0 {
2022-12-01 16:21:14 +00:00
return nil , nil
2022-11-23 15:29:18 +00:00
}
2022-12-01 16:21:14 +00:00
args := [ ] string { "--mode" , "755" }
2023-02-22 15:10:28 +00:00
for _ , folder := range folders {
2022-12-01 16:21:14 +00:00
args = append ( args , "--path" , folder )
}
2022-12-12 14:26:21 +00:00
2024-04-24 08:47:45 +00:00
hook := discover . CreateNvidiaCDIHook (
d . nvidiaCDIHookPath ,
2022-12-01 16:21:14 +00:00
"chmod" ,
args ... ,
)
return [ ] discover . Hook { hook } , nil
2022-11-23 15:29:18 +00:00
}
2023-02-22 15:10:28 +00:00
func ( d * deviceFolderPermissions ) getDeviceSubfolders ( ) ( [ ] string , error ) {
// For now we only consider the following special case paths
allowedPaths := map [ string ] bool {
"/dev/dri" : true ,
"/dev/nvidia-caps" : true ,
}
devices , err := d . devices . Devices ( )
if err != nil {
return nil , fmt . Errorf ( "failed to get devices: %v" , err )
}
var folders [ ] string
seen := make ( map [ string ] bool )
for _ , device := range devices {
df := filepath . Dir ( device . Path )
if seen [ df ] {
continue
}
// We only consider the special case paths
if ! allowedPaths [ df ] {
continue
}
folders = append ( folders , df )
seen [ df ] = true
if len ( folders ) == len ( allowedPaths ) {
break
}
}
return folders , nil
}
2022-11-23 15:29:18 +00:00
// Mounts are empty for this discoverer
func ( d * deviceFolderPermissions ) Mounts ( ) ( [ ] discover . Mount , error ) {
return nil , nil
}