From a2953dad10db69dd9bd6e0880151dc033b8e87b5 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 13 Mar 2025 16:44:04 +0100 Subject: [PATCH] libpod: improve createRootlessContainer do not run the expensive pmount.GetMounts() function if it is not needed. As a follow-up for commit c9c44d400c2870e9a6c966647be1c414dc773b66, do not restore the propagation flag for the parent mount to shared unless it was changed to slave first. Signed-off-by: Giuseppe Scrivano --- libpod/oci_conmon_linux.go | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index dcd0088aed..5cc5948d8d 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -11,6 +11,7 @@ import ( "path/filepath" "runtime" "strings" + "sync" runcconfig "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/devices" @@ -61,11 +62,17 @@ func (r *ConmonOCIRuntime) createRootlessContainer(ctr *Container, restoreOption logrus.Errorf("Unable to reset the previous mount namespace: %q", err) } }() - mounts, err := pmount.GetMounts() - if err != nil { - return 0, err - } - if rootPath != "" { + + getMounts := sync.OnceValues(pmount.GetMounts) + + // bind mount the containers' mount path to the path where the OCI runtime expects it to be + // if the container is already mounted at the expected path, do not cover the mountpoint. + if rootPath != "" && filepath.Clean(ctr.state.Mountpoint) != filepath.Clean(rootPath) { + mounts, err := getMounts() + if err != nil { + return 0, err + } + byMountpoint := make(map[string]*pmount.Info) for _, m := range mounts { byMountpoint[m.Mountpoint] = m @@ -89,18 +96,13 @@ func (r *ConmonOCIRuntime) createRootlessContainer(ctr *Container, restoreOption } } - // bind mount the containers' mount path to the path where the OCI runtime expects it to be - // if the container is already mounted at the expected path, do not cover the mountpoint. - if filepath.Clean(ctr.state.Mountpoint) != filepath.Clean(rootPath) { - // do not propagate the bind mount on the parent mount namespace - if err := unix.Mount("", parentMount, "", unix.MS_SLAVE, ""); err != nil { - return 0, fmt.Errorf("failed to make %s slave: %w", parentMount, err) - } - if err := unix.Mount(ctr.state.Mountpoint, rootPath, "", unix.MS_BIND, ""); err != nil { - return 0, fmt.Errorf("failed to bind mount %s to %s: %w", ctr.state.Mountpoint, rootPath, err) - } + // do not propagate the bind mount on the parent mount namespace + if err := unix.Mount("", parentMount, "", unix.MS_SLAVE, ""); err != nil { + return 0, fmt.Errorf("failed to make %s slave: %w", parentMount, err) + } + if err := unix.Mount(ctr.state.Mountpoint, rootPath, "", unix.MS_BIND, ""); err != nil { + return 0, fmt.Errorf("failed to bind mount %s to %s: %w", ctr.state.Mountpoint, rootPath, err) } - if isShared { // we need to restore the shared propagation of the parent mount so that we don't break -v $SRC:$DST:shared in the container // if $SRC is on the same mount as the root path @@ -118,6 +120,10 @@ func (r *ConmonOCIRuntime) createRootlessContainer(ctr *Container, restoreOption if err != nil { return 0, fmt.Errorf("cannot make /sys slave: %w", err) } + mounts, err := getMounts() + if err != nil { + return 0, err + } for _, m := range mounts { if !strings.HasPrefix(m.Mountpoint, "/sys/kernel") { continue