From 0e29b7a0771ee8e59873420cbe23f6d27755df35 Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Wed, 16 Apr 2025 11:42:48 +0100 Subject: [PATCH] lisa._kmod: Add fuse-overlayfs overlay backend FEATURE Add "fuse-overlayfs" backend in addition to the existing "overlayfs". This backend has much better performance than the "copy" backend even if it is itself worse than the native "overlayfs". However, it can come in handy in environments that don't allow user namespaces like some modern distribution (e.g. Ubuntu 24.04 without specific configuration). --- install_base.sh | 10 ++++++++-- lisa/_kmod.py | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/install_base.sh b/install_base.sh index 893689ded..fb1ba0346 100755 --- a/install_base.sh +++ b/install_base.sh @@ -252,7 +252,13 @@ for arg in "${args[@]}"; do handled=1 ;;& - "--install-toolchains" | "--install-all") + "--install-build-env" | "--install-all") + apt_packages+=(fuse-overlayfs) + pacman_packages+=(fuse-overlayfs) + handled=1 + ;;& + + "--install-toolchains" | "--install-build-env" | "--install-all") apt_packages+=(build-essential gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu) # arm-linux-gnueabihf-gcc can be installed from the AUR pacman_packages+=(base-devel aarch64-linux-gnu-gcc flex) @@ -265,7 +271,7 @@ for arg in "${args[@]}"; do handled=1 ;;& - "--install-kernel-build-dependencies" | "--install-all") + "--install-kernel-build-dependencies" | "--install-build-env" | "--install-all") apt_packages+=(build-essential gcc bc bison flex libssl-dev libncurses5-dev libelf-dev) if test_os_release NAME "Ubuntu"; then diff --git a/lisa/_kmod.py b/lisa/_kmod.py index 1fc804680..7253f4112 100644 --- a/lisa/_kmod.py +++ b/lisa/_kmod.py @@ -864,7 +864,7 @@ def _overlay_folders(lowers, backend, upper=None, copy_filter=None): ) @destroyablecontextmanager - def do_mount(dirs): + def do_mount_overlayfs(dirs): dirs['lower'] = ':'.join(map(str, reversed(list(lowers)))) cmd = [ 'mount', @@ -897,6 +897,30 @@ def _overlay_folders(lowers, backend, upper=None, copy_filter=None): level=logging.DEBUG ) + @destroyablecontextmanager + def do_mount_fuse_overlayfs(dirs): + dirs['lower'] = ':'.join(map(str, reversed(list(lowers)))) + cmd = [ + 'fuse-overlayfs', + '-o', 'lowerdir={lower},workdir={work},upperdir={upper}'.format(**dirs), + mount_point, + ] + _subprocess_log(cmd, logger=logger, level=logging.DEBUG) + + try: + yield mount_point + except ContextManagerExit: + # Use lazy unmount, so it will not fail if it still in use for + # some reason. That said, all supporting folders are going to + # be removed so an external user working outside of the "with" + # statement will have issues, which is expected (and not + # supported). + _subprocess_log( + ['fusermount', '-u', mount_point], + logger=logger, + level=logging.DEBUG + ) + if copy_filter is None: copy_filter = lambda src, dst: True @@ -975,7 +999,9 @@ def _overlay_folders(lowers, backend, upper=None, copy_filter=None): shutil.move(src=mount_point, dst=upper) if backend == 'overlayfs': - action = do_mount + action = do_mount_overlayfs + elif backend == 'fuse-overlayfs': + action = do_mount_fuse_overlayfs elif backend == 'copy': action = do_copy else: @@ -1162,7 +1188,7 @@ class _KernelBuildEnvConf(SimpleMultiSrcConf): )), )), - KeyDesc('overlay-backend', 'Backend to use for overlaying folders while building modules. Can be "overlayfs" (overlayfs filesystem, recommended and fastest) or "copy (plain folder copy)', [str]), + KeyDesc('overlay-backend', 'Backend to use for overlaying folders while building modules. Can be "overlayfs" (overlayfs filesystem, recommended and fastest), "fuse-overlayfs" (suitable for environments where user namespaces are disabled), "copy (plain folder copy)', [str]), KeyDesc('make-variables', 'Extra variables to pass to "make" command, such as "CC"', [typing.Dict[str, object]]), VariadicLevelKeyDesc('modules', 'modules settings', @@ -3029,7 +3055,13 @@ class DynamicKmod(Loggable): make_vars = dict(make_vars) if self._compile_needs_root: - compile_ = ensure_root(self._do_compile_subprocess.__func__, inline=True) + def compile_(*args, **kwargs): + try: + return ensure_root(self._do_compile_subprocess.__func__, inline=True)(*args, **kwargs) + except Exception as e: + if self.kernel_build_env.conf['overlay-backend'] == 'overlayfs': + self.logger.error('If user namespace could not be setup, you may want to try "overlay-backend: fuse-overlayfs"') + raise e else: compile_ = self._do_compile.__func__ -- GitLab