]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
apk: Fix EBUSY in sync() when context.root is a mount point main
authorClayton Craft <clayton@craftyguy.net>
Sat, 11 Apr 2026 00:18:48 +0000 (17:18 -0700)
committerJörg Behrmann <behrmann@physik.fu-berlin.de>
Thu, 16 Apr 2026 07:53:22 +0000 (09:53 +0200)
sync() temporarily moved context.root out of the way to get an empty
directory to run apk against without touching the image root. This fails
when context.root is a mount point, e.g. when Overlay= is enabled:

    OSError: [Errno 16] Resource busy: '...root' -> '...saved-root'

This uses a throwaway directory in the workspace instead, since apk
doesn't need to run against context.root specifically.

mkosi/installer/apk.py

index 2d9c7ceb7bc9b25d7c9a899dc7c8b16fbecb26c3..f043c0fc6cccad38f752e6d003f5b5e3435ca3f3 100644 (file)
@@ -130,13 +130,19 @@ class Apk(PackageManager):
     @classmethod
     def sync(cls, context: Context, force: bool) -> None:
         # Updating the cache requires an initialized apk database but we don't want to touch the image root
-        # directory so temporarily replace it with an empty directory to make apk happy.
-        saved = context.root.rename(context.workspace / "saved-root")
-        context.root.mkdir()
-        cls.invoke(context, "add", ["--initdb"])
-        cls.invoke(context, "update", ["--update-cache"] if force else [], cached_metadata=False)
-        rmtree(context.root)
-        saved.rename(context.root)
+        # directory as it may be a mount point. Use a throwaway directory instead.
+        tmp = context.workspace / "apk-sync-root"
+        tmp.mkdir(exist_ok=True)
+        cmd = cls.cmd(context)
+        options = ["--bind", tmp, "/buildroot", *cls.mounts(context), *cls.options(root=tmp, apivfs=False)]
+        env = cls.finalize_environment(context)
+        run(cmd + ["add", "--initdb"], sandbox=context.sandbox(network=True, options=options), env=env)
+        run(
+            cls.cmd(context, cached_metadata=False) + ["update", *(["--update-cache"] if force else [])],
+            sandbox=context.sandbox(network=True, options=options),
+            env=env,
+        )
+        rmtree(tmp)
 
     @classmethod
     def createrepo(cls, context: Context) -> None: