Overlay/sys-libs/libnvidia-container/files/libnvidia-container-1.3.0-f...

568 lines
15 KiB
Diff

--- a/src/nvidia-modprobe-utils.c 2020-09-18 18:11:57.042187266 +0800
+++ b/src/nvidia-modprobe-utils.c 2020-09-18 18:25:49.318472815 +0800
@@ -1,3 +1,29 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * This file provides utility functions on Linux for loading the
+ * NVIDIA kernel module and creating NVIDIA device files.
+ */
#if defined(NV_LINUX)
@@ -27,9 +53,6 @@
#define NV_NVIDIA_MODULE_NAME "nvidia"
#define NV_PROC_REGISTRY_PATH "/proc/driver/nvidia/params"
-#define NV_NMODULE_NVIDIA_MODULE_NAME "nvidia%d"
-#define NV_NMODULE_PROC_REGISTRY_PATH "/proc/driver/nvidia/%d/params"
-
#define NV_UVM_MODULE_NAME "nvidia-uvm"
#define NV_UVM_DEVICE_NAME "/dev/nvidia-uvm"
#define NV_UVM_TOOLS_DEVICE_NAME "/dev/nvidia-uvm-tools"
@@ -41,12 +64,16 @@
#define NV_NVLINK_MODULE_NAME "nvidia-nvlink"
#define NV_NVLINK_PROC_PERM_PATH "/proc/driver/nvidia-nvlink/permissions"
+#define NV_NVSWITCH_MODULE_NAME "nvidia-nvswitch"
+#define NV_NVSWITCH_PROC_PERM_PATH "/proc/driver/nvidia-nvswitch/permissions"
+
#define NV_DEVICE_FILE_MODE_MASK (S_IRWXU|S_IRWXG|S_IRWXO)
#define NV_DEVICE_FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
#define NV_DEVICE_FILE_UID 0
#define NV_DEVICE_FILE_GID 0
-#define NV_MAKE_DEVICE(x,y) ((dev_t)((x) << 8 | (y)))
+#define NV_MAKE_DEVICE(major, minor) \
+ ((dev_t)((minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12)))
#define NV_MAJOR_DEVICE_NUMBER 195
@@ -55,84 +82,6 @@
#define NV_MIN(a, b) (((a) < (b)) ? (a) : (b))
/*
- * Construct the nvidia kernel module name based on the input
- * module instance provided. If an error occurs, the null
- * terminator will be written to nv_module_name[0].
- */
-static __inline__ void assign_nvidia_kernel_module_name
-(
- char nv_module_name[NV_MAX_MODULE_NAME_SIZE],
- int module_instance
-)
-{
- int ret;
-
- if (is_multi_module(module_instance))
- {
- ret = snprintf(nv_module_name, NV_MAX_MODULE_NAME_SIZE,
- NV_NMODULE_NVIDIA_MODULE_NAME, module_instance);
- }
- else
- {
- ret = snprintf(nv_module_name, NV_MAX_MODULE_NAME_SIZE,
- NV_NVIDIA_MODULE_NAME);
- }
-
- if (ret <= 0)
- {
- goto fail;
- }
-
- nv_module_name[NV_MAX_MODULE_NAME_SIZE - 1] = '\0';
-
- return;
-
-fail:
-
- nv_module_name[0] = '\0';
-}
-
-
-/*
- * Construct the proc registry path name based on the input
- * module instance provided. If an error occurs, the null
- * terminator will be written to proc_path[0].
- */
-static __inline__ void assign_proc_registry_path
-(
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE],
- int module_instance
-)
-{
- int ret;
-
- if (is_multi_module(module_instance))
- {
- ret = snprintf(proc_path, NV_MAX_PROC_REGISTRY_PATH_SIZE,
- NV_NMODULE_PROC_REGISTRY_PATH, module_instance);
- }
- else
- {
- ret = snprintf(proc_path, NV_MAX_PROC_REGISTRY_PATH_SIZE,
- NV_PROC_REGISTRY_PATH);
- }
-
- if (ret <= 0)
- {
- goto fail;
- }
-
- proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE - 1] = '\0';
-
- return;
-
-fail:
-
- proc_path[0] = '\0';
-}
-
-
-/*
* Just like strcmp(3), except that differences between '-' and '_' are
* ignored. This is useful for comparing module names, where '-' and '_'
* are supposed to be treated interchangeably.
@@ -370,18 +319,20 @@
return 0;
default:
- if (waitpid(pid, &status, 0) < 0)
- {
- return 0;
- }
- if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
- {
- return 1;
- }
- else
- {
- return 0;
- }
+ /*
+ * waitpid(2) is not always guaranteed to return success even if
+ * the child terminated normally. For example, if the process
+ * explicitly configured the handling of the SIGCHLD signal
+ * to SIG_IGN, then waitpid(2) will instead block until all
+ * children terminate and return the error ECHILD, regardless
+ * of the child's exit codes.
+ *
+ * Hence, ignore waitpid(2) error codes and instead check
+ * whether the desired kernel module is loaded.
+ */
+ waitpid(pid, NULL, 0);
+
+ return is_kernel_module_loaded(module_name);
}
return 1;
@@ -391,13 +342,9 @@
/*
* Attempt to load an NVIDIA kernel module
*/
-int nvidia_modprobe(const int print_errors, int module_instance)
+int nvidia_modprobe(const int print_errors)
{
- char nv_module_name[NV_MAX_MODULE_NAME_SIZE];
-
- assign_nvidia_kernel_module_name(nv_module_name, module_instance);
-
- return modprobe_helper(print_errors, nv_module_name);
+ return modprobe_helper(print_errors, NV_NVIDIA_MODULE_NAME);
}
@@ -447,7 +394,8 @@
{
*mode = value;
}
- if (strcmp(name, "ModifyDeviceFiles") == 0)
+ if ((strcmp(name, "ModifyDeviceFiles") == 0) ||
+ (strcmp(name, "DeviceFileModify") == 0))
{
*modify = value;
}
@@ -456,7 +404,7 @@
fclose(fp);
}
-/*
+/*
* A helper to query device file states.
*/
static int get_file_state_helper(
@@ -494,24 +442,22 @@
return state;
}
-int nvidia_get_file_state(int minor, int module_instance)
+int nvidia_get_file_state(int minor)
{
char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
mode_t mode;
uid_t uid;
gid_t gid;
int modification_allowed;
int state = 0;
- assign_device_file_name(path, minor, module_instance);
- assign_proc_registry_path(proc_path, module_instance);
+ assign_device_file_name(path, minor);
init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
- proc_path);
+ NV_PROC_REGISTRY_PATH);
state = get_file_state_helper(path, NV_MAJOR_DEVICE_NUMBER, minor,
- proc_path, uid, gid, mode);
+ NV_PROC_REGISTRY_PATH, uid, gid, mode);
return state;
}
@@ -522,8 +468,8 @@
* permissions. Returns 1 if the file is successfully created; returns 0
* if the file could not be created.
*/
-int mknod_helper(int major, int minor, const char *path,
- const char *proc_path)
+static int mknod_helper(int major, int minor, const char *path,
+ const char *proc_path)
{
dev_t dev = NV_MAKE_DEVICE(major, minor);
mode_t mode;
@@ -616,15 +562,13 @@
* Attempt to create a device file with the specified minor number for
* the specified NVIDIA module instance.
*/
-int nvidia_mknod(int minor, int module_instance)
+int nvidia_mknod(int minor)
{
char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
- assign_device_file_name(path, minor, module_instance);
- assign_proc_registry_path(proc_path, module_instance);
+ assign_device_file_name(path, minor);
- return mknod_helper(NV_MAJOR_DEVICE_NUMBER, minor, path, proc_path);
+ return mknod_helper(NV_MAJOR_DEVICE_NUMBER, minor, path, NV_PROC_REGISTRY_PATH);
}
@@ -633,7 +577,7 @@
* device with the specified name. Returns the major number on success,
* or -1 on failure.
*/
-int get_chardev_major(const char *name)
+int nvidia_get_chardev_major(const char *name)
{
int ret = -1;
char line[NV_MAX_LINE_LENGTH];
@@ -702,13 +646,86 @@
return ret;
}
+int nvidia_nvlink_get_file_state(void)
+{
+ char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+ int modification_allowed;
+ int ret;
+ int major = nvidia_get_chardev_major(NV_NVLINK_MODULE_NAME);
+
+ if (major < 0)
+ {
+ path[0] = '\0';
+ goto done;
+ }
+
+ ret = snprintf(path, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
+ NV_NVLINK_DEVICE_NAME);
+
+ if (ret < 0 || ret >= NV_MAX_CHARACTER_DEVICE_FILE_STRLEN)
+ {
+ path[0] = '\0';
+ }
+
+done:
+
+ init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
+ NV_NVLINK_PROC_PERM_PATH);
+
+ return get_file_state_helper(path, major, 0,
+ NV_NVLINK_PROC_PERM_PATH, uid, gid, mode);
+}
+
+int nvidia_nvswitch_get_file_state(int minor)
+{
+ char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+ int modification_allowed;
+ int ret;
+ int major = nvidia_get_chardev_major(NV_NVSWITCH_MODULE_NAME);
+
+ if ((major < 0) || (minor < 0) || (minor > NV_NVSWITCH_CTL_MINOR))
+ {
+ path[0] = '\0';
+ goto done;
+ }
+
+ if (minor == NV_NVSWITCH_CTL_MINOR)
+ {
+ ret = snprintf(path, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
+ NV_NVSWITCH_CTL_NAME);
+ }
+ else
+ {
+ ret = snprintf(path, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
+ NV_NVSWITCH_DEVICE_NAME, minor);
+ }
+
+ if (ret < 0 || ret >= NV_MAX_CHARACTER_DEVICE_FILE_STRLEN)
+ {
+ path[0] = '\0';
+ }
+
+done:
+
+ init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
+ NV_NVSWITCH_PROC_PERM_PATH);
+
+ return get_file_state_helper(path, major, minor,
+ NV_NVSWITCH_PROC_PERM_PATH, uid, gid, mode);
+}
/*
* Attempt to create the NVIDIA Unified Memory device file
*/
int nvidia_uvm_mknod(int base_minor)
{
- int major = get_chardev_major(NV_UVM_MODULE_NAME);
+ int major = nvidia_get_chardev_major(NV_UVM_MODULE_NAME);
if (major < 0)
{
@@ -743,13 +760,9 @@
*/
int nvidia_modeset_mknod(void)
{
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
-
- assign_proc_registry_path(proc_path, NV_MODULE_INSTANCE_NONE);
-
return mknod_helper(NV_MAJOR_DEVICE_NUMBER,
NV_MODESET_MINOR_DEVICE_NUM,
- NV_MODESET_DEVICE_NAME, proc_path);
+ NV_MODESET_DEVICE_NAME, NV_PROC_REGISTRY_PATH);
}
/*
@@ -757,7 +770,7 @@
*/
int nvidia_nvlink_mknod(void)
{
- int major = get_chardev_major(NV_NVLINK_MODULE_NAME);
+ int major = nvidia_get_chardev_major(NV_NVLINK_MODULE_NAME);
if (major < 0)
{
@@ -770,25 +783,164 @@
NV_NVLINK_PROC_PERM_PATH);
}
+/*
+ * Attempt to create the NVIDIA NVSwitch driver device files.
+ */
+int nvidia_nvswitch_mknod(int minor)
+{
+ int major = 0;
+ char name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
+ int ret;
+
+ major = nvidia_get_chardev_major(NV_NVSWITCH_MODULE_NAME);
+
+ if (major < 0)
+ {
+ return 0;
+ }
+
+ if (minor == NV_NVSWITCH_CTL_MINOR)
+ {
+ ret = snprintf(name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
+ NV_NVSWITCH_CTL_NAME);
+ }
+ else
+ {
+ ret = snprintf(name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
+ NV_NVSWITCH_DEVICE_NAME, minor);
+ }
+
+ if (ret < 0 || ret >= NV_MAX_CHARACTER_DEVICE_FILE_STRLEN)
+ {
+ return 0;
+ }
+
+ return mknod_helper(major, minor, name, NV_NVSWITCH_PROC_PERM_PATH);
+}
+
int nvidia_vgpu_vfio_mknod(int minor_num)
{
- int major = get_chardev_major(NV_VGPU_VFIO_MODULE_NAME);
+ int major = nvidia_get_chardev_major(NV_VGPU_VFIO_MODULE_NAME);
char vgpu_dev_name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
+ int ret;
if (major < 0)
{
return 0;
}
- assign_proc_registry_path(proc_path, NV_MODULE_INSTANCE_NONE);
-
- snprintf(vgpu_dev_name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
- NV_VGPU_VFIO_DEVICE_NAME, minor_num);
+ ret = snprintf(vgpu_dev_name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
+ NV_VGPU_VFIO_DEVICE_NAME, minor_num);
+ if (ret <= 0)
+ {
+ return 0;
+ }
vgpu_dev_name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN - 1] = '\0';
- return mknod_helper(major, minor_num, vgpu_dev_name, proc_path);
+ return mknod_helper(major, minor_num, vgpu_dev_name, NV_PROC_REGISTRY_PATH);
+}
+
+int nvidia_cap_get_device_file_attrs(const char* cap_file_path,
+ int *major,
+ int *minor,
+ char *name)
+{
+ char field[32];
+ FILE *fp;
+ int value;
+ int ret;
+
+ *major = nvidia_get_chardev_major(NV_CAPS_MODULE_NAME);
+
+ if (*major < 0)
+ {
+ return 0;
+ }
+
+ fp = fopen(cap_file_path, "r");
+
+ if (fp == NULL)
+ {
+ return 0;
+ }
+
+ *minor = -1;
+
+ while (fscanf(fp, "%31[^:]: %d\n", field, &value) == 2)
+ {
+ field[31] = '\0';
+ if (strcmp(field, "DeviceFileMinor") == 0)
+ {
+ *minor = value;
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ if (*minor < 0)
+ {
+ return 0;
+ }
+
+ ret = snprintf(name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
+ NV_CAP_DEVICE_NAME, *minor);
+
+ if (ret < 0 || ret >= NV_MAX_CHARACTER_DEVICE_FILE_STRLEN)
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Attempt to create the NVIDIA capability device files.
+ */
+int nvidia_cap_mknod(const char* cap_file_path, int *minor)
+{
+ int major;
+ char name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
+ int ret;
+
+ ret = nvidia_cap_get_device_file_attrs(cap_file_path, &major, minor, name);
+ if (ret == 0)
+ {
+ return 0;
+ }
+
+ ret = mkdir("/dev/"NV_CAPS_MODULE_NAME, 0755);
+ if ((ret != 0) && (errno != EEXIST))
+ {
+ return 0;
+ }
+
+ return mknod_helper(major, *minor, name, cap_file_path);
+}
+
+int nvidia_cap_get_file_state(const char* cap_file_path)
+{
+ char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+ int modification_allowed;
+ int ret;
+ int major;
+ int minor;
+
+ ret = nvidia_cap_get_device_file_attrs(cap_file_path, &major, &minor, path);
+ if (ret == 0)
+ {
+ path[0] = '\0';
+ }
+
+ init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
+ cap_file_path);
+
+ return get_file_state_helper(path, major, minor,
+ cap_file_path, uid, gid, mode);
}
-#endif /* NV_LINUX */
\ No newline at end of file
+#endif /* NV_LINUX */