mirror of
https://github.com/containers/podman.git
synced 2025-10-17 11:14:40 +08:00
Update common, image, and storage deps
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
8
go.mod
8
go.mod
@ -12,21 +12,21 @@ require (
|
||||
github.com/checkpoint-restore/go-criu/v7 v7.2.0
|
||||
github.com/containernetworking/plugins v1.7.1
|
||||
github.com/containers/buildah v1.40.1-0.20250604193037-b8d8cc375f30
|
||||
github.com/containers/common v0.63.2-0.20250707185859-2b4e95a951de
|
||||
github.com/containers/common v0.63.2-0.20250711144526-f3f68c4e79f5
|
||||
github.com/containers/conmon v2.0.20+incompatible
|
||||
github.com/containers/gvisor-tap-vsock v0.8.6
|
||||
github.com/containers/image/v5 v5.35.1-0.20250707180819-778317a88563
|
||||
github.com/containers/image/v5 v5.35.1-0.20250714114753-9e95082de671
|
||||
github.com/containers/libhvee v0.10.0
|
||||
github.com/containers/ocicrypt v1.2.1
|
||||
github.com/containers/psgo v1.9.0
|
||||
github.com/containers/storage v1.58.1-0.20250701152554-3aa733962202
|
||||
github.com/containers/storage v1.58.1-0.20250711145627-2b18ddcfafca
|
||||
github.com/containers/winquit v1.1.0
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09
|
||||
github.com/crc-org/vfkit v0.6.1
|
||||
github.com/cyphar/filepath-securejoin v0.4.1
|
||||
github.com/digitalocean/go-qemu v0.0.0-20250212194115-ee9b0668d242
|
||||
github.com/docker/distribution v2.8.3+incompatible
|
||||
github.com/docker/docker v28.3.1+incompatible
|
||||
github.com/docker/docker v28.3.2+incompatible
|
||||
github.com/docker/go-connections v0.5.0
|
||||
github.com/docker/go-plugins-helpers v0.0.0-20240701071450-45e2431495c8
|
||||
github.com/docker/go-units v0.5.0
|
||||
|
20
go.sum
20
go.sum
@ -64,14 +64,14 @@ github.com/containernetworking/plugins v1.7.1 h1:CNAR0jviDj6FS5Vg85NTgKWLDzZPfi/
|
||||
github.com/containernetworking/plugins v1.7.1/go.mod h1:xuMdjuio+a1oVQsHKjr/mgzuZ24leAsqUYRnzGoXHy0=
|
||||
github.com/containers/buildah v1.40.1-0.20250604193037-b8d8cc375f30 h1:kCt0fnVBvXY9J98pUDeUc0gHKrhRwaBTWWD3otLutCE=
|
||||
github.com/containers/buildah v1.40.1-0.20250604193037-b8d8cc375f30/go.mod h1:QDecwvjrr+e0VD5GYv2dw7tsiqrz673r8B4rIYFP11Y=
|
||||
github.com/containers/common v0.63.2-0.20250707185859-2b4e95a951de h1:52Qyd3ijcmsRNiv2Dl8JVdvewO4YRM0a8+FwLHq3ylk=
|
||||
github.com/containers/common v0.63.2-0.20250707185859-2b4e95a951de/go.mod h1:WyydvanMw4iZI2pnup5MbK7zyDvLUBTaTyva3fYwBwc=
|
||||
github.com/containers/common v0.63.2-0.20250711144526-f3f68c4e79f5 h1:jkwIh/F1mGjunP/FEaAB8EsMGNxewzudOeP5/d4s1eQ=
|
||||
github.com/containers/common v0.63.2-0.20250711144526-f3f68c4e79f5/go.mod h1:qggLDgdS0vtjnj3aNTnRxU34cgXTSDWu48jRBX8GSZM=
|
||||
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
|
||||
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
|
||||
github.com/containers/gvisor-tap-vsock v0.8.6 h1:9SeAXK+K2o36CtrgYk6zRXbU3zrayjvkrI8b7/O6u5A=
|
||||
github.com/containers/gvisor-tap-vsock v0.8.6/go.mod h1:+0mtKmm4STeSDnZe+DGnIwN4EH2f7AcWir7PwT28Ti0=
|
||||
github.com/containers/image/v5 v5.35.1-0.20250707180819-778317a88563 h1:LDvwngzUOv0V0UUuGQXXaxUeH7HNRDe+gl+3Plv8A5s=
|
||||
github.com/containers/image/v5 v5.35.1-0.20250707180819-778317a88563/go.mod h1:djHq2If38NWdEC9aZxGoZj4HxKOrkDo6QOOKz5wdJTs=
|
||||
github.com/containers/image/v5 v5.35.1-0.20250714114753-9e95082de671 h1:FClIeKz9aUUq2uUd1idJmFslxt1/wu3FooKANQhDItI=
|
||||
github.com/containers/image/v5 v5.35.1-0.20250714114753-9e95082de671/go.mod h1:7MVa/W6N1HIm4G+S9D+u8MtMDVtHmouDwJNSDNgH67Y=
|
||||
github.com/containers/libhvee v0.10.0 h1:7VLv8keWZpHuGmWvyY4c1mVH5V1JYb1G78VC+8AlrM0=
|
||||
github.com/containers/libhvee v0.10.0/go.mod h1:at0h8lRcK5jCKfQgU/e6Io0Mw12F36zRLjXVOXRoDTM=
|
||||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
|
||||
@ -82,8 +82,8 @@ github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpV
|
||||
github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ=
|
||||
github.com/containers/psgo v1.9.0 h1:eJ74jzSaCHnWt26OlKZROSyUyRcGDf+gYBdXnxrMW4g=
|
||||
github.com/containers/psgo v1.9.0/go.mod h1:0YoluUm43Mz2UnBIh1P+6V6NWcbpTL5uRtXyOcH0B5A=
|
||||
github.com/containers/storage v1.58.1-0.20250701152554-3aa733962202 h1:JV0pkbDShVyzX3c45WZU24Phq2LZ/dlG/SmlwTCQxXk=
|
||||
github.com/containers/storage v1.58.1-0.20250701152554-3aa733962202/go.mod h1:uXFaVHnIkR0wMBWdK01TL8G0iVtZVYLJmFqZuqS4rCE=
|
||||
github.com/containers/storage v1.58.1-0.20250711145627-2b18ddcfafca h1:uQC94qWTjMKo0/IDTe5qTGGqkLb0rD18UfjG675YpwU=
|
||||
github.com/containers/storage v1.58.1-0.20250711145627-2b18ddcfafca/go.mod h1:KoAYHnAjP3/cTsRS+mmWZGkufSY2GACiKQ4V3ZLQnR0=
|
||||
github.com/containers/winquit v1.1.0 h1:jArun04BNDQvt2W0Y78kh9TazN2EIEMG5Im6/JY7+pE=
|
||||
github.com/containers/winquit v1.1.0/go.mod h1:PsPeZlnbkmGGIToMPHF1zhWjBUkd8aHjMOr/vFcPxw8=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
|
||||
@ -113,12 +113,12 @@ github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWh
|
||||
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v28.3.1+incompatible h1:ZUdwOLDEBoE3TE5rdC9IXGY5HPHksJK3M+hJEWhh2mc=
|
||||
github.com/docker/cli v28.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v28.3.2+incompatible h1:mOt9fcLE7zaACbxW1GeS65RI67wIJrTnqS3hP2huFsY=
|
||||
github.com/docker/cli v28.3.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v28.3.1+incompatible h1:20+BmuA9FXlCX4ByQ0vYJcUEnOmRM6XljDnFWR+jCyY=
|
||||
github.com/docker/docker v28.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA=
|
||||
github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
|
2
vendor/github.com/containers/common/libimage/copier.go
generated
vendored
2
vendor/github.com/containers/common/libimage/copier.go
generated
vendored
@ -488,7 +488,7 @@ func (c *Copier) copyToStorage(ctx context.Context, source, destination types.Im
|
||||
var resolvedReference types.ImageReference
|
||||
_, err := c.copyInternal(ctx, source, destination, &resolvedReference)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("internal error: unable to copy from source %s: %w", transports.ImageName(source), err)
|
||||
return nil, fmt.Errorf("unable to copy from source %s: %w", transports.ImageName(source), err)
|
||||
}
|
||||
if resolvedReference == nil {
|
||||
return nil, fmt.Errorf("internal error: After attempting to copy %s, resolvedReference is nil", source)
|
||||
|
12
vendor/github.com/containers/storage/drivers/aufs/aufs.go
generated
vendored
12
vendor/github.com/containers/storage/drivers/aufs/aufs.go
generated
vendored
@ -36,6 +36,7 @@ import (
|
||||
"time"
|
||||
|
||||
graphdriver "github.com/containers/storage/drivers"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/chrootarchive"
|
||||
"github.com/containers/storage/pkg/directory"
|
||||
@ -781,3 +782,14 @@ func (a *Driver) SupportsShifting(uidmap, gidmap []idtools.IDMap) bool {
|
||||
func (a *Driver) Dedup(req graphdriver.DedupArgs) (graphdriver.DedupResult, error) {
|
||||
return graphdriver.DedupResult{}, nil
|
||||
}
|
||||
|
||||
// DeferredRemove is not implemented.
|
||||
// It calls Remove directly.
|
||||
func (a *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
|
||||
return nil, a.Remove(id)
|
||||
}
|
||||
|
||||
// GetTempDirRootDirs is not implemented.
|
||||
func (a *Driver) GetTempDirRootDirs() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
12
vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
generated
vendored
12
vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
generated
vendored
@ -30,6 +30,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
graphdriver "github.com/containers/storage/drivers"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/directory"
|
||||
"github.com/containers/storage/pkg/fileutils"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
@ -678,3 +679,14 @@ func (d *Driver) AdditionalImageStores() []string {
|
||||
func (d *Driver) Dedup(req graphdriver.DedupArgs) (graphdriver.DedupResult, error) {
|
||||
return graphdriver.DedupResult{}, nil
|
||||
}
|
||||
|
||||
// DeferredRemove is not implemented.
|
||||
// It calls Remove directly.
|
||||
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
|
||||
return nil, d.Remove(id)
|
||||
}
|
||||
|
||||
// GetTempDirRootDirs is not implemented.
|
||||
func (d *Driver) GetTempDirRootDirs() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
11
vendor/github.com/containers/storage/drivers/driver.go
generated
vendored
11
vendor/github.com/containers/storage/drivers/driver.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/containers/storage/internal/dedup"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/directory"
|
||||
"github.com/containers/storage/pkg/fileutils"
|
||||
@ -123,7 +124,17 @@ type ProtoDriver interface {
|
||||
// and parent, with contents identical to the specified template layer.
|
||||
CreateFromTemplate(id, template string, templateIDMappings *idtools.IDMappings, parent string, parentIDMappings *idtools.IDMappings, opts *CreateOpts, readWrite bool) error
|
||||
// Remove attempts to remove the filesystem layer with this id.
|
||||
// This is soft-deprecated and should not get any new callers; use DeferredRemove.
|
||||
Remove(id string) error
|
||||
// DeferredRemove is used to remove the filesystem layer with this id.
|
||||
// This removal happen immediately (the layer is no longer usable),
|
||||
// but physically deleting the files may be deferred.
|
||||
// Caller MUST call returned Cleanup function EVEN IF the function returns an error.
|
||||
DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error)
|
||||
// GetTempDirRootDirs returns the root directories for temporary directories.
|
||||
// Multiple directories may be returned when drivers support different filesystems
|
||||
// for layers (e.g., overlay with imageStore vs home directory).
|
||||
GetTempDirRootDirs() []string
|
||||
// Get returns the mountpoint for the layered filesystem referred
|
||||
// to by this id. You can optionally specify a mountLabel or "".
|
||||
// Optionally it gets the mappings used to create the layer.
|
||||
|
60
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
60
vendor/github.com/containers/storage/drivers/overlay/overlay.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
"github.com/containers/storage/drivers/quota"
|
||||
"github.com/containers/storage/internal/dedup"
|
||||
"github.com/containers/storage/internal/staging_lockfile"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/chrootarchive"
|
||||
"github.com/containers/storage/pkg/directory"
|
||||
@ -80,10 +81,11 @@ const (
|
||||
// that mounts do not fail due to length.
|
||||
|
||||
const (
|
||||
linkDir = "l"
|
||||
stagingDir = "staging"
|
||||
lowerFile = "lower"
|
||||
maxDepth = 500
|
||||
linkDir = "l"
|
||||
stagingDir = "staging"
|
||||
tempDirName = "tempdirs"
|
||||
lowerFile = "lower"
|
||||
maxDepth = 500
|
||||
|
||||
stagingLockFile = "staging.lock"
|
||||
|
||||
@ -1305,17 +1307,22 @@ func (d *Driver) optsAppendMappings(opts string, uidMaps, gidMaps []idtools.IDMa
|
||||
|
||||
// Remove cleans the directories that are created for this id.
|
||||
func (d *Driver) Remove(id string) error {
|
||||
return d.removeCommon(id, system.EnsureRemoveAll)
|
||||
}
|
||||
|
||||
func (d *Driver) removeCommon(id string, cleanup func(string) error) error {
|
||||
dir := d.dir(id)
|
||||
lid, err := os.ReadFile(path.Join(dir, "link"))
|
||||
if err == nil {
|
||||
if err := os.RemoveAll(path.Join(d.home, linkDir, string(lid))); err != nil {
|
||||
linkPath := path.Join(d.home, linkDir, string(lid))
|
||||
if err := cleanup(linkPath); err != nil {
|
||||
logrus.Debugf("Failed to remove link: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
d.releaseAdditionalLayerByID(id)
|
||||
|
||||
if err := system.EnsureRemoveAll(dir); err != nil && !os.IsNotExist(err) {
|
||||
if err := cleanup(dir); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if d.quotaCtl != nil {
|
||||
@ -1327,6 +1334,41 @@ func (d *Driver) Remove(id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetTempDirRootDirs() []string {
|
||||
tempDirs := []string{filepath.Join(d.home, tempDirName)}
|
||||
// Include imageStore temp directory if it's configured
|
||||
// Writable layers can only be in d.home or d.imageStore, not in additional image stores
|
||||
if d.imageStore != "" {
|
||||
tempDirs = append(tempDirs, filepath.Join(d.imageStore, d.name, tempDirName))
|
||||
}
|
||||
return tempDirs
|
||||
}
|
||||
|
||||
// Determine the correct temp directory root based on where the layer actually exists.
|
||||
func (d *Driver) getTempDirRoot(id string) string {
|
||||
layerDir := d.dir(id)
|
||||
if d.imageStore != "" {
|
||||
expectedLayerDir := path.Join(d.imageStore, d.name, id)
|
||||
if layerDir == expectedLayerDir {
|
||||
return filepath.Join(d.imageStore, d.name, tempDirName)
|
||||
}
|
||||
}
|
||||
return filepath.Join(d.home, tempDirName)
|
||||
}
|
||||
|
||||
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
|
||||
tempDirRoot := d.getTempDirRoot(id)
|
||||
t, err := tempdir.NewTempDir(tempDirRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := d.removeCommon(id, t.StageDeletion); err != nil {
|
||||
return t.Cleanup, fmt.Errorf("failed to add to stage directory: %w", err)
|
||||
}
|
||||
return t.Cleanup, nil
|
||||
}
|
||||
|
||||
// recreateSymlinks goes through the driver's home directory and checks if the diff directory
|
||||
// under each layer has a symlink created for it under the linkDir. If the symlink does not
|
||||
// exist, it creates them
|
||||
@ -1353,8 +1395,8 @@ func (d *Driver) recreateSymlinks() error {
|
||||
// Check that for each layer, there's a link in "l" with the name in
|
||||
// the layer's "link" file that points to the layer's "diff" directory.
|
||||
for _, dir := range dirs {
|
||||
// Skip over the linkDir and anything that is not a directory
|
||||
if dir.Name() == linkDir || !dir.IsDir() {
|
||||
// Skip over the linkDir, stagingDir, tempDirName and anything that is not a directory
|
||||
if dir.Name() == linkDir || dir.Name() == stagingDir || dir.Name() == tempDirName || !dir.IsDir() {
|
||||
continue
|
||||
}
|
||||
// Read the "link" file under each layer to get the name of the symlink
|
||||
@ -2022,7 +2064,7 @@ func (d *Driver) ListLayers() ([]string, error) {
|
||||
for _, entry := range entries {
|
||||
id := entry.Name()
|
||||
switch id {
|
||||
case linkDir, stagingDir, quota.BackingFsBlockDeviceLink, mountProgramFlagFile:
|
||||
case linkDir, stagingDir, tempDirName, quota.BackingFsBlockDeviceLink, mountProgramFlagFile:
|
||||
// expected, but not a layer. skip it
|
||||
continue
|
||||
default:
|
||||
|
42
vendor/github.com/containers/storage/drivers/vfs/driver.go
generated
vendored
42
vendor/github.com/containers/storage/drivers/vfs/driver.go
generated
vendored
@ -11,6 +11,7 @@ import (
|
||||
|
||||
graphdriver "github.com/containers/storage/drivers"
|
||||
"github.com/containers/storage/internal/dedup"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/directory"
|
||||
"github.com/containers/storage/pkg/fileutils"
|
||||
@ -22,7 +23,10 @@ import (
|
||||
"github.com/vbatts/tar-split/tar/storage"
|
||||
)
|
||||
|
||||
const defaultPerms = os.FileMode(0o555)
|
||||
const (
|
||||
defaultPerms = os.FileMode(0o555)
|
||||
tempDirName = "tempdirs"
|
||||
)
|
||||
|
||||
func init() {
|
||||
graphdriver.MustRegister("vfs", Init)
|
||||
@ -244,6 +248,42 @@ func (d *Driver) Remove(id string) error {
|
||||
return system.EnsureRemoveAll(d.dir(id))
|
||||
}
|
||||
|
||||
func (d *Driver) GetTempDirRootDirs() []string {
|
||||
tempDirs := []string{filepath.Join(d.home, tempDirName)}
|
||||
// Include imageStore temp directory if it's configured
|
||||
// Writable layers can only be in d.home or d.imageStore, not in additionalHomes (which are read-only)
|
||||
if d.imageStore != "" {
|
||||
tempDirs = append(tempDirs, filepath.Join(d.imageStore, d.String(), tempDirName))
|
||||
}
|
||||
return tempDirs
|
||||
}
|
||||
|
||||
// Determine the correct temp directory root based on where the layer actually exists.
|
||||
func (d *Driver) getTempDirRoot(id string) string {
|
||||
layerDir := d.dir(id)
|
||||
if d.imageStore != "" {
|
||||
expectedLayerDir := filepath.Join(d.imageStore, d.String(), "dir", filepath.Base(id))
|
||||
if layerDir == expectedLayerDir {
|
||||
return filepath.Join(d.imageStore, d.String(), tempDirName)
|
||||
}
|
||||
}
|
||||
return filepath.Join(d.home, tempDirName)
|
||||
}
|
||||
|
||||
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
|
||||
tempDirRoot := d.getTempDirRoot(id)
|
||||
t, err := tempdir.NewTempDir(tempDirRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
layerDir := d.dir(id)
|
||||
if err := t.StageDeletion(layerDir); err != nil {
|
||||
return t.Cleanup, err
|
||||
}
|
||||
return t.Cleanup, nil
|
||||
}
|
||||
|
||||
// Get returns the directory for the given id.
|
||||
func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) {
|
||||
dir := d.dir(id)
|
||||
|
12
vendor/github.com/containers/storage/drivers/windows/windows.go
generated
vendored
12
vendor/github.com/containers/storage/drivers/windows/windows.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
"github.com/Microsoft/go-winio/backuptar"
|
||||
"github.com/Microsoft/hcsshim"
|
||||
graphdriver "github.com/containers/storage/drivers"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/directory"
|
||||
"github.com/containers/storage/pkg/fileutils"
|
||||
@ -1014,3 +1015,14 @@ func parseStorageOpt(storageOpt map[string]string) (*storageOptions, error) {
|
||||
}
|
||||
return &options, nil
|
||||
}
|
||||
|
||||
// DeferredRemove is not implemented.
|
||||
// It calls Remove directly.
|
||||
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
|
||||
return nil, d.Remove(id)
|
||||
}
|
||||
|
||||
// GetTempDirRootDirs is not implemented.
|
||||
func (d *Driver) GetTempDirRootDirs() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
12
vendor/github.com/containers/storage/drivers/zfs/zfs.go
generated
vendored
12
vendor/github.com/containers/storage/drivers/zfs/zfs.go
generated
vendored
@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
graphdriver "github.com/containers/storage/drivers"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/directory"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/containers/storage/pkg/mount"
|
||||
@ -406,6 +407,12 @@ func (d *Driver) Remove(id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeferredRemove is not implemented.
|
||||
// It calls Remove directly.
|
||||
func (d *Driver) DeferredRemove(id string) (tempdir.CleanupTempDirFunc, error) {
|
||||
return nil, d.Remove(id)
|
||||
}
|
||||
|
||||
// Get returns the mountpoint for the given id after creating the target directories if necessary.
|
||||
func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) {
|
||||
mountpoint := d.mountPath(id)
|
||||
@ -516,3 +523,8 @@ func (d *Driver) AdditionalImageStores() []string {
|
||||
func (d *Driver) Dedup(req graphdriver.DedupArgs) (graphdriver.DedupResult, error) {
|
||||
return graphdriver.DedupResult{}, nil
|
||||
}
|
||||
|
||||
// GetTempDirRootDirs is not implemented.
|
||||
func (d *Driver) GetTempDirRootDirs() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
243
vendor/github.com/containers/storage/internal/tempdir/tempdir.go
generated
vendored
Normal file
243
vendor/github.com/containers/storage/internal/tempdir/tempdir.go
generated
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
package tempdir
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/storage/internal/staging_lockfile"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
/*
|
||||
Locking rules and invariants for TempDir and its recovery mechanism:
|
||||
|
||||
1. TempDir Instance Locks:
|
||||
- Path: 'RootDir/lock-XYZ' (in the root directory)
|
||||
- Each TempDir instance creates and holds an exclusive lock on this file immediately
|
||||
during NewTempDir() initialization.
|
||||
- This lock signifies that the temporary directory is in active use by the
|
||||
process/goroutine that holds the TempDir object.
|
||||
|
||||
2. Stale Directory Recovery (separate operation):
|
||||
- RecoverStaleDirs() can be called independently to identify and clean up stale
|
||||
temporary directories.
|
||||
- For each potential stale directory (found by listPotentialStaleDirs), it
|
||||
attempts to TryLockPath() its instance lock file.
|
||||
- If TryLockPath() succeeds: The directory is considered stale, and both the
|
||||
directory and lock file are removed.
|
||||
- If TryLockPath() fails: The directory is considered in active use by another
|
||||
process/goroutine, and it's skipped.
|
||||
|
||||
3. TempDir Usage:
|
||||
- NewTempDir() immediately creates both the instance lock and the temporary directory.
|
||||
- TempDir.StageDeletion() moves files into the existing temporary directory with counter-based naming.
|
||||
- Files moved into the temporary directory are renamed with a counter-based prefix
|
||||
to ensure uniqueness (e.g., "0-filename", "1-filename").
|
||||
- Once cleaned up, the TempDir instance cannot be reused - StageDeletion() will return an error.
|
||||
|
||||
4. Cleanup Process:
|
||||
- TempDir.Cleanup() removes both the temporary directory and its lock file.
|
||||
- The instance lock is unlocked and deleted after cleanup operations are complete.
|
||||
- The TempDir instance becomes inactive after cleanup (internal fields are reset).
|
||||
- The TempDir instance cannot be reused after Cleanup() - StageDeletion() will fail.
|
||||
|
||||
5. TempDir Lifetime:
|
||||
- NewTempDir() creates both the TempDir manager and the actual temporary directory immediately.
|
||||
- The temporary directory is created eagerly during NewTempDir().
|
||||
- During its lifetime, the temporary directory is protected by its instance lock.
|
||||
- The temporary directory exists until Cleanup() is called, which removes both
|
||||
the directory and its lock file.
|
||||
- Multiple TempDir instances can coexist in the same RootDir, each with its own
|
||||
unique subdirectory and lock.
|
||||
- After cleanup, the TempDir instance cannot be reused.
|
||||
|
||||
6. Example Directory Structure:
|
||||
|
||||
RootDir/
|
||||
lock-ABC (instance lock for temp-dir-ABC)
|
||||
temp-dir-ABC/
|
||||
0-file1
|
||||
1-file3
|
||||
lock-XYZ (instance lock for temp-dir-XYZ)
|
||||
temp-dir-XYZ/
|
||||
0-file2
|
||||
*/
|
||||
const (
|
||||
// tempDirPrefix is the prefix used for creating temporary directories.
|
||||
tempDirPrefix = "temp-dir-"
|
||||
// tempdirLockPrefix is the prefix used for creating lock files for temporary directories.
|
||||
tempdirLockPrefix = "lock-"
|
||||
)
|
||||
|
||||
// TempDir represents a temporary directory that is created in a specified root directory.
|
||||
// It manages the lifecycle of the temporary directory, including creation, locking, and cleanup.
|
||||
// Each TempDir instance is associated with a unique subdirectory in the root directory.
|
||||
// Warning: The TempDir instance should be used in a single goroutine.
|
||||
type TempDir struct {
|
||||
RootDir string
|
||||
|
||||
tempDirPath string
|
||||
// tempDirLock is a lock file (e.g., RootDir/lock-XYZ) specific to this
|
||||
// TempDir instance, indicating it's in active use.
|
||||
tempDirLock *staging_lockfile.StagingLockFile
|
||||
tempDirLockPath string
|
||||
|
||||
// counter is used to generate unique filenames for added files.
|
||||
counter uint64
|
||||
}
|
||||
|
||||
// CleanupTempDirFunc is a function type that can be returned by operations
|
||||
// which need to perform cleanup actions later.
|
||||
type CleanupTempDirFunc func() error
|
||||
|
||||
// listPotentialStaleDirs scans the RootDir for directories that might be stale temporary directories.
|
||||
// It identifies directories with the tempDirPrefix and their corresponding lock files with the tempdirLockPrefix.
|
||||
// The function returns a map of IDs that correspond to both directories and lock files found.
|
||||
// These IDs are extracted from the filenames by removing their respective prefixes.
|
||||
func listPotentialStaleDirs(rootDir string) (map[string]struct{}, error) {
|
||||
ids := make(map[string]struct{})
|
||||
|
||||
dirContent, err := os.ReadDir(rootDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("error reading temp dir %s: %w", rootDir, err)
|
||||
}
|
||||
|
||||
for _, entry := range dirContent {
|
||||
if id, ok := strings.CutPrefix(entry.Name(), tempDirPrefix); ok {
|
||||
ids[id] = struct{}{}
|
||||
continue
|
||||
}
|
||||
|
||||
if id, ok := strings.CutPrefix(entry.Name(), tempdirLockPrefix); ok {
|
||||
ids[id] = struct{}{}
|
||||
}
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// RecoverStaleDirs identifies and removes stale temporary directories in the root directory.
|
||||
// A directory is considered stale if its lock file can be acquired (indicating no active use).
|
||||
// The function attempts to remove both the directory and its lock file.
|
||||
// If a directory's lock cannot be acquired, it is considered in use and is skipped.
|
||||
func RecoverStaleDirs(rootDir string) error {
|
||||
potentialStaleDirs, err := listPotentialStaleDirs(rootDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error listing potential stale temp dirs in %s: %w", rootDir, err)
|
||||
}
|
||||
|
||||
if len(potentialStaleDirs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var recoveryErrors []error
|
||||
|
||||
for id := range potentialStaleDirs {
|
||||
lockPath := filepath.Join(rootDir, tempdirLockPrefix+id)
|
||||
tempDirPath := filepath.Join(rootDir, tempDirPrefix+id)
|
||||
|
||||
// Try to lock the lock file. If it can be locked, the directory is stale.
|
||||
instanceLock, err := staging_lockfile.TryLockPath(lockPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if rmErr := os.RemoveAll(tempDirPath); rmErr != nil && !os.IsNotExist(rmErr) {
|
||||
recoveryErrors = append(recoveryErrors, fmt.Errorf("error removing stale temp dir %s: %w", tempDirPath, rmErr))
|
||||
}
|
||||
if unlockErr := instanceLock.UnlockAndDelete(); unlockErr != nil {
|
||||
recoveryErrors = append(recoveryErrors, fmt.Errorf("error unlocking and deleting stale lock file %s: %w", lockPath, unlockErr))
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Join(recoveryErrors...)
|
||||
}
|
||||
|
||||
// NewTempDir creates a TempDir and immediately creates both the temporary directory
|
||||
// and its corresponding lock file in the specified RootDir.
|
||||
// The RootDir itself will be created if it doesn't exist.
|
||||
// Note: The caller MUST ensure that returned TempDir instance is cleaned up with .Cleanup().
|
||||
func NewTempDir(rootDir string) (*TempDir, error) {
|
||||
if err := os.MkdirAll(rootDir, 0o700); err != nil {
|
||||
return nil, fmt.Errorf("creating root temp directory %s failed: %w", rootDir, err)
|
||||
}
|
||||
|
||||
td := &TempDir{
|
||||
RootDir: rootDir,
|
||||
}
|
||||
tempDirLock, tempDirLockFileName, err := staging_lockfile.CreateAndLock(td.RootDir, tempdirLockPrefix)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating and locking temp dir instance lock in %s failed: %w", td.RootDir, err)
|
||||
}
|
||||
td.tempDirLock = tempDirLock
|
||||
td.tempDirLockPath = filepath.Join(td.RootDir, tempDirLockFileName)
|
||||
|
||||
// Create the temporary directory that corresponds to the lock file
|
||||
id := strings.TrimPrefix(tempDirLockFileName, tempdirLockPrefix)
|
||||
actualTempDirPath := filepath.Join(td.RootDir, tempDirPrefix+id)
|
||||
if err := os.MkdirAll(actualTempDirPath, 0o700); err != nil {
|
||||
return nil, fmt.Errorf("creating temp directory %s failed: %w", actualTempDirPath, err)
|
||||
}
|
||||
td.tempDirPath = actualTempDirPath
|
||||
td.counter = 0
|
||||
return td, nil
|
||||
}
|
||||
|
||||
// StageDeletion moves the specified file into the instance's temporary directory.
|
||||
// The temporary directory must already exist (created during NewTempDir).
|
||||
// Files are renamed with a counter-based prefix (e.g., "0-filename", "1-filename") to ensure uniqueness.
|
||||
// Note: 'path' must be on the same filesystem as the TempDir for os.Rename to work.
|
||||
// The caller MUST ensure .Cleanup() is called.
|
||||
// If the TempDir has been cleaned up, this method will return an error.
|
||||
func (td *TempDir) StageDeletion(path string) error {
|
||||
if td.tempDirLock == nil {
|
||||
return fmt.Errorf("temp dir instance not initialized or already cleaned up")
|
||||
}
|
||||
fileName := fmt.Sprintf("%d-", td.counter) + filepath.Base(path)
|
||||
destPath := filepath.Join(td.tempDirPath, fileName)
|
||||
td.counter++
|
||||
return os.Rename(path, destPath)
|
||||
}
|
||||
|
||||
// Cleanup removes the temporary directory and releases its instance lock.
|
||||
// After cleanup, the TempDir instance becomes inactive and cannot be reused.
|
||||
// Subsequent calls to StageDeletion() will fail.
|
||||
// Multiple calls to Cleanup() are safe and will not return an error.
|
||||
// Callers should typically defer Cleanup() to run after any application-level
|
||||
// global locks are released to avoid holding those locks during potentially
|
||||
// slow disk I/O.
|
||||
func (td *TempDir) Cleanup() error {
|
||||
if td.tempDirLock == nil {
|
||||
logrus.Debug("Temp dir already cleaned up")
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(td.tempDirPath); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("removing temp dir %s failed: %w", td.tempDirPath, err)
|
||||
}
|
||||
|
||||
lock := td.tempDirLock
|
||||
td.tempDirPath = ""
|
||||
td.tempDirLock = nil
|
||||
td.tempDirLockPath = ""
|
||||
return lock.UnlockAndDelete()
|
||||
}
|
||||
|
||||
// CleanupTemporaryDirectories cleans up multiple temporary directories by calling their cleanup functions.
|
||||
func CleanupTemporaryDirectories(cleanFuncs ...CleanupTempDirFunc) error {
|
||||
var cleanupErrors []error
|
||||
for _, cleanupFunc := range cleanFuncs {
|
||||
if cleanupFunc == nil {
|
||||
continue
|
||||
}
|
||||
if err := cleanupFunc(); err != nil {
|
||||
cleanupErrors = append(cleanupErrors, err)
|
||||
}
|
||||
}
|
||||
return errors.Join(cleanupErrors...)
|
||||
}
|
98
vendor/github.com/containers/storage/layers.go
generated
vendored
98
vendor/github.com/containers/storage/layers.go
generated
vendored
@ -18,6 +18,7 @@ import (
|
||||
"time"
|
||||
|
||||
drivers "github.com/containers/storage/drivers"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
@ -38,6 +39,8 @@ import (
|
||||
|
||||
const (
|
||||
tarSplitSuffix = ".tar-split.gz"
|
||||
// tempDirPath is the subdirectory name used for storing temporary directories during layer deletion
|
||||
tempDirPath = "tmp"
|
||||
incompleteFlag = "incomplete"
|
||||
// maxLayerStoreCleanupIterations is the number of times we try to clean up inconsistent layer store state
|
||||
// in readers (which, for implementation reasons, gives other writers the opportunity to create more inconsistent state)
|
||||
@ -290,8 +293,14 @@ type rwLayerStore interface {
|
||||
// updateNames modifies names associated with a layer based on (op, names).
|
||||
updateNames(id string, names []string, op updateNameOperation) error
|
||||
|
||||
// Delete deletes a layer with the specified name or ID.
|
||||
Delete(id string) error
|
||||
// deleteWhileHoldingLock deletes a layer with the specified name or ID.
|
||||
deleteWhileHoldingLock(id string) error
|
||||
|
||||
// deferredDelete deletes a layer with the specified name or ID.
|
||||
// This removal happen immediately (the layer is no longer usable),
|
||||
// but physically deleting the files may be deferred.
|
||||
// Caller MUST call all returned cleanup functions outside of the locks.
|
||||
deferredDelete(id string) ([]tempdir.CleanupTempDirFunc, error)
|
||||
|
||||
// Wipe deletes all layers.
|
||||
Wipe() error
|
||||
@ -794,6 +803,17 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
|
||||
layers := []*Layer{}
|
||||
ids := make(map[string]*Layer)
|
||||
|
||||
if r.lockfile.IsReadWrite() {
|
||||
if err := tempdir.RecoverStaleDirs(filepath.Join(r.layerdir, tempDirPath)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, driverTempDirPath := range r.driver.GetTempDirRootDirs() {
|
||||
if err := tempdir.RecoverStaleDirs(driverTempDirPath); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for locationIndex := range numLayerLocationIndex {
|
||||
location := layerLocationFromIndex(locationIndex)
|
||||
rpath := r.jsonPath[locationIndex]
|
||||
@ -935,7 +955,12 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
|
||||
// Now actually delete the layers
|
||||
for _, layer := range layersToDelete {
|
||||
logrus.Warnf("Found incomplete layer %q, deleting it", layer.ID)
|
||||
err := r.deleteInternal(layer.ID)
|
||||
cleanFunctions, err := r.internalDelete(layer.ID)
|
||||
defer func() {
|
||||
if err := tempdir.CleanupTemporaryDirectories(cleanFunctions...); err != nil {
|
||||
logrus.Errorf("Error cleaning up temporary directories: %v", err)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
// Don't return the error immediately, because deleteInternal does not saveLayers();
|
||||
// Even if deleting one incomplete layer fails, call saveLayers() so that other possible successfully
|
||||
@ -1334,7 +1359,7 @@ func (r *layerStore) PutAdditionalLayer(id string, parentLayer *Layer, names []s
|
||||
r.bytocsum[layer.TOCDigest] = append(r.bytocsum[layer.TOCDigest], layer.ID)
|
||||
}
|
||||
if err := r.saveFor(layer); err != nil {
|
||||
if e := r.Delete(layer.ID); e != nil {
|
||||
if e := r.deleteWhileHoldingLock(layer.ID); e != nil {
|
||||
logrus.Errorf("While recovering from a failure to save layers, error deleting layer %#v: %v", id, e)
|
||||
}
|
||||
return nil, err
|
||||
@ -1469,7 +1494,7 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
|
||||
if cleanupFailureContext == "" {
|
||||
cleanupFailureContext = "unknown: cleanupFailureContext not set at the failure site"
|
||||
}
|
||||
if e := r.Delete(id); e != nil {
|
||||
if e := r.deleteWhileHoldingLock(id); e != nil {
|
||||
logrus.Errorf("While recovering from a failure (%s), error deleting layer %#v: %v", cleanupFailureContext, id, e)
|
||||
}
|
||||
}
|
||||
@ -1920,13 +1945,15 @@ func layerHasIncompleteFlag(layer *Layer) bool {
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
func (r *layerStore) deleteInternal(id string) error {
|
||||
// Caller MUST run all returned cleanup functions after this, EVEN IF the function returns an error.
|
||||
// Ideally outside of the startWriting.
|
||||
func (r *layerStore) internalDelete(id string) ([]tempdir.CleanupTempDirFunc, error) {
|
||||
if !r.lockfile.IsReadWrite() {
|
||||
return fmt.Errorf("not allowed to delete layers at %q: %w", r.layerdir, ErrStoreIsReadOnly)
|
||||
return nil, fmt.Errorf("not allowed to delete layers at %q: %w", r.layerdir, ErrStoreIsReadOnly)
|
||||
}
|
||||
layer, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return ErrLayerUnknown
|
||||
return nil, ErrLayerUnknown
|
||||
}
|
||||
// Ensure that if we are interrupted, the layer will be cleaned up.
|
||||
if !layerHasIncompleteFlag(layer) {
|
||||
@ -1935,16 +1962,30 @@ func (r *layerStore) deleteInternal(id string) error {
|
||||
}
|
||||
layer.Flags[incompleteFlag] = true
|
||||
if err := r.saveFor(layer); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// We never unset incompleteFlag; below, we remove the entire object from r.layers.
|
||||
id = layer.ID
|
||||
if err := r.driver.Remove(id); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
tempDirectory, err := tempdir.NewTempDir(filepath.Join(r.layerdir, tempDirPath))
|
||||
cleanFunctions := []tempdir.CleanupTempDirFunc{}
|
||||
cleanFunctions = append(cleanFunctions, tempDirectory.Cleanup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id = layer.ID
|
||||
cleanFunc, err := r.driver.DeferredRemove(id)
|
||||
cleanFunctions = append(cleanFunctions, cleanFunc)
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return cleanFunctions, err
|
||||
}
|
||||
|
||||
cleanFunctions = append(cleanFunctions, tempDirectory.Cleanup)
|
||||
if err := tempDirectory.StageDeletion(r.tspath(id)); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return cleanFunctions, err
|
||||
}
|
||||
if err := tempDirectory.StageDeletion(r.datadir(id)); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return cleanFunctions, err
|
||||
}
|
||||
os.Remove(r.tspath(id))
|
||||
os.RemoveAll(r.datadir(id))
|
||||
delete(r.byid, id)
|
||||
for _, name := range layer.Names {
|
||||
delete(r.byname, name)
|
||||
@ -1968,7 +2009,7 @@ func (r *layerStore) deleteInternal(id string) error {
|
||||
}) {
|
||||
selinux.ReleaseLabel(mountLabel)
|
||||
}
|
||||
return nil
|
||||
return cleanFunctions, nil
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
@ -1988,10 +2029,20 @@ func (r *layerStore) deleteInDigestMap(id string) {
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
func (r *layerStore) Delete(id string) error {
|
||||
// This is soft-deprecated and should not have any new callers; use deferredDelete instead.
|
||||
func (r *layerStore) deleteWhileHoldingLock(id string) error {
|
||||
cleanupFunctions, deferErr := r.deferredDelete(id)
|
||||
cleanupErr := tempdir.CleanupTemporaryDirectories(cleanupFunctions...)
|
||||
return errors.Join(deferErr, cleanupErr)
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
// Caller MUST run all returned cleanup functions after this, EVEN IF the function returns an error.
|
||||
// Ideally outside of the startWriting.
|
||||
func (r *layerStore) deferredDelete(id string) ([]tempdir.CleanupTempDirFunc, error) {
|
||||
layer, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return ErrLayerUnknown
|
||||
return nil, ErrLayerUnknown
|
||||
}
|
||||
id = layer.ID
|
||||
// The layer may already have been explicitly unmounted, but if not, we
|
||||
@ -2003,13 +2054,14 @@ func (r *layerStore) Delete(id string) error {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := r.deleteInternal(id); err != nil {
|
||||
return err
|
||||
cleanFunctions, err := r.internalDelete(id)
|
||||
if err != nil {
|
||||
return cleanFunctions, err
|
||||
}
|
||||
return r.saveFor(layer)
|
||||
return cleanFunctions, r.saveFor(layer)
|
||||
}
|
||||
|
||||
// Requires startReading or startWriting.
|
||||
@ -2039,7 +2091,7 @@ func (r *layerStore) Wipe() error {
|
||||
return r.byid[ids[i]].Created.After(r.byid[ids[j]].Created)
|
||||
})
|
||||
for _, id := range ids {
|
||||
if err := r.Delete(id); err != nil {
|
||||
if err := r.deleteWhileHoldingLock(id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -2571,7 +2623,7 @@ func (r *layerStore) applyDiffFromStagingDirectory(id string, diffOutput *driver
|
||||
}
|
||||
for k, v := range diffOutput.BigData {
|
||||
if err := r.SetBigData(id, k, bytes.NewReader(v)); err != nil {
|
||||
if err2 := r.Delete(id); err2 != nil {
|
||||
if err2 := r.deleteWhileHoldingLock(id); err2 != nil {
|
||||
logrus.Errorf("While recovering from a failure to set big data, error deleting layer %#v: %v", id, err2)
|
||||
}
|
||||
return err
|
||||
|
57
vendor/github.com/containers/storage/store.go
generated
vendored
57
vendor/github.com/containers/storage/store.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
||||
|
||||
drivers "github.com/containers/storage/drivers"
|
||||
"github.com/containers/storage/internal/dedup"
|
||||
"github.com/containers/storage/internal/tempdir"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/directory"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
@ -1758,7 +1759,7 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore roImageStore, rlst
|
||||
}
|
||||
// By construction, createMappedLayer can only be true if ristore == s.imageStore.
|
||||
if err = s.imageStore.addMappedTopLayer(image.ID, mappedLayer.ID); err != nil {
|
||||
if err2 := rlstore.Delete(mappedLayer.ID); err2 != nil {
|
||||
if err2 := rlstore.deleteWhileHoldingLock(mappedLayer.ID); err2 != nil {
|
||||
err = fmt.Errorf("deleting layer %q: %v: %w", mappedLayer.ID, err2, err)
|
||||
}
|
||||
return nil, fmt.Errorf("registering ID-mapped layer with image %q: %w", image.ID, err)
|
||||
@ -1943,7 +1944,7 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
|
||||
}
|
||||
container, err := s.containerStore.create(id, names, imageID, layer, &options)
|
||||
if err != nil || container == nil {
|
||||
if err2 := rlstore.Delete(layer); err2 != nil {
|
||||
if err2 := rlstore.deleteWhileHoldingLock(layer); err2 != nil {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("deleting layer %#v: %w", layer, err2)
|
||||
} else {
|
||||
@ -2540,7 +2541,13 @@ func (s *store) Lookup(name string) (string, error) {
|
||||
return "", ErrLayerUnknown
|
||||
}
|
||||
|
||||
func (s *store) DeleteLayer(id string) error {
|
||||
func (s *store) DeleteLayer(id string) (retErr error) {
|
||||
cleanupFunctions := []tempdir.CleanupTempDirFunc{}
|
||||
defer func() {
|
||||
if cleanupErr := tempdir.CleanupTemporaryDirectories(cleanupFunctions...); cleanupErr != nil {
|
||||
retErr = errors.Join(cleanupErr, retErr)
|
||||
}
|
||||
}()
|
||||
return s.writeToAllStores(func(rlstore rwLayerStore) error {
|
||||
if rlstore.Exists(id) {
|
||||
if l, err := rlstore.Get(id); err != nil {
|
||||
@ -2574,7 +2581,9 @@ func (s *store) DeleteLayer(id string) error {
|
||||
return fmt.Errorf("layer %v used by container %v: %w", id, container.ID, ErrLayerUsedByContainer)
|
||||
}
|
||||
}
|
||||
if err := rlstore.Delete(id); err != nil {
|
||||
cf, err := rlstore.deferredDelete(id)
|
||||
cleanupFunctions = append(cleanupFunctions, cf...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete layer %v: %w", id, err)
|
||||
}
|
||||
|
||||
@ -2591,8 +2600,14 @@ func (s *store) DeleteLayer(id string) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) {
|
||||
func (s *store) DeleteImage(id string, commit bool) (layers []string, retErr error) {
|
||||
layersToRemove := []string{}
|
||||
cleanupFunctions := []tempdir.CleanupTempDirFunc{}
|
||||
defer func() {
|
||||
if cleanupErr := tempdir.CleanupTemporaryDirectories(cleanupFunctions...); cleanupErr != nil {
|
||||
retErr = errors.Join(cleanupErr, retErr)
|
||||
}
|
||||
}()
|
||||
if err := s.writeToAllStores(func(rlstore rwLayerStore) error {
|
||||
// Delete image from all available imagestores configured to be used.
|
||||
imageFound := false
|
||||
@ -2698,7 +2713,9 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error)
|
||||
}
|
||||
if commit {
|
||||
for _, layer := range layersToRemove {
|
||||
if err = rlstore.Delete(layer); err != nil {
|
||||
cf, err := rlstore.deferredDelete(layer)
|
||||
cleanupFunctions = append(cleanupFunctions, cf...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -2710,7 +2727,13 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error)
|
||||
return layersToRemove, nil
|
||||
}
|
||||
|
||||
func (s *store) DeleteContainer(id string) error {
|
||||
func (s *store) DeleteContainer(id string) (retErr error) {
|
||||
cleanupFunctions := []tempdir.CleanupTempDirFunc{}
|
||||
defer func() {
|
||||
if cleanupErr := tempdir.CleanupTemporaryDirectories(cleanupFunctions...); cleanupErr != nil {
|
||||
retErr = errors.Join(cleanupErr, retErr)
|
||||
}
|
||||
}()
|
||||
return s.writeToAllStores(func(rlstore rwLayerStore) error {
|
||||
if !s.containerStore.Exists(id) {
|
||||
return ErrNotAContainer
|
||||
@ -2726,7 +2749,9 @@ func (s *store) DeleteContainer(id string) error {
|
||||
// the container record that refers to it, effectively losing
|
||||
// track of it
|
||||
if rlstore.Exists(container.LayerID) {
|
||||
if err := rlstore.Delete(container.LayerID); err != nil {
|
||||
cf, err := rlstore.deferredDelete(container.LayerID)
|
||||
cleanupFunctions = append(cleanupFunctions, cf...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -2752,12 +2777,20 @@ func (s *store) DeleteContainer(id string) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *store) Delete(id string) error {
|
||||
func (s *store) Delete(id string) (retErr error) {
|
||||
cleanupFunctions := []tempdir.CleanupTempDirFunc{}
|
||||
defer func() {
|
||||
if cleanupErr := tempdir.CleanupTemporaryDirectories(cleanupFunctions...); cleanupErr != nil {
|
||||
retErr = errors.Join(cleanupErr, retErr)
|
||||
}
|
||||
}()
|
||||
return s.writeToAllStores(func(rlstore rwLayerStore) error {
|
||||
if s.containerStore.Exists(id) {
|
||||
if container, err := s.containerStore.Get(id); err == nil {
|
||||
if rlstore.Exists(container.LayerID) {
|
||||
if err = rlstore.Delete(container.LayerID); err != nil {
|
||||
cf, err := rlstore.deferredDelete(container.LayerID)
|
||||
cleanupFunctions = append(cleanupFunctions, cf...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = s.containerStore.Delete(id); err != nil {
|
||||
@ -2781,7 +2814,9 @@ func (s *store) Delete(id string) error {
|
||||
return s.imageStore.Delete(id)
|
||||
}
|
||||
if rlstore.Exists(id) {
|
||||
return rlstore.Delete(id)
|
||||
cf, err := rlstore.deferredDelete(id)
|
||||
cleanupFunctions = append(cleanupFunctions, cf...)
|
||||
return err
|
||||
}
|
||||
return ErrLayerUnknown
|
||||
})
|
||||
|
2
vendor/github.com/containers/storage/userns.go
generated
vendored
2
vendor/github.com/containers/storage/userns.go
generated
vendored
@ -202,7 +202,7 @@ outer:
|
||||
return 0, err
|
||||
}
|
||||
defer func() {
|
||||
if err2 := rlstore.Delete(clayer.ID); err2 != nil {
|
||||
if err2 := rlstore.deleteWhileHoldingLock(clayer.ID); err2 != nil {
|
||||
if retErr == nil {
|
||||
retErr = fmt.Errorf("deleting temporary layer %#v: %w", clayer.ID, err2)
|
||||
} else {
|
||||
|
3
vendor/github.com/docker/docker/api/swagger.yaml
generated
vendored
3
vendor/github.com/docker/docker/api/swagger.yaml
generated
vendored
@ -2913,7 +2913,8 @@ definitions:
|
||||
be used. If multiple endpoints have the same priority, endpoints are
|
||||
lexicographically sorted based on their network name, and the one
|
||||
that sorts first is picked.
|
||||
type: "number"
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example:
|
||||
- 10
|
||||
|
||||
|
9
vendor/modules.txt
vendored
9
vendor/modules.txt
vendored
@ -141,7 +141,7 @@ github.com/containers/buildah/pkg/sshagent
|
||||
github.com/containers/buildah/pkg/util
|
||||
github.com/containers/buildah/pkg/volumes
|
||||
github.com/containers/buildah/util
|
||||
# github.com/containers/common v0.63.2-0.20250707185859-2b4e95a951de
|
||||
# github.com/containers/common v0.63.2-0.20250711144526-f3f68c4e79f5
|
||||
## explicit; go 1.23.3
|
||||
github.com/containers/common/internal
|
||||
github.com/containers/common/internal/attributedstring
|
||||
@ -214,7 +214,7 @@ github.com/containers/conmon/runner/config
|
||||
# github.com/containers/gvisor-tap-vsock v0.8.6
|
||||
## explicit; go 1.23.0
|
||||
github.com/containers/gvisor-tap-vsock/pkg/types
|
||||
# github.com/containers/image/v5 v5.35.1-0.20250707180819-778317a88563
|
||||
# github.com/containers/image/v5 v5.35.1-0.20250714114753-9e95082de671
|
||||
## explicit; go 1.23.3
|
||||
github.com/containers/image/v5/copy
|
||||
github.com/containers/image/v5/directory
|
||||
@ -324,7 +324,7 @@ github.com/containers/psgo/internal/dev
|
||||
github.com/containers/psgo/internal/host
|
||||
github.com/containers/psgo/internal/proc
|
||||
github.com/containers/psgo/internal/process
|
||||
# github.com/containers/storage v1.58.1-0.20250701152554-3aa733962202
|
||||
# github.com/containers/storage v1.58.1-0.20250711145627-2b18ddcfafca
|
||||
## explicit; go 1.23.0
|
||||
github.com/containers/storage
|
||||
github.com/containers/storage/drivers
|
||||
@ -341,6 +341,7 @@ github.com/containers/storage/drivers/zfs
|
||||
github.com/containers/storage/internal/dedup
|
||||
github.com/containers/storage/internal/rawfilelock
|
||||
github.com/containers/storage/internal/staging_lockfile
|
||||
github.com/containers/storage/internal/tempdir
|
||||
github.com/containers/storage/pkg/archive
|
||||
github.com/containers/storage/pkg/chrootarchive
|
||||
github.com/containers/storage/pkg/chunked
|
||||
@ -428,7 +429,7 @@ github.com/distribution/reference
|
||||
## explicit
|
||||
github.com/docker/distribution/registry/api/errcode
|
||||
github.com/docker/distribution/registry/api/v2
|
||||
# github.com/docker/docker v28.3.1+incompatible
|
||||
# github.com/docker/docker v28.3.2+incompatible
|
||||
## explicit
|
||||
github.com/docker/docker/api
|
||||
github.com/docker/docker/api/types
|
||||
|
Reference in New Issue
Block a user