10
10
#include <libgen.h>
11
11
#undef basename /* Use the GNU version of basename. */
12
12
#include <limits.h>
13
+ #include <nvidia-modprobe-utils.h>
13
14
#include <stdio.h>
14
15
#include <string.h>
15
16
#include <sched.h>
24
25
25
26
static char * * mount_files (struct error * , const char * , const struct nvc_container * , const char * , char * [], size_t );
26
27
static char * * mount_driverstore_files (struct error * , const char * , const struct nvc_container * , const char * , const char * [], size_t );
28
+ static char * mount_directory (struct error * , const char * , const struct nvc_container * , const char * );
27
29
static char * mount_device (struct error * , const char * , const struct nvc_container * , const struct nvc_device_node * );
28
30
static char * mount_ipc (struct error * , const char * , const struct nvc_container * , const char * );
29
31
static char * mount_procfs (struct error * , const char * , const struct nvc_container * );
@@ -38,6 +40,40 @@ static int symlink_libraries(struct error *, const struct nvc_container *, cons
38
40
static void filter_libraries (const struct nvc_driver_info * , char * [], size_t * );
39
41
static int device_mount_dxcore (struct nvc_context * , const struct nvc_container * );
40
42
static int device_mount_native (struct nvc_context * , const struct nvc_container * , const struct nvc_device * );
43
+ static int cap_device_from_path (struct nvc_context * , const char * , struct nvc_device_node * );
44
+ static int cap_device_mount (struct nvc_context * , const struct nvc_container * , const char * );
45
+ static int setup_mig_minor_cgroups (struct error * , const struct nvc_container * , int , const struct nvc_device_node * );
46
+
47
+ static char *
48
+ mount_directory (struct error * err , const char * root , const struct nvc_container * cnt , const char * dir )
49
+ {
50
+ char src [PATH_MAX ];
51
+ char dst [PATH_MAX ];
52
+ mode_t mode ;
53
+ char * mnt ;
54
+
55
+ if (path_join (err , src , root , dir ) < 0 )
56
+ return (NULL );
57
+ if (path_resolve_full (err , dst , cnt -> cfg .rootfs , dir ) < 0 )
58
+ return (NULL );
59
+ if (file_mode (err , src , & mode ) < 0 )
60
+ goto fail ;
61
+ if (file_create (err , dst , NULL , cnt -> uid , cnt -> gid , mode ) < 0 )
62
+ goto fail ;
63
+
64
+ log_infof ("mounting %s at %s" , src , dst );
65
+ if (xmount (err , src , dst , NULL , MS_BIND , NULL ) < 0 )
66
+ goto fail ;
67
+ if (xmount (err , NULL , dst , NULL , MS_BIND |MS_REMOUNT | MS_NOSUID |MS_NOEXEC , NULL ) < 0 )
68
+ goto fail ;
69
+ if ((mnt = xstrdup (err , dst )) == NULL )
70
+ goto fail ;
71
+ return (mnt );
72
+
73
+ fail :
74
+ unmount (mnt );
75
+ return (NULL );
76
+ }
41
77
42
78
static char * *
43
79
mount_files (struct error * err , const char * root , const struct nvc_container * cnt , const char * dir , char * paths [], size_t size )
@@ -607,6 +643,94 @@ device_mount_native(struct nvc_context *ctx, const struct nvc_container *cnt, co
607
643
return (rv );
608
644
}
609
645
646
+ static int
647
+ cap_device_from_path (struct nvc_context * ctx , const char * cap_path , struct nvc_device_node * node )
648
+ {
649
+ char abs_cap_path [PATH_MAX ];
650
+ char dev_name [PATH_MAX ];
651
+ int major , minor ;
652
+ int rv = -1 ;
653
+
654
+ if (path_join (& ctx -> err , abs_cap_path , ctx -> cfg .root , cap_path ) < 0 )
655
+ goto fail ;
656
+
657
+ if (nvidia_cap_get_device_file_attrs (abs_cap_path , & major , & minor , dev_name ) == 0 ) {
658
+ error_set (& ctx -> err , "unable to get cap device attributes: %s" , cap_path );
659
+ goto fail ;
660
+ }
661
+
662
+ if ((node -> path = xstrdup (& ctx -> err , dev_name )) == NULL )
663
+ goto fail ;
664
+ node -> id = makedev ((unsigned int )major , (unsigned int )minor );
665
+
666
+ rv = 0 ;
667
+
668
+ fail :
669
+ return (rv );
670
+ }
671
+
672
+ static int
673
+ cap_device_mount (struct nvc_context * ctx , const struct nvc_container * cnt , const char * cap_path )
674
+ {
675
+ char * dev_mnt = NULL ;
676
+ struct nvc_device_node node = {0 };
677
+ int rv = -1 ;
678
+
679
+ if (cap_device_from_path (ctx , cap_path , & node ) < 0 )
680
+ goto fail ;
681
+
682
+ if (!(cnt -> flags & OPT_NO_DEVBIND )) {
683
+ if ((dev_mnt = mount_device (& ctx -> err , ctx -> cfg .root , cnt , & node )) == NULL )
684
+ goto fail ;
685
+ }
686
+ if (!(cnt -> flags & OPT_NO_CGROUPS ))
687
+ if (setup_cgroup (& ctx -> err , cnt -> dev_cg , node .id ) < 0 )
688
+ goto fail ;
689
+
690
+ rv = 0 ;
691
+
692
+ fail :
693
+ if (rv < 0 ) {
694
+ unmount (dev_mnt );
695
+ }
696
+
697
+ free (node .path );
698
+ free (dev_mnt );
699
+
700
+ return (rv );
701
+ }
702
+
703
+ static int
704
+ setup_mig_minor_cgroups (struct error * err , const struct nvc_container * cnt , int mig_major , const struct nvc_device_node * node )
705
+ {
706
+ unsigned int gpu_minor = 0 ;
707
+ unsigned int mig_minor = 0 ;
708
+ char line [PATH_MAX ];
709
+ char dummy [PATH_MAX ];
710
+ FILE * fp ;
711
+ int rv = -1 ;
712
+
713
+ if ((fp = fopen (NV_CAPS_MIG_MINORS_PATH , "r" )) == NULL ) {
714
+ error_set (err , "unable to open file for reading: %s" , NV_CAPS_MIG_MINORS_PATH );
715
+ goto fail ;
716
+ }
717
+
718
+ line [PATH_MAX - 1 ] = '\0' ;
719
+ while (fgets (line , PATH_MAX - 1 , fp )) {
720
+ if (sscanf (line , "gpu%u%s %u" , & gpu_minor , dummy , & mig_minor ) != 3 )
721
+ continue ;
722
+ if (gpu_minor != minor (node -> id ))
723
+ continue ;
724
+ if (setup_cgroup (err , cnt -> dev_cg , makedev ((unsigned int )mig_major , mig_minor )) < 0 )
725
+ goto fail ;
726
+ }
727
+
728
+ rv = 0 ;
729
+
730
+ fail :
731
+ fclose (fp );
732
+ return (rv );
733
+ }
610
734
611
735
int
612
736
nvc_driver_mount (struct nvc_context * ctx , const struct nvc_container * cnt , const struct nvc_driver_info * info )
@@ -776,6 +900,13 @@ nvc_mig_device_access_caps_mount(struct nvc_context *ctx, const struct nvc_conta
776
900
if ((proc_mnt_gi = mount_procfs_mig (& ctx -> err , ctx -> cfg .root , cnt , access )) == NULL )
777
901
goto fail ;
778
902
903
+ // Check if NV_CAPS_MODULE_NAME exists as a major device,
904
+ // and if so, mount in the /dev based capability as a device.
905
+ if (nvidia_get_chardev_major (NV_CAPS_MODULE_NAME ) != -1 ) {
906
+ if (cap_device_mount (ctx , cnt , access ) < 0 )
907
+ goto fail ;
908
+ }
909
+
779
910
// Construct the path to the 'access' file in '/proc' for the Compute Instance.
780
911
if (path_join (& ctx -> err , access , dev -> ci_caps_path , NV_MIG_ACCESS_FILE ) < 0 )
781
912
goto fail ;
@@ -784,6 +915,13 @@ nvc_mig_device_access_caps_mount(struct nvc_context *ctx, const struct nvc_conta
784
915
if ((proc_mnt_ci = mount_procfs_mig (& ctx -> err , ctx -> cfg .root , cnt , access )) == NULL )
785
916
goto fail ;
786
917
918
+ // Check if NV_CAPS_MODULE_NAME exists as a major device,
919
+ // and if so, mount in the /dev based capability as a device.
920
+ if (nvidia_get_chardev_major (NV_CAPS_MODULE_NAME ) != -1 ) {
921
+ if (cap_device_mount (ctx , cnt , access ) < 0 )
922
+ goto fail ;
923
+ }
924
+
787
925
// Set the return value to indicate success.
788
926
rv = 0 ;
789
927
@@ -811,7 +949,9 @@ nvc_mig_config_global_caps_mount(struct nvc_context *ctx, const struct nvc_conta
811
949
{
812
950
// Initialize local variables.
813
951
char config [PATH_MAX ];
952
+ char * dev_mnt = NULL ;
814
953
char * proc_mnt = NULL ;
954
+ struct nvc_device_node node = {0 };
815
955
int rv = -1 ;
816
956
817
957
// Validate incoming arguments.
@@ -832,6 +972,20 @@ nvc_mig_config_global_caps_mount(struct nvc_context *ctx, const struct nvc_conta
832
972
if ((proc_mnt = mount_procfs_mig (& ctx -> err , ctx -> cfg .root , cnt , config )) == NULL )
833
973
goto fail ;
834
974
975
+ // Check if NV_CAPS_MODULE_NAME exists as a major device,
976
+ // and if so, mount in the /dev based capability as a device.
977
+ if (nvidia_get_chardev_major (NV_CAPS_MODULE_NAME ) != -1 ) {
978
+ if ((dev_mnt = mount_directory (& ctx -> err , ctx -> cfg .root , cnt , NV_CAPS_DEVICE_DIR )) == NULL )
979
+ goto fail ;
980
+
981
+ if (cap_device_from_path (ctx , config , & node ) < 0 )
982
+ goto fail ;
983
+
984
+ if (!(cnt -> flags & OPT_NO_CGROUPS ))
985
+ if (setup_cgroup (& ctx -> err , cnt -> dev_cg , node .id ) < 0 )
986
+ goto fail ;
987
+ }
988
+
835
989
// Set the return value to indicate success.
836
990
rv = 0 ;
837
991
@@ -848,6 +1002,7 @@ nvc_mig_config_global_caps_mount(struct nvc_context *ctx, const struct nvc_conta
848
1002
849
1003
// In all cases, free the string associated with the mounted 'access'
850
1004
// file and return.
1005
+ free (dev_mnt );
851
1006
free (proc_mnt );
852
1007
return (rv );
853
1008
}
@@ -857,7 +1012,9 @@ nvc_mig_monitor_global_caps_mount(struct nvc_context *ctx, const struct nvc_cont
857
1012
{
858
1013
// Initialize local variables.
859
1014
char monitor [PATH_MAX ];
1015
+ char * dev_mnt = NULL ;
860
1016
char * proc_mnt = NULL ;
1017
+ struct nvc_device_node node = {0 };
861
1018
int rv = -1 ;
862
1019
863
1020
// Validate incoming arguments.
@@ -878,6 +1035,20 @@ nvc_mig_monitor_global_caps_mount(struct nvc_context *ctx, const struct nvc_cont
878
1035
if ((proc_mnt = mount_procfs_mig (& ctx -> err , ctx -> cfg .root , cnt , monitor )) == NULL )
879
1036
goto fail ;
880
1037
1038
+ // Check if NV_CAPS_MODULE_NAME exists as a major device,
1039
+ // and if so, mount in the /dev based capability as a device.
1040
+ if (nvidia_get_chardev_major (NV_CAPS_MODULE_NAME ) != -1 ) {
1041
+ if ((dev_mnt = mount_directory (& ctx -> err , ctx -> cfg .root , cnt , NV_CAPS_DEVICE_DIR )) == NULL )
1042
+ goto fail ;
1043
+
1044
+ if (cap_device_from_path (ctx , monitor , & node ) < 0 )
1045
+ goto fail ;
1046
+
1047
+ if (!(cnt -> flags & OPT_NO_CGROUPS ))
1048
+ if (setup_cgroup (& ctx -> err , cnt -> dev_cg , node .id ) < 0 )
1049
+ goto fail ;
1050
+ }
1051
+
881
1052
// Set the return value to indicate success.
882
1053
rv = 0 ;
883
1054
@@ -894,6 +1065,7 @@ nvc_mig_monitor_global_caps_mount(struct nvc_context *ctx, const struct nvc_cont
894
1065
895
1066
// In all cases, free the string associated with the mounted 'access'
896
1067
// file and return.
1068
+ free (dev_mnt );
897
1069
free (proc_mnt );
898
1070
return (rv );
899
1071
}
@@ -903,6 +1075,7 @@ nvc_device_mig_caps_mount(struct nvc_context *ctx, const struct nvc_container *c
903
1075
{
904
1076
// Initialize local variables.
905
1077
char * proc_mnt = NULL ;
1078
+ int nvcaps_major = -1 ;
906
1079
int rv = -1 ;
907
1080
908
1081
// Validate incoming arguments.
@@ -919,6 +1092,13 @@ nvc_device_mig_caps_mount(struct nvc_context *ctx, const struct nvc_container *c
919
1092
if ((proc_mnt = mount_procfs_mig (& ctx -> err , ctx -> cfg .root , cnt , dev -> mig_caps_path )) == NULL )
920
1093
goto fail ;
921
1094
1095
+ // Check if NV_CAPS_MODULE_NAME exists as a major device, and if so,
1096
+ // mount in the appropriate /dev based capabilities as devices.
1097
+ if ((nvcaps_major = nvidia_get_chardev_major (NV_CAPS_MODULE_NAME )) != -1 ) {
1098
+ if (setup_mig_minor_cgroups (& ctx -> err , cnt , nvcaps_major , & dev -> node ) < 0 )
1099
+ goto fail ;
1100
+ }
1101
+
922
1102
// Set the return value to indicate success.
923
1103
rv = 0 ;
924
1104
0 commit comments