mirror of
https://github.com/containerd/containerd.git
synced 2026-06-24 08:48:48 +00:00
Kernel 6.12.80+ returns 'fsync=volatile' instead of just 'volatile' in mount options, which breaks containerd's exact string matching checks. Fixes this issue by adding support for 'fsync=volatile' in addition to the existing 'volatile' check in RemoveVolatileOption and addVolatileOptionOnImageVolumeMount. Assisted-by: Antigravity Signed-off-by: Chris Henzie <chrishenzie@gmail.com>
109 lines
3.0 KiB
Go
109 lines
3.0 KiB
Go
//go:build linux
|
|
|
|
/*
|
|
Copyright The containerd Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package server
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"slices"
|
|
"sync"
|
|
|
|
containerd "github.com/containerd/containerd/v2/client"
|
|
"github.com/containerd/containerd/v2/core/mount"
|
|
"github.com/containerd/containerd/v2/core/snapshots"
|
|
kernel "github.com/containerd/containerd/v2/pkg/kernelversion"
|
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
|
)
|
|
|
|
var (
|
|
volatileSupported bool
|
|
volatileSupportedOnce sync.Once
|
|
)
|
|
|
|
// addVolatileOptionOnImageVolumeMount adds volatile option if applicable. It
|
|
// can avoid syncfs when we clean it up.
|
|
func addVolatileOptionOnImageVolumeMount(mounts []mount.Mount) []mount.Mount {
|
|
volatileSupportedOnce.Do(func() {
|
|
volatileSupported, _ = kernel.GreaterEqualThan(
|
|
kernel.KernelVersion{
|
|
Kernel: 5, Major: 10,
|
|
},
|
|
)
|
|
})
|
|
|
|
if !volatileSupported {
|
|
return mounts
|
|
}
|
|
|
|
for i, m := range mounts {
|
|
if m.Type != "overlay" || slices.Contains(m.Options, "volatile") || slices.Contains(m.Options, "fsync=volatile") {
|
|
continue
|
|
}
|
|
mounts[i].Options = append(mounts[i].Options, "volatile")
|
|
}
|
|
return mounts
|
|
}
|
|
|
|
// ensureImageVolumeMounted ensures target volume is mounted.
|
|
//
|
|
// NOTE: Currently, kubelet creates containers in pod sequencially. It won't
|
|
// cause multiple mountpoints on same target path.
|
|
func ensureImageVolumeMounted(target string) (bool, error) {
|
|
_, err := os.Stat(target)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return false, nil
|
|
}
|
|
return false, fmt.Errorf("failed to stat %s: %w", target, err)
|
|
}
|
|
mpInfo, err := mount.Lookup(target)
|
|
if err != nil {
|
|
return false, fmt.Errorf("failed to check %s mountpoint: %w", target, err)
|
|
}
|
|
|
|
if mpInfo.Mountpoint != target {
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
// getImageVolumeSnapshotOpts returns snapshot options with user namespace idmap labels
|
|
// from the mount's UID/GID mappings. This ensures that image volumes work correctly
|
|
// with user namespaces by applying idmap to the overlay lower layers.
|
|
func (c *criService) getImageVolumeSnapshotOpts(ctx context.Context, mount *runtime.Mount) ([]snapshots.Opt, error) {
|
|
uids, err := parseUsernsIDMap(mount.GetUidMappings())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse UID mappings: %w", err)
|
|
}
|
|
|
|
gids, err := parseUsernsIDMap(mount.GetGidMappings())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse GID mappings: %w", err)
|
|
}
|
|
|
|
if len(uids) == 0 || len(gids) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
return []snapshots.Opt{
|
|
containerd.WithRemapperLabels(0, uids[0].HostID, 0, gids[0].HostID, uids[0].Size),
|
|
}, nil
|
|
}
|