Skip to content

Commit 554c4e9

Browse files
committed
Merge branch 'upstream-add-dev-node-support' into 'master'
Add support for /dev based capabilities See merge request nvidia/container-toolkit/libnvidia-container!35
2 parents ad74a14 + f94be45 commit 554c4e9

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed

src/nvc_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,15 @@
3131
#define NV_UVM_DEVICE_PATH _PATH_DEV "nvidia-uvm"
3232
#define NV_UVM_TOOLS_DEVICE_PATH _PATH_DEV "nvidia-uvm-tools"
3333
#define NV_MODESET_DEVICE_PATH _PATH_DEV "nvidia-modeset"
34+
#define NV_CAPS_DEVICE_DIR _PATH_DEV "nvidia-caps"
35+
#define NV_CAPS_DEVICE_PATH NV_CAPS_DEVICE_DIR "/nvidia-cap%d"
3436
#define NV_PERSISTENCED_SOCKET _PATH_VARRUN "nvidia-persistenced/socket"
3537
#define NV_MPS_PIPE_DIR _PATH_TMP "nvidia-mps"
3638
#define NV_PROC_DRIVER "/proc/driver/nvidia"
39+
#define NV_CAPS_PROC_DRIVER "/proc/driver/nvidia-caps"
3740
#define NV_UVM_PROC_DRIVER "/proc/driver/nvidia-uvm"
3841
#define NV_APP_PROFILE_DIR "/etc/nvidia/nvidia-application-profiles-rc.d"
42+
#define NV_CAPS_MIG_MINORS_PATH NV_CAPS_PROC_DRIVER "/mig-minors"
3943

4044
#define NV_PROC_DRIVER_CAPS NV_PROC_DRIVER "/capabilities"
4145
#define NV_MIG_CAPS_PATH NV_PROC_DRIVER_CAPS "/mig"

src/nvc_mount.c

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <libgen.h>
1111
#undef basename /* Use the GNU version of basename. */
1212
#include <limits.h>
13+
#include <nvidia-modprobe-utils.h>
1314
#include <stdio.h>
1415
#include <string.h>
1516
#include <sched.h>
@@ -24,6 +25,7 @@
2425

2526
static char **mount_files(struct error *, const char *, const struct nvc_container *, const char *, char *[], size_t);
2627
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 *);
2729
static char *mount_device(struct error *, const char *, const struct nvc_container *, const struct nvc_device_node *);
2830
static char *mount_ipc(struct error *, const char *, const struct nvc_container *, const char *);
2931
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
3840
static void filter_libraries(const struct nvc_driver_info *, char * [], size_t *);
3941
static int device_mount_dxcore(struct nvc_context *, const struct nvc_container *);
4042
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+
}
4177

4278
static char **
4379
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
607643
return (rv);
608644
}
609645

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+
}
610734

611735
int
612736
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
776900
if ((proc_mnt_gi = mount_procfs_mig(&ctx->err, ctx->cfg.root, cnt, access)) == NULL)
777901
goto fail;
778902

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+
779910
// Construct the path to the 'access' file in '/proc' for the Compute Instance.
780911
if (path_join(&ctx->err, access, dev->ci_caps_path, NV_MIG_ACCESS_FILE) < 0)
781912
goto fail;
@@ -784,6 +915,13 @@ nvc_mig_device_access_caps_mount(struct nvc_context *ctx, const struct nvc_conta
784915
if ((proc_mnt_ci = mount_procfs_mig(&ctx->err, ctx->cfg.root, cnt, access)) == NULL)
785916
goto fail;
786917

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+
787925
// Set the return value to indicate success.
788926
rv = 0;
789927

@@ -811,7 +949,9 @@ nvc_mig_config_global_caps_mount(struct nvc_context *ctx, const struct nvc_conta
811949
{
812950
// Initialize local variables.
813951
char config[PATH_MAX];
952+
char *dev_mnt = NULL;
814953
char *proc_mnt = NULL;
954+
struct nvc_device_node node = {0};
815955
int rv = -1;
816956

817957
// Validate incoming arguments.
@@ -832,6 +972,20 @@ nvc_mig_config_global_caps_mount(struct nvc_context *ctx, const struct nvc_conta
832972
if ((proc_mnt = mount_procfs_mig(&ctx->err, ctx->cfg.root, cnt, config)) == NULL)
833973
goto fail;
834974

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+
835989
// Set the return value to indicate success.
836990
rv = 0;
837991

@@ -848,6 +1002,7 @@ nvc_mig_config_global_caps_mount(struct nvc_context *ctx, const struct nvc_conta
8481002

8491003
// In all cases, free the string associated with the mounted 'access'
8501004
// file and return.
1005+
free(dev_mnt);
8511006
free(proc_mnt);
8521007
return (rv);
8531008
}
@@ -857,7 +1012,9 @@ nvc_mig_monitor_global_caps_mount(struct nvc_context *ctx, const struct nvc_cont
8571012
{
8581013
// Initialize local variables.
8591014
char monitor[PATH_MAX];
1015+
char *dev_mnt = NULL;
8601016
char *proc_mnt = NULL;
1017+
struct nvc_device_node node = {0};
8611018
int rv = -1;
8621019

8631020
// Validate incoming arguments.
@@ -878,6 +1035,20 @@ nvc_mig_monitor_global_caps_mount(struct nvc_context *ctx, const struct nvc_cont
8781035
if ((proc_mnt = mount_procfs_mig(&ctx->err, ctx->cfg.root, cnt, monitor)) == NULL)
8791036
goto fail;
8801037

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+
8811052
// Set the return value to indicate success.
8821053
rv = 0;
8831054

@@ -894,6 +1065,7 @@ nvc_mig_monitor_global_caps_mount(struct nvc_context *ctx, const struct nvc_cont
8941065

8951066
// In all cases, free the string associated with the mounted 'access'
8961067
// file and return.
1068+
free(dev_mnt);
8971069
free(proc_mnt);
8981070
return (rv);
8991071
}
@@ -903,6 +1075,7 @@ nvc_device_mig_caps_mount(struct nvc_context *ctx, const struct nvc_container *c
9031075
{
9041076
// Initialize local variables.
9051077
char *proc_mnt = NULL;
1078+
int nvcaps_major = -1;
9061079
int rv = -1;
9071080

9081081
// Validate incoming arguments.
@@ -919,6 +1092,13 @@ nvc_device_mig_caps_mount(struct nvc_context *ctx, const struct nvc_container *c
9191092
if ((proc_mnt = mount_procfs_mig(&ctx->err, ctx->cfg.root, cnt, dev->mig_caps_path)) == NULL)
9201093
goto fail;
9211094

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+
9221102
// Set the return value to indicate success.
9231103
rv = 0;
9241104

0 commit comments

Comments
 (0)