daemon: sortMounts: move to container.SortMounts

Move the utility to the container package, which is where the Mount
type is defined, and to allow re-use of the utility both inside the
container package and the daemon package.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn committed 2026-09-01 11:37:19 +02:00
1 parent d436f4962e
commit 6b41afdf0a
6 files changed
+39 -35

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
package container
import (
"cmp"
"os"
"path/filepath"
"slices"
"strings"
)
// compareMountPaths compares mount paths by depth so that parent paths sort
// before paths beneath them.
func compareMountPaths(a, b string) int {
a = filepath.Clean(a)
b = filepath.Clean(b)
aParts := strings.Count(a, string(os.PathSeparator))
bParts := strings.Count(b, string(os.PathSeparator))
if c := cmp.Compare(aParts, bParts); c != 0 {
return c
}
return cmp.Compare(a, b)
}
// SortMounts sorts mounts by destination depth so that parent mounts are
// applied before mounts beneath them. Mounts at the same depth are sorted
// by destination to produce a deterministic order.
//
// For example, /etc must be mounted before /etc/resolv.conf.
func SortMounts(m []Mount) {
slices.SortStableFunc(m, func(a, b Mount) int {
return compareMountPaths(a.Destination, b.Destination)
})
}
@@ -1,4 +1,4 @@
package daemon
package container_test
import (
"testing"
@@ -81,7 +81,7 @@ func TestSortMounts(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
sortMounts(tc.mounts)
container.SortMounts(tc.mounts)
assert.DeepEqual(t, tc.expected, tc.mounts)
})
}
+1 -1
View File
@@ -479,7 +479,7 @@ var (
// withMounts sets the container's mounts
func withMounts(daemon *Daemon, daemonCfg *configStore, c *container.Container, mounts []container.Mount) coci.SpecOpts {
return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
sortMounts(mounts)
container.SortMounts(mounts)
userMounts := make(map[string]struct{})
for _, m := range mounts {
-30
View File
@@ -1,15 +1,10 @@
package daemon
import (
"cmp"
"context"
"crypto/sha256"
"encoding/hex"
"maps"
"os"
"path/filepath"
"slices"
"strings"
"time"
"github.com/containerd/log"
@@ -28,31 +23,6 @@ import (
var _ volume.LiveRestorer = (*volumeWrapper)(nil)
// compareMountPaths compares mount paths by depth so that parent paths sort
// before paths beneath them.
func compareMountPaths(a, b string) int {
a = filepath.Clean(a)
b = filepath.Clean(b)
aParts := strings.Count(a, string(os.PathSeparator))
bParts := strings.Count(b, string(os.PathSeparator))
if c := cmp.Compare(aParts, bParts); c != 0 {
return c
}
return cmp.Compare(a, b)
}
// sortMounts sorts mounts by destination depth so that parent mounts are
// applied before mounts beneath them. Mounts at the same depth are sorted
// by destination to produce a deterministic order.
//
// For example, /etc must be mounted before /etc/resolv.conf.
func sortMounts(m []container.Mount) {
slices.SortStableFunc(m, func(a, b container.Mount) int {
return compareMountPaths(a.Destination, b.Destination)
})
}
// registerMountPoints initializes the container mount points with the configured volumes and bind mounts.
// It follows the next sequence to decide what to mount in each final destination:
//
+1 -1
View File
@@ -103,7 +103,7 @@ func (daemon *Daemon) setupMounts(ctx context.Context, c *container.Container) (
}
}
sortMounts(mounts)
container.SortMounts(mounts)
netMounts := c.NetworkMounts()
// if we are going to mount any of the network files from container
// metadata, the ownership must be set properly for potential container
+1 -1
View File
@@ -48,7 +48,7 @@ func (daemon *Daemon) setupMounts(ctx context.Context, c *container.Container) (
})
}
sortMounts(mnts)
container.SortMounts(mnts)
return mnts, mntCleanups.Release(), nil
}