Add a function to fix issues with Nvidia GPUs

The function is called NVIDIA_HANDLER and is disabled by default.
When enabled, it will automatically download the same Nvidia driver version as installed on the host system and pass it into the container.

This is implemented via fuse-overlayfs, fuse3 is required for this to work.
This commit is contained in:
Kron4ek 2023-05-21 22:01:03 +05:00
parent 9ed24fef16
commit a467da324d
4 changed files with 140 additions and 10 deletions

View file

@ -19,8 +19,8 @@ script_version="1.23"
# Important variables to manually adjust after modification!
# Needed to avoid problems with mounting due to an incorrect offset.
script_size=29108
utils_size=2520686
script_size=33659
utils_size=2564623
# Full path to the script
script_literal="${BASH_SOURCE[0]}"
@ -114,6 +114,12 @@ Environment variables:
isolates X11 server with Xephyr.
The default is 1.
NVIDIA_HANDLER Fixes issues with graphical applications on Nvidia
GPUs with the proprietary driver. Enable this only
if you are using an Nvidia GPU, the proprietary
driver and encountering issues running graphical
applications. Fuse3 is required for this to work.
USE_SYS_UTILS Tells the script to use squashfuse/dwarfs and bwrap
installed on the system instead of the builtin ones.
@ -166,6 +172,9 @@ fi
mount_point="${working_dir}"/mnt
export overlayfs_dir="${HOME}"/.local/share/Conty/overlayfs
export nvidia_drivers_dir="${HOME}"/.local/share/Conty/nvidia
# Offset where the image is stored
offset=$((script_size+utils_size))
@ -284,6 +293,90 @@ gui () {
fi
}
mount_overlayfs () {
if [ "${script_md5}" != "$(cat "${overlayfs_dir}"/current-image-version 2>/dev/null)" ]; then
rm -rf "${overlayfs_dir}"/up "${overlayfs_dir}"/work \
"${nvidia_drivers_dir}"/current-nvidia-version
fi
mkdir -p "${overlayfs_dir}"/up
mkdir -p "${overlayfs_dir}"/work
mkdir -p "${overlayfs_dir}"/merged
echo "${script_md5}" > "${overlayfs_dir}"/current-image-version
if [ ! "$(ls "${overlayfs_dir}"/merged 2>/dev/null)" ]; then
if command -v "${fuse_overlayfs}" 1>/dev/null; then
if command -v fusermount3 1>/dev/null; then
"${fuse_overlayfs}" -o squash_to_uid="$(id -u)" -o squash_to_gid="$(id -g)" -o lowerdir="${mount_point}",upperdir="${overlayfs_dir}"/up,workdir="${overlayfs_dir}"/work "${overlayfs_dir}"/merged
else
echo "Fuse3 is required for fuse-overlayfs"
fi
else
echo "fuse-overlayfs not found"
fi
fi
}
nvidia_driver_handler () {
if lsmod | grep nvidia 1>/dev/null || nvidia-smi 1>/dev/null; then
if [ "$(ls /tmp/hostlibs/x86_64-linux-gnu/libGLX_nvidia.so.* 2>/dev/null)" ]; then
nvidia_driver_version="$(basename /tmp/hostlibs/x86_64-linux-gnu/libGLX_nvidia.so.*.* | tail -c +18)"
elif [ "$(ls /tmp/hostlibs/libGLX_nvidia.so.* 2>/dev/null)" ]; then
nvidia_driver_version="$(basename /tmp/hostlibs/libGLX_nvidia.so.*.* | tail -c +18)"
elif nvidia-smi 1>/dev/null; then
nvidia_driver_version="$(nvidia-smi --query-gpu=driver_version --format=csv,noheader)"
elif modinfo nvidia &>/dev/null; then
nvidia_driver_version="$(modinfo -F version nvidia 2>/dev/null)"
fi
else
echo "Seems like your system has no Nvidia driver loaded"
exit 1
fi
if [ "$(cat "${nvidia_drivers_dir}"/current-nvidia-version 2>/dev/null)" = "${nvidia_driver_version}" ]; then
exit
fi
if [ -z "${nvidia_driver_version}" ]; then
echo "Unable to determine the Nvidia driver version"
exit 1
fi
OLD_PWD="${PWD}"
mkdir -p "${nvidia_drivers_dir}"
cd "${nvidia_drivers_dir}"
echo "Found Nvidia driver ${nvidia_driver_version}"
echo "Downloading the Nvidia driver ${nvidia_driver_version}, please wait..."
# Try to download the driver from the default Nvidia URL
driver_url="https://us.download.nvidia.com/XFree86/Linux-x86_64/${nvidia_driver_version}/NVIDIA-Linux-x86_64-${nvidia_driver_version}.run"
curl -#Lo nvidia.run "${driver_url}"
# If the previous download failed, get the URL from FlatHub repo
if [ ! -s nvidia.run ]; then
rm -f nvidia.run
driver_url="https:$(curl -#Lo - "https://raw.githubusercontent.com/flathub/org.freedesktop.Platform.GL.nvidia/master/data/nvidia-${nvidia_driver_version}-i386.data" | cut -d ':' -f 6)"
curl -#Lo nvidia.run "${driver_url}"
fi
if [ -s nvidia.run ]; then
echo "Installing the Nvidia driver, please wait..."
chmod +x nvidia.run
./nvidia.run --target nvidia-driver -x &>/dev/null
cd nvidia-driver || exit 1
fakeroot ./nvidia-installer --silent --no-x-check --no-kernel-module &>/dev/null
cd "${nvidia_drivers_dir}"
echo "${nvidia_driver_version}" > current-nvidia-version
rm -rf nvidia.run nvidia-driver
echo "The driver has been installed"
fi
cd "${OLD_PWD}"
}
# Check if FUSE is installed
if ! command -v fusermount3 1>/dev/null && ! command -v fusermount 1>/dev/null; then
echo "Please install fuse2 or fuse3 and run the script again."
@ -357,6 +450,7 @@ if [ "${USE_SYS_UTILS}" != 1 ]; then
fi
bwrap="${working_dir}"/utils/bwrap
fuse_overlayfs="${working_dir}"/utils/fuse-overlayfs
if [ ! -f "${mount_tool}" ] || [ ! -f "${bwrap}" ]; then
tail -c +$((script_size+1)) "${script}" | head -c "${utils_size}" | tar -C "${working_dir}" -zxf -
@ -369,9 +463,10 @@ if [ "${USE_SYS_UTILS}" != 1 ]; then
exit 1
fi
chmod +x "${mount_tool}"
chmod +x "${bwrap}"
chmod +x "${mount_tool}" 2>/dev/null
chmod +x "${bwrap}" 2>/dev/null
chmod +x "${extraction_tool}" 2>/dev/null
chmod +x "${fuse_overlayfs}" 2>/dev/null
fi
else
if ! command -v bwrap 1>/dev/null; then
@ -382,6 +477,7 @@ else
fi
bwrap=bwrap
fuse_overlayfs=fuse-overlayfs
if [ "${dwarfs_image}" = 1 ]; then
if ! command -v dwarfs 1>/dev/null && ! command -v dwarfs2 1>/dev/null; then
@ -774,10 +870,16 @@ run_bwrap () {
mount_opt=(--bind-try /opt /opt)
fi
if [ "${NVIDIA_HANDLER}" = 1 ] && [ "$(ls "${overlayfs_dir}"/merged 2>/dev/null)" ]; then
newroot_path="${overlayfs_dir}"/merged
else
newroot_path="${mount_point}"
fi
show_msg
launch_wrapper "${bwrap}" \
--ro-bind "${mount_point}" / \
--bind "${newroot_path}" / \
--dev-bind /dev /dev \
--ro-bind /sys /sys \
--bind-try /tmp /tmp \
@ -809,6 +911,11 @@ run_bwrap () {
trap_exit () {
rm -f "${working_dir}"/running_"${script_id}"
if [ -d "${overlayfs_dir}"/merged ]; then
fusermount"${fuse_version}" -uz "${overlayfs_dir}"/merged 2>/dev/null || \
umount --lazy "${overlayfs_dir}"/merged 2>/dev/null
fi
if [ ! "$(ls "${working_dir}"/running_* 2>/dev/null)" ]; then
fusermount"${fuse_version}" -uz "${mount_point}" 2>/dev/null || \
umount --lazy "${mount_point}" 2>/dev/null
@ -926,6 +1033,19 @@ if [ "$(ls "${mount_point}" 2>/dev/null)" ] || \
exit
fi
if [ "${NVIDIA_HANDLER}" = 1 ]; then
show_msg "Nvidia driver handler is enabled"
mount_overlayfs
mkdir -p "${nvidia_drivers_dir}"
export -f nvidia_driver_handler
run_bwrap --tmpfs /tmp --tmpfs /var --tmpfs /run \
--bind-try /usr/lib /tmp/hostlibs \
--bind-try /usr/lib64 /tmp/hostlibs \
--bind-try "${nvidia_drivers_dir}" "${nvidia_drivers_dir}" \
bash -c nvidia_driver_handler
fi
# If SANDBOX_LEVEL is 3, run Xephyr and openbox before running applications
if [ "${SANDBOX}" = 1 ] && [ -n "${SANDBOX_LEVEL}" ] && [ "${SANDBOX_LEVEL}" -ge 3 ]; then
if [ -f "${mount_point}"/usr/bin/Xephyr ]; then

View file

@ -12,13 +12,14 @@
script_dir="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
# Set to true to compile dwarfs instead of squashfuse
build_dwarfs="true"
build_dwarfs="false"
squashfuse_version="0.1.105"
bwrap_version="0.8.0"
lz4_version="1.9.4"
zstd_version="1.5.5"
squashfs_tools_version="4.6.1"
fuse_overlayfs_version="1.12"
export CC=gcc
export CXX=g++
@ -33,10 +34,12 @@ cd "${script_dir}"/build-utils || exit 1
curl -#Lo lz4.tar.gz https://github.com/lz4/lz4/archive/refs/tags/v${lz4_version}.tar.gz
curl -#Lo zstd.tar.gz https://github.com/facebook/zstd/archive/refs/tags/v${zstd_version}.tar.gz
curl -#Lo bwrap.tar.gz https://github.com/containers/bubblewrap/archive/refs/tags/v${bwrap_version}.tar.gz
curl -#Lo fuse-overlayfs.tar.gz https://github.com/containers/fuse-overlayfs/archive/refs/tags/v${fuse_overlayfs_version}.tar.gz
tar xf lz4.tar.gz
tar xf zstd.tar.gz
tar xf bwrap.tar.gz
tar xf fuse-overlayfs.tar.gz
if [ "${build_dwarfs}" != "true" ]; then
curl -#Lo squashfuse.tar.gz https://github.com/vasi/squashfuse/archive/refs/tags/${squashfuse_version}.tar.gz
@ -51,6 +54,11 @@ cd bubblewrap-"${bwrap_version}" || exit 1
./configure --disable-selinux --disable-man
make -j"$(nproc)" DESTDIR="${script_dir}"/build-utils/bin install
cd ../fuse-overlayfs-"${fuse_overlayfs_version}" || exit 1
./autogen.sh
./configure
make -j"$(nproc)" DESTDIR="${script_dir}"/build-utils/bin install
cd ../lz4-"${lz4_version}" || exit 1
make -j"$(nproc)" DESTDIR="${script_dir}"/build-utils/bin install
@ -76,6 +84,7 @@ mv bin/usr/local/bin/squashfuse utils
mv bin/usr/local/bin/squashfuse_ll utils
mv bin/usr/local/bin/mksquashfs utils
mv bin/usr/local/bin/unsquashfs utils
mv bin/usr/local/bin/fuse-overlayfs utils
mv bin/usr/local/lib/liblz4.so."${lz4_version}" utils/liblz4.so.1
mv bin/usr/local/lib/libzstd.so."${zstd_version}" utils/libzstd.so.1
mv bin/usr/local/lib/libfuseprivate.so.0.0.0 utils/libfuseprivate.so.0
@ -130,6 +139,7 @@ find utils -type f -exec strip --strip-unneeded {} \; 2>/dev/null
cat <<EOF > utils/info
bubblewrap ${bwrap_version}
fuse-overlayfs ${fuse_overlayfs_version}
lz4 ${lz4_version}
zstd ${zstd_version}
EOF

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6637ac7ef4a0e36e90349b5ce701c334abe284f4425024ea67cbf55761f617f3
size 2520686
oid sha256:20b855587b07fa71c8be8e73220495fcee7c9ec290914e982b76fd184fa67094
size 2564623

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5b160ecd08ffb0b4c6340799c882fb3f017524383b323582e6e8bd7e76fbf9cc
size 9387864
oid sha256:ef56bd72810c1c05a6f4cd77e816b2741ab014b421c00eb0337602c5a11d0959
size 9431944