mirror of
https://github.com/containers/podman.git
synced 2025-10-17 11:14:40 +08:00
Bump to latest c/storage main
Includes a patch for quotas that is needed for this PR. Signed-off-by: Matt Heon <mheon@redhat.com>
This commit is contained in:
15
vendor/github.com/containers/storage/drivers/quota/projectquota_supported.go
generated
vendored
15
vendor/github.com/containers/storage/drivers/quota/projectquota_supported.go
generated
vendored
@ -190,7 +190,8 @@ func NewControl(basePath string) (*Control, error) {
|
||||
}
|
||||
|
||||
// SetQuota - assign a unique project id to directory and set the quota limits
|
||||
// for that project id
|
||||
// for that project id.
|
||||
// targetPath must exist, must be a directory, and must be empty.
|
||||
func (q *Control) SetQuota(targetPath string, quota Quota) error {
|
||||
var projectID uint32
|
||||
value, ok := q.quotas.Load(targetPath)
|
||||
@ -200,10 +201,20 @@ func (q *Control) SetQuota(targetPath string, quota Quota) error {
|
||||
if !ok {
|
||||
projectID = q.nextProjectID
|
||||
|
||||
// The directory we are setting an ID on must be empty, as
|
||||
// the ID will not be propagated to pre-existing subdirectories.
|
||||
dents, err := os.ReadDir(targetPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading directory %s: %w", targetPath, err)
|
||||
}
|
||||
if len(dents) > 0 {
|
||||
return fmt.Errorf("can only set project ID on empty directories, %s is not empty", targetPath)
|
||||
}
|
||||
|
||||
//
|
||||
// assign project id to new container directory
|
||||
//
|
||||
err := setProjectID(targetPath, projectID)
|
||||
err = setProjectID(targetPath, projectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
70
vendor/github.com/containers/storage/layers.go
generated
vendored
70
vendor/github.com/containers/storage/layers.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"math/bits"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
@ -46,11 +47,13 @@ const (
|
||||
|
||||
type layerLocations uint8
|
||||
|
||||
// The backing store is split in two json files, one (the volatile)
|
||||
// that is written without fsync() meaning it isn't as robust to
|
||||
// unclean shutdown
|
||||
// The backing store is split in three json files.
|
||||
// The volatile store is written without fsync() meaning it isn't as robust to unclean shutdown.
|
||||
// Optionally, an image store can be configured to store RO layers.
|
||||
// The stable store is used for the remaining layers that don't go into the other stores.
|
||||
const (
|
||||
stableLayerLocation layerLocations = 1 << iota
|
||||
imageStoreLayerLocation
|
||||
volatileLayerLocation
|
||||
|
||||
numLayerLocationIndex = iota
|
||||
@ -60,6 +63,10 @@ func layerLocationFromIndex(index int) layerLocations {
|
||||
return 1 << index
|
||||
}
|
||||
|
||||
func indexFromLayerLocation(location layerLocations) int {
|
||||
return bits.TrailingZeros(uint(location))
|
||||
}
|
||||
|
||||
// A Layer is a record of a copy-on-write layer that's stored by the lower
|
||||
// level graph driver.
|
||||
type Layer struct {
|
||||
@ -164,8 +171,8 @@ type Layer struct {
|
||||
// ReadOnly is true if this layer resides in a read-only layer store.
|
||||
ReadOnly bool `json:"-"`
|
||||
|
||||
// volatileStore is true if the container is from the volatile json file
|
||||
volatileStore bool `json:"-"`
|
||||
// location is the location of the store where the layer is present.
|
||||
location layerLocations `json:"-"`
|
||||
|
||||
// BigDataNames is a list of names of data items that we keep for the
|
||||
// convenience of the caller. They can be large, and are only in
|
||||
@ -430,14 +437,6 @@ type layerStore struct {
|
||||
driver drivers.Driver
|
||||
}
|
||||
|
||||
// The caller must hold r.inProcessLock for reading.
|
||||
func layerLocation(l *Layer) layerLocations {
|
||||
if l.volatileStore {
|
||||
return volatileLayerLocation
|
||||
}
|
||||
return stableLayerLocation
|
||||
}
|
||||
|
||||
func copyLayer(l *Layer) *Layer {
|
||||
return &Layer{
|
||||
ID: l.ID,
|
||||
@ -455,7 +454,7 @@ func copyLayer(l *Layer) *Layer {
|
||||
TOCDigest: l.TOCDigest,
|
||||
CompressionType: l.CompressionType,
|
||||
ReadOnly: l.ReadOnly,
|
||||
volatileStore: l.volatileStore,
|
||||
location: l.location,
|
||||
BigDataNames: copySlicePreferringNil(l.BigDataNames),
|
||||
Flags: copyMapPreferringNil(l.Flags),
|
||||
UIDMap: copySlicePreferringNil(l.UIDMap),
|
||||
@ -658,7 +657,11 @@ func (r *layerStore) layersModified() (lockfile.LastWrite, bool, error) {
|
||||
// modified manually, then we have to reload the storage in
|
||||
// any case.
|
||||
for locationIndex := 0; locationIndex < numLayerLocationIndex; locationIndex++ {
|
||||
info, err := os.Stat(r.jsonPath[locationIndex])
|
||||
rpath := r.jsonPath[locationIndex]
|
||||
if rpath == "" {
|
||||
continue
|
||||
}
|
||||
info, err := os.Stat(rpath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return lockfile.LastWrite{}, false, fmt.Errorf("stat layers file: %w", err)
|
||||
}
|
||||
@ -794,6 +797,9 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
|
||||
for locationIndex := 0; locationIndex < numLayerLocationIndex; locationIndex++ {
|
||||
location := layerLocationFromIndex(locationIndex)
|
||||
rpath := r.jsonPath[locationIndex]
|
||||
if rpath == "" {
|
||||
continue
|
||||
}
|
||||
info, err := os.Stat(rpath)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
@ -820,9 +826,7 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
|
||||
continue // skip invalid duplicated layer
|
||||
}
|
||||
// Remember where the layer came from
|
||||
if location == volatileLayerLocation {
|
||||
layer.volatileStore = true
|
||||
}
|
||||
layer.location = location
|
||||
layers = append(layers, layer)
|
||||
ids[layer.ID] = layer
|
||||
}
|
||||
@ -843,7 +847,7 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
|
||||
if conflict, ok := names[name]; ok {
|
||||
r.removeName(conflict, name)
|
||||
errorToResolveBySaving = ErrDuplicateLayerNames
|
||||
modifiedLocations |= layerLocation(conflict)
|
||||
modifiedLocations |= conflict.location
|
||||
}
|
||||
names[name] = layers[n]
|
||||
}
|
||||
@ -939,7 +943,7 @@ func (r *layerStore) load(lockedForWriting bool) (bool, error) {
|
||||
incompleteDeletionErrors = errors.Join(incompleteDeletionErrors,
|
||||
fmt.Errorf("deleting layer %#v: %w", layer.ID, err))
|
||||
}
|
||||
modifiedLocations |= layerLocation(layer)
|
||||
modifiedLocations |= layer.location
|
||||
}
|
||||
if err := r.saveLayers(modifiedLocations); err != nil {
|
||||
return false, err
|
||||
@ -1008,7 +1012,7 @@ func (r *layerStore) save(saveLocations layerLocations) error {
|
||||
// The caller must hold r.lockfile locked for writing.
|
||||
// The caller must hold r.inProcessLock for WRITING.
|
||||
func (r *layerStore) saveFor(modifiedLayer *Layer) error {
|
||||
return r.save(layerLocation(modifiedLayer))
|
||||
return r.save(modifiedLayer.location)
|
||||
}
|
||||
|
||||
// The caller must hold r.lockfile locked for writing.
|
||||
@ -1033,12 +1037,15 @@ func (r *layerStore) saveLayers(saveLocations layerLocations) error {
|
||||
continue
|
||||
}
|
||||
rpath := r.jsonPath[locationIndex]
|
||||
if rpath == "" {
|
||||
return fmt.Errorf("internal error: no path for location %v", location)
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(rpath), 0o700); err != nil {
|
||||
return err
|
||||
}
|
||||
subsetLayers := make([]*Layer, 0, len(r.layers))
|
||||
for _, layer := range r.layers {
|
||||
if layerLocation(layer) == location {
|
||||
if layer.location == location {
|
||||
subsetLayers = append(subsetLayers, layer)
|
||||
}
|
||||
}
|
||||
@ -1138,12 +1145,17 @@ func (s *store) newLayerStore(rundir, layerdir, imagedir string, driver drivers.
|
||||
if transient {
|
||||
volatileDir = rundir
|
||||
}
|
||||
layersImageDir := ""
|
||||
if imagedir != "" {
|
||||
layersImageDir = filepath.Join(imagedir, "layers.json")
|
||||
}
|
||||
rlstore := layerStore{
|
||||
lockfile: newMultipleLockFile(lockFiles...),
|
||||
mountsLockfile: mountsLockfile,
|
||||
rundir: rundir,
|
||||
jsonPath: [numLayerLocationIndex]string{
|
||||
filepath.Join(layerdir, "layers.json"),
|
||||
layersImageDir,
|
||||
filepath.Join(volatileDir, "volatile-layers.json"),
|
||||
},
|
||||
layerdir: layerdir,
|
||||
@ -1181,6 +1193,7 @@ func newROLayerStore(rundir string, layerdir string, driver drivers.Driver) (roL
|
||||
rundir: rundir,
|
||||
jsonPath: [numLayerLocationIndex]string{
|
||||
filepath.Join(layerdir, "layers.json"),
|
||||
"",
|
||||
filepath.Join(layerdir, "volatile-layers.json"),
|
||||
},
|
||||
layerdir: layerdir,
|
||||
@ -1329,6 +1342,17 @@ func (r *layerStore) PutAdditionalLayer(id string, parentLayer *Layer, names []s
|
||||
return copyLayer(layer), nil
|
||||
}
|
||||
|
||||
func (r *layerStore) pickStoreLocation(volatile, writeable bool) layerLocations {
|
||||
switch {
|
||||
case volatile:
|
||||
return volatileLayerLocation
|
||||
case !writeable && r.jsonPath[indexFromLayerLocation(imageStoreLayerLocation)] != "":
|
||||
return imageStoreLayerLocation
|
||||
default:
|
||||
return stableLayerLocation
|
||||
}
|
||||
}
|
||||
|
||||
// Requires startWriting.
|
||||
func (r *layerStore) create(id string, parentLayer *Layer, names []string, mountLabel string, options map[string]string, moreOptions *LayerOptions, writeable bool, diff io.Reader, slo *stagedLayerOptions) (layer *Layer, size int64, err error) {
|
||||
if moreOptions == nil {
|
||||
@ -1421,7 +1445,7 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
|
||||
UIDMap: copySlicePreferringNil(moreOptions.UIDMap),
|
||||
GIDMap: copySlicePreferringNil(moreOptions.GIDMap),
|
||||
BigDataNames: []string{},
|
||||
volatileStore: moreOptions.Volatile,
|
||||
location: r.pickStoreLocation(moreOptions.Volatile, writeable),
|
||||
}
|
||||
layer.Flags[incompleteFlag] = true
|
||||
|
||||
|
17
vendor/github.com/containers/storage/pkg/archive/archive.go
generated
vendored
17
vendor/github.com/containers/storage/pkg/archive/archive.go
generated
vendored
@ -16,6 +16,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containers/storage/pkg/fileutils"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
@ -67,6 +68,8 @@ type (
|
||||
CopyPass bool
|
||||
// ForceMask, if set, indicates the permission mask used for created files.
|
||||
ForceMask *os.FileMode
|
||||
// Timestamp, if set, will be set in each header as create/mod/access time
|
||||
Timestamp *time.Time
|
||||
}
|
||||
)
|
||||
|
||||
@ -494,15 +497,19 @@ type tarWriter struct {
|
||||
// from the traditional behavior/format to get features like subsecond
|
||||
// precision in timestamps.
|
||||
CopyPass bool
|
||||
|
||||
// Timestamp, if set, will be set in each header as create/mod/access time
|
||||
Timestamp *time.Time
|
||||
}
|
||||
|
||||
func newTarWriter(idMapping *idtools.IDMappings, writer io.Writer, chownOpts *idtools.IDPair) *tarWriter {
|
||||
func newTarWriter(idMapping *idtools.IDMappings, writer io.Writer, chownOpts *idtools.IDPair, timestamp *time.Time) *tarWriter {
|
||||
return &tarWriter{
|
||||
SeenFiles: make(map[uint64]string),
|
||||
TarWriter: tar.NewWriter(writer),
|
||||
Buffer: pools.BufioWriter32KPool.Get(nil),
|
||||
IDMappings: idMapping,
|
||||
ChownOpts: chownOpts,
|
||||
Timestamp: timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,6 +607,13 @@ func (ta *tarWriter) addFile(path, name string) error {
|
||||
hdr.Gname = ""
|
||||
}
|
||||
|
||||
// if override timestamp set, replace all times with this
|
||||
if ta.Timestamp != nil {
|
||||
hdr.ModTime = *ta.Timestamp
|
||||
hdr.AccessTime = *ta.Timestamp
|
||||
hdr.ChangeTime = *ta.Timestamp
|
||||
}
|
||||
|
||||
maybeTruncateHeaderModTime(hdr)
|
||||
|
||||
if ta.WhiteoutConverter != nil {
|
||||
@ -866,6 +880,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
|
||||
idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps),
|
||||
compressWriter,
|
||||
options.ChownOpts,
|
||||
options.Timestamp,
|
||||
)
|
||||
ta.WhiteoutConverter = GetWhiteoutConverter(options.WhiteoutFormat, options.WhiteoutData)
|
||||
ta.CopyPass = options.CopyPass
|
||||
|
2
vendor/github.com/containers/storage/pkg/archive/changes.go
generated
vendored
2
vendor/github.com/containers/storage/pkg/archive/changes.go
generated
vendored
@ -452,7 +452,7 @@ func ChangesSize(newDir string, changes []Change) int64 {
|
||||
func ExportChanges(dir string, changes []Change, uidMaps, gidMaps []idtools.IDMap) (io.ReadCloser, error) {
|
||||
reader, writer := io.Pipe()
|
||||
go func() {
|
||||
ta := newTarWriter(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer, nil)
|
||||
ta := newTarWriter(idtools.NewIDMappingsFromMaps(uidMaps, gidMaps), writer, nil, nil)
|
||||
|
||||
// this buffer is needed for the duration of this piped stream
|
||||
defer pools.BufioWriter32KPool.Put(ta.Buffer)
|
||||
|
Reference in New Issue
Block a user