Merge pull request #1195 from rhatdan/VENDOR

Update vendor containers/storage
This commit is contained in:
OpenShift Merge Robot 2022-10-25 07:41:48 -04:00 committed by GitHub
commit ba0f2825a0
22 changed files with 840 additions and 1749 deletions

View File

@ -9,7 +9,7 @@ require (
github.com/containernetworking/plugins v1.1.1
github.com/containers/image/v5 v5.23.1-0.20221015133641-1921a1993c67
github.com/containers/ocicrypt v1.1.6
github.com/containers/storage v1.43.1-0.20221017123904-a4d4fe98e37d
github.com/containers/storage v1.43.1-0.20221024131621-fae5bbf607fc
github.com/coreos/go-systemd/v22 v22.4.0
github.com/cyphar/filepath-securejoin v0.2.3
github.com/davecgh/go-spew v1.1.1

File diff suppressed because it is too large Load Diff

View File

@ -68,11 +68,24 @@ type Container struct {
// rwContainerStore provides bookkeeping for information about Containers.
type rwContainerStore interface {
fileBasedStore
metadataStore
containerBigDataStore
flaggableStore
// startWriting makes sure the store is fresh, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
startWriting() error
// stopWriting releases locks obtained by startWriting.
stopWriting()
// startReading makes sure the store is fresh, and locks it for reading.
// If this succeeds, the caller MUST call stopReading().
startReading() error
// stopReading releases locks obtained by startReading.
stopReading()
// Create creates a container that has a specified ID (or generates a
// random one if an empty value is supplied) and optional names,
// based on the specified image, using the specified layer as its
@ -163,6 +176,77 @@ func (c *Container) MountOpts() []string {
}
}
// startWritingWithReload makes sure the store is fresh if canReload, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
//
// This is an internal implementation detail of containerStore construction, every other caller
// should use startWriting() instead.
func (r *containerStore) startWritingWithReload(canReload bool) error {
r.lockfile.Lock()
succeeded := false
defer func() {
if !succeeded {
r.lockfile.Unlock()
}
}()
if canReload {
if err := r.ReloadIfChanged(); err != nil {
return err
}
}
succeeded = true
return nil
}
// startWriting makes sure the store is fresh, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
func (r *containerStore) startWriting() error {
return r.startWritingWithReload(true)
}
// stopWriting releases locks obtained by startWriting.
func (r *containerStore) stopWriting() {
r.lockfile.Unlock()
}
// startReading makes sure the store is fresh, and locks it for reading.
// If this succeeds, the caller MUST call stopReading().
func (r *containerStore) startReading() error {
r.lockfile.RLock()
succeeded := false
defer func() {
if !succeeded {
r.lockfile.Unlock()
}
}()
if err := r.ReloadIfChanged(); err != nil {
return err
}
succeeded = true
return nil
}
// stopReading releases locks obtained by startReading.
func (r *containerStore) stopReading() {
r.lockfile.Unlock()
}
// ReloadIfChanged reloads the contents of the store from disk if it is changed.
func (r *containerStore) ReloadIfChanged() error {
r.loadMut.Lock()
defer r.loadMut.Unlock()
modified, err := r.lockfile.Modified()
if err == nil && modified {
return r.Load()
}
return err
}
func (r *containerStore) Containers() ([]Container, error) {
containers := make([]Container, len(r.containers))
for i := range r.containers {
@ -183,6 +267,8 @@ func (r *containerStore) datapath(id, key string) string {
return filepath.Join(r.datadir(id), makeBigDataBaseName(key))
}
// Load reloads the contents of the store from disk. It should be called
// with the lock held.
func (r *containerStore) Load() error {
needSave := false
rpath := r.containerspath()
@ -221,8 +307,10 @@ func (r *containerStore) Load() error {
return nil
}
// Save saves the contents of the store to disk. It should be called with
// the lock held.
func (r *containerStore) Save() error {
if !r.Locked() {
if !r.lockfile.Locked() {
return errors.New("container store is not locked")
}
rpath := r.containerspath()
@ -236,7 +324,7 @@ func (r *containerStore) Save() error {
if err := ioutils.AtomicWriteFile(rpath, jdata, 0600); err != nil {
return err
}
return r.Touch()
return r.lockfile.Touch()
}
func newContainerStore(dir string) (rwContainerStore, error) {
@ -255,8 +343,10 @@ func newContainerStore(dir string) (rwContainerStore, error) {
bylayer: make(map[string]*Container),
byname: make(map[string]*Container),
}
cstore.Lock()
defer cstore.Unlock()
if err := cstore.startWritingWithReload(false); err != nil {
return nil, err
}
defer cstore.stopWriting()
if err := cstore.Load(); err != nil {
return nil, err
}
@ -595,46 +685,3 @@ func (r *containerStore) Wipe() error {
}
return nil
}
func (r *containerStore) Lock() {
r.lockfile.Lock()
}
func (r *containerStore) RLock() {
r.lockfile.RLock()
}
func (r *containerStore) Unlock() {
r.lockfile.Unlock()
}
func (r *containerStore) Touch() error {
return r.lockfile.Touch()
}
func (r *containerStore) Modified() (bool, error) {
return r.lockfile.Modified()
}
func (r *containerStore) IsReadWrite() bool {
return r.lockfile.IsReadWrite()
}
func (r *containerStore) TouchedSince(when time.Time) bool {
return r.lockfile.TouchedSince(when)
}
func (r *containerStore) Locked() bool {
return r.lockfile.Locked()
}
func (r *containerStore) ReloadIfChanged() error {
r.loadMut.Lock()
defer r.loadMut.Unlock()
modified, err := r.Modified()
if err == nil && modified {
return r.Load()
}
return err
}

View File

@ -89,7 +89,7 @@ const (
// is true (512 is a buffer for label metadata, 128 is the
// number of lowers we want to be able to use without having
// to use bind mounts to get all the way to the kernel limit).
// ((idLength + len(linkDir) + 1) * maxDepth) <= (pageSize - 512)
// ((idLength + len(linkDir) + 1) * 128) <= (pageSize - 512)
idLength = 26
)

View File

@ -96,10 +96,16 @@ type Image struct {
// roImageStore provides bookkeeping for information about Images.
type roImageStore interface {
roFileBasedStore
roMetadataStore
roBigDataStore
// startReading makes sure the store is fresh, and locks it for reading.
// If this succeeds, the caller MUST call stopReading().
startReading() error
// stopReading releases locks obtained by startReading.
stopReading()
// Exists checks if there is an image with the given ID or name.
Exists(id string) bool
@ -119,11 +125,17 @@ type roImageStore interface {
// rwImageStore provides bookkeeping for information about Images.
type rwImageStore interface {
roImageStore
rwFileBasedStore
rwMetadataStore
rwImageBigDataStore
flaggableStore
// startWriting makes sure the store is fresh, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
startWriting() error
// stopWriting releases locks obtained by startWriting.
stopWriting()
// Create creates an image that has a specified ID (or a random one) and
// optional names, using the specified layer as its topmost (hopefully
// read-only) layer. That layer can be referenced by multiple images.
@ -182,6 +194,88 @@ func copyImageSlice(slice []*Image) []*Image {
return nil
}
// startWritingWithReload makes sure the store is fresh if canReload, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
//
// This is an internal implementation detail of imageStore construction, every other caller
// should use startReading() instead.
func (r *imageStore) startWritingWithReload(canReload bool) error {
r.lockfile.Lock()
succeeded := false
defer func() {
if !succeeded {
r.lockfile.Unlock()
}
}()
if canReload {
if err := r.ReloadIfChanged(); err != nil {
return err
}
}
succeeded = true
return nil
}
// startWriting makes sure the store is fresh, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
func (r *imageStore) startWriting() error {
return r.startWritingWithReload(true)
}
// stopWriting releases locks obtained by startWriting.
func (r *imageStore) stopWriting() {
r.lockfile.Unlock()
}
// startReadingWithReload makes sure the store is fresh if canReload, and locks it for reading.
// If this succeeds, the caller MUST call stopReading().
//
// This is an internal implementation detail of imageStore construction, every other caller
// should use startReading() instead.
func (r *imageStore) startReadingWithReload(canReload bool) error {
r.lockfile.RLock()
succeeded := false
defer func() {
if !succeeded {
r.lockfile.Unlock()
}
}()
if canReload {
if err := r.ReloadIfChanged(); err != nil {
return err
}
}
succeeded = true
return nil
}
// startReading makes sure the store is fresh, and locks it for reading.
// If this succeeds, the caller MUST call stopReading().
func (r *imageStore) startReading() error {
return r.startReadingWithReload(true)
}
// stopReading releases locks obtained by startReading.
func (r *imageStore) stopReading() {
r.lockfile.Unlock()
}
// ReloadIfChanged reloads the contents of the store from disk if it is changed.
func (r *imageStore) ReloadIfChanged() error {
r.loadMut.Lock()
defer r.loadMut.Unlock()
modified, err := r.lockfile.Modified()
if err == nil && modified {
return r.Load()
}
return err
}
func (r *imageStore) Images() ([]Image, error) {
images := make([]Image, len(r.images))
for i := range r.images {
@ -242,6 +336,8 @@ func (i *Image) recomputeDigests() error {
return nil
}
// Load reloads the contents of the store from disk. It should be called
// with the lock held.
func (r *imageStore) Load() error {
shouldSave := false
rpath := r.imagespath()
@ -277,10 +373,10 @@ func (r *imageStore) Load() error {
list := digests[digest]
digests[digest] = append(list, image)
}
image.ReadOnly = !r.IsReadWrite()
image.ReadOnly = !r.lockfile.IsReadWrite()
}
}
if shouldSave && (!r.IsReadWrite() || !r.Locked()) {
if shouldSave && (!r.lockfile.IsReadWrite() || !r.lockfile.Locked()) {
return ErrDuplicateImageNames
}
r.images = images
@ -294,11 +390,13 @@ func (r *imageStore) Load() error {
return nil
}
// Save saves the contents of the store to disk. It should be called with
// the lock held.
func (r *imageStore) Save() error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to modify the image store at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
if !r.Locked() {
if !r.lockfile.Locked() {
return errors.New("image store is not locked for writing")
}
rpath := r.imagespath()
@ -312,7 +410,7 @@ func (r *imageStore) Save() error {
if err := ioutils.AtomicWriteFile(rpath, jdata, 0600); err != nil {
return err
}
return r.Touch()
return r.lockfile.Touch()
}
func newImageStore(dir string) (rwImageStore, error) {
@ -331,8 +429,10 @@ func newImageStore(dir string) (rwImageStore, error) {
byname: make(map[string]*Image),
bydigest: make(map[digest.Digest][]*Image),
}
istore.Lock()
defer istore.Unlock()
if err := istore.startWritingWithReload(false); err != nil {
return nil, err
}
defer istore.stopWriting()
if err := istore.Load(); err != nil {
return nil, err
}
@ -352,8 +452,10 @@ func newROImageStore(dir string) (roImageStore, error) {
byname: make(map[string]*Image),
bydigest: make(map[digest.Digest][]*Image),
}
istore.RLock()
defer istore.Unlock()
if err := istore.startReadingWithReload(false); err != nil {
return nil, err
}
defer istore.stopReading()
if err := istore.Load(); err != nil {
return nil, err
}
@ -373,7 +475,7 @@ func (r *imageStore) lookup(id string) (*Image, bool) {
}
func (r *imageStore) ClearFlag(id string, flag string) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to clear flags on images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
image, ok := r.lookup(id)
@ -385,7 +487,7 @@ func (r *imageStore) ClearFlag(id string, flag string) error {
}
func (r *imageStore) SetFlag(id string, flag string, value interface{}) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to set flags on images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
image, ok := r.lookup(id)
@ -400,7 +502,7 @@ func (r *imageStore) SetFlag(id string, flag string, value interface{}) error {
}
func (r *imageStore) Create(id string, names []string, layer, metadata string, created time.Time, searchableDigest digest.Digest) (image *Image, err error) {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return nil, fmt.Errorf("not allowed to create new images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
if id == "" {
@ -487,7 +589,7 @@ func (r *imageStore) Metadata(id string) (string, error) {
}
func (r *imageStore) SetMetadata(id, metadata string) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to modify image metadata at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
if image, ok := r.lookup(id); ok {
@ -506,7 +608,7 @@ func (i *Image) addNameToHistory(name string) {
}
func (r *imageStore) updateNames(id string, names []string, op updateNameOperation) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to change image name assignments at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
image, ok := r.lookup(id)
@ -533,7 +635,7 @@ func (r *imageStore) updateNames(id string, names []string, op updateNameOperati
}
func (r *imageStore) Delete(id string) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to delete images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
image, ok := r.lookup(id)
@ -669,7 +771,7 @@ func (r *imageStore) SetBigData(id, key string, data []byte, digestManifest func
if key == "" {
return fmt.Errorf("can't set empty name for image big data item: %w", ErrInvalidBigDataName)
}
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to save data items associated with images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
image, ok := r.lookup(id)
@ -750,7 +852,7 @@ func (r *imageStore) SetBigData(id, key string, data []byte, digestManifest func
}
func (r *imageStore) Wipe() error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to delete images at %q: %w", r.imagespath(), ErrStoreIsReadOnly)
}
ids := make([]string, 0, len(r.byid))
@ -764,46 +866,3 @@ func (r *imageStore) Wipe() error {
}
return nil
}
func (r *imageStore) Lock() {
r.lockfile.Lock()
}
func (r *imageStore) RLock() {
r.lockfile.RLock()
}
func (r *imageStore) Unlock() {
r.lockfile.Unlock()
}
func (r *imageStore) Touch() error {
return r.lockfile.Touch()
}
func (r *imageStore) Modified() (bool, error) {
return r.lockfile.Modified()
}
func (r *imageStore) IsReadWrite() bool {
return r.lockfile.IsReadWrite()
}
func (r *imageStore) TouchedSince(when time.Time) bool {
return r.lockfile.TouchedSince(when)
}
func (r *imageStore) Locked() bool {
return r.lockfile.Locked()
}
func (r *imageStore) ReloadIfChanged() error {
r.loadMut.Lock()
defer r.loadMut.Unlock()
modified, err := r.Modified()
if err == nil && modified {
return r.Load()
}
return err
}

View File

@ -141,10 +141,16 @@ type DiffOptions struct {
// name, and keeping track of parent-child relationships, along with a list of
// all known layers.
type roLayerStore interface {
roFileBasedStore
roMetadataStore
roLayerBigDataStore
// startReading makes sure the store is fresh, and locks it for reading.
// If this succeeds, the caller MUST call stopReading().
startReading() error
// stopReading releases locks obtained by startReading.
stopReading()
// Exists checks if a layer with the specified name or ID is known.
Exists(id string) bool
@ -194,11 +200,17 @@ type roLayerStore interface {
// all known layers.
type rwLayerStore interface {
roLayerStore
rwFileBasedStore
rwMetadataStore
flaggableStore
rwLayerBigDataStore
// startWriting makes sure the store is fresh, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
startWriting() error
// stopWriting releases locks obtained by startWriting.
stopWriting()
// Create creates a new layer, optionally giving it a specified ID rather than
// a randomly-generated one, either inheriting data from another specified
// layer or the empty base layer. The new layer can optionally be given names
@ -304,6 +316,122 @@ func copyLayer(l *Layer) *Layer {
}
}
// startWritingWithReload makes sure the store is fresh if canReload, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
//
// This is an internal implementation detail of layerStore construction, every other caller
// should use startWriting() instead.
func (r *layerStore) startWritingWithReload(canReload bool) error {
r.lockfile.Lock()
succeeded := false
defer func() {
if !succeeded {
r.lockfile.Unlock()
}
}()
if canReload {
if err := r.ReloadIfChanged(); err != nil {
return err
}
}
succeeded = true
return nil
}
// startWriting makes sure the store is fresh, and locks it for writing.
// If this succeeds, the caller MUST call stopWriting().
func (r *layerStore) startWriting() error {
return r.startWritingWithReload(true)
}
// stopWriting releases locks obtained by startWriting.
func (r *layerStore) stopWriting() {
r.lockfile.Unlock()
}
// startReadingWithReload makes sure the store is fresh if canReload, and locks it for reading.
// If this succeeds, the caller MUST call stopReading().
//
// This is an internal implementation detail of layerStore construction, every other caller
// should use startReading() instead.
func (r *layerStore) startReadingWithReload(canReload bool) error {
r.lockfile.RLock()
succeeded := false
defer func() {
if !succeeded {
r.lockfile.Unlock()
}
}()
if canReload {
if err := r.ReloadIfChanged(); err != nil {
return err
}
}
succeeded = true
return nil
}
// startReading makes sure the store is fresh, and locks it for reading.
// If this succeeds, the caller MUST call stopReading().
func (r *layerStore) startReading() error {
return r.startReadingWithReload(true)
}
// stopReading releases locks obtained by startReading.
func (r *layerStore) stopReading() {
r.lockfile.Unlock()
}
// Modified() checks if the most recent writer was a party other than the
// last recorded writer. It should only be called with the lock held.
func (r *layerStore) Modified() (bool, error) {
var mmodified, tmodified bool
lmodified, err := r.lockfile.Modified()
if err != nil {
return lmodified, err
}
if r.lockfile.IsReadWrite() {
r.mountsLockfile.RLock()
defer r.mountsLockfile.Unlock()
mmodified, err = r.mountsLockfile.Modified()
if err != nil {
return lmodified, err
}
}
if lmodified || mmodified {
return true, nil
}
// If the layers.json file has been modified manually, then we have to
// reload the storage in any case.
info, err := os.Stat(r.layerspath())
if err != nil && !os.IsNotExist(err) {
return false, fmt.Errorf("stat layers file: %w", err)
}
if info != nil {
tmodified = info.ModTime() != r.layerspathModified
}
return tmodified, nil
}
// ReloadIfChanged reloads the contents of the store from disk if it is changed.
func (r *layerStore) ReloadIfChanged() error {
r.loadMut.Lock()
defer r.loadMut.Unlock()
modified, err := r.Modified()
if err == nil && modified {
return r.Load()
}
return err
}
func (r *layerStore) Layers() ([]Layer, error) {
layers := make([]Layer, len(r.layers))
for i := range r.layers {
@ -320,6 +448,8 @@ func (r *layerStore) layerspath() string {
return filepath.Join(r.layerdir, "layers.json")
}
// Load reloads the contents of the store from disk. It should be called
// with the lock held.
func (r *layerStore) Load() error {
shouldSave := false
rpath := r.layerspath()
@ -341,7 +471,7 @@ func (r *layerStore) Load() error {
names := make(map[string]*Layer)
compressedsums := make(map[digest.Digest][]string)
uncompressedsums := make(map[digest.Digest][]string)
if r.IsReadWrite() {
if r.lockfile.IsReadWrite() {
selinux.ClearLabels()
}
if err = json.Unmarshal(data, &layers); len(data) == 0 || err == nil {
@ -365,11 +495,11 @@ func (r *layerStore) Load() error {
if layer.MountLabel != "" {
selinux.ReserveLabel(layer.MountLabel)
}
layer.ReadOnly = !r.IsReadWrite()
layer.ReadOnly = !r.lockfile.IsReadWrite()
}
err = nil
}
if shouldSave && (!r.IsReadWrite() || !r.Locked()) {
if shouldSave && (!r.lockfile.IsReadWrite() || !r.lockfile.Locked()) {
return ErrDuplicateLayerNames
}
r.layers = layers
@ -380,7 +510,7 @@ func (r *layerStore) Load() error {
r.byuncompressedsum = uncompressedsums
// Load and merge information about which layers are mounted, and where.
if r.IsReadWrite() {
if r.lockfile.IsReadWrite() {
r.mountsLockfile.RLock()
defer r.mountsLockfile.Unlock()
if err = r.loadMounts(); err != nil {
@ -390,7 +520,7 @@ func (r *layerStore) Load() error {
// Last step: as were writable, try to remove anything that a previous
// user of this storage area marked for deletion but didn't manage to
// actually delete.
if r.Locked() {
if r.lockfile.Locked() {
for _, layer := range r.layers {
if layer.Flags == nil {
layer.Flags = make(map[string]interface{})
@ -450,6 +580,8 @@ func (r *layerStore) loadMounts() error {
return err
}
// Save saves the contents of the store to disk. It should be called with
// the lock held.
func (r *layerStore) Save() error {
r.mountsLockfile.Lock()
defer r.mountsLockfile.Unlock()
@ -460,10 +592,10 @@ func (r *layerStore) Save() error {
}
func (r *layerStore) saveLayers() error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to modify the layer store at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
if !r.Locked() {
if !r.lockfile.Locked() {
return errors.New("layer store is not locked for writing")
}
rpath := r.layerspath()
@ -477,11 +609,11 @@ func (r *layerStore) saveLayers() error {
if err := ioutils.AtomicWriteFile(rpath, jldata, 0600); err != nil {
return err
}
return r.Touch()
return r.lockfile.Touch()
}
func (r *layerStore) saveMounts() error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to modify the layer store at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
if !r.mountsLockfile.Locked() {
@ -539,8 +671,10 @@ func (s *store) newLayerStore(rundir string, layerdir string, driver drivers.Dri
bymount: make(map[string]*Layer),
byname: make(map[string]*Layer),
}
rlstore.Lock()
defer rlstore.Unlock()
if err := rlstore.startWritingWithReload(false); err != nil {
return nil, err
}
defer rlstore.stopWriting()
if err := rlstore.Load(); err != nil {
return nil, err
}
@ -562,8 +696,10 @@ func newROLayerStore(rundir string, layerdir string, driver drivers.Driver) (roL
bymount: make(map[string]*Layer),
byname: make(map[string]*Layer),
}
rlstore.RLock()
defer rlstore.Unlock()
if err := rlstore.startReadingWithReload(false); err != nil {
return nil, err
}
defer rlstore.stopReading()
if err := rlstore.Load(); err != nil {
return nil, err
}
@ -597,7 +733,7 @@ func (r *layerStore) Size(name string) (int64, error) {
}
func (r *layerStore) ClearFlag(id string, flag string) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to clear flags on layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
layer, ok := r.lookup(id)
@ -609,7 +745,7 @@ func (r *layerStore) ClearFlag(id string, flag string) error {
}
func (r *layerStore) SetFlag(id string, flag string, value interface{}) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to set flags on layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
layer, ok := r.lookup(id)
@ -684,7 +820,7 @@ func (r *layerStore) PutAdditionalLayer(id string, parentLayer *Layer, names []s
}
func (r *layerStore) Put(id string, parentLayer *Layer, names []string, mountLabel string, options map[string]string, moreOptions *LayerOptions, writeable bool, flags map[string]interface{}, diff io.Reader) (*Layer, int64, error) {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return nil, -1, fmt.Errorf("not allowed to create new layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
if err := os.MkdirAll(r.rundir, 0700); err != nil {
@ -889,7 +1025,7 @@ func (r *layerStore) Create(id string, parent *Layer, names []string, mountLabel
}
func (r *layerStore) Mounted(id string) (int, error) {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return 0, fmt.Errorf("no mount information for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
}
r.mountsLockfile.RLock()
@ -919,7 +1055,7 @@ func (r *layerStore) Mount(id string, options drivers.MountOpts) (string, error)
// You are not allowed to mount layers from readonly stores if they
// are not mounted read/only.
if !r.IsReadWrite() && !hasReadOnlyOpt(options.Options) {
if !r.lockfile.IsReadWrite() && !hasReadOnlyOpt(options.Options) {
return "", fmt.Errorf("not allowed to update mount locations for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
}
r.mountsLockfile.Lock()
@ -969,7 +1105,7 @@ func (r *layerStore) Mount(id string, options drivers.MountOpts) (string, error)
}
func (r *layerStore) Unmount(id string, force bool) (bool, error) {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return false, fmt.Errorf("not allowed to update mount locations for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
}
r.mountsLockfile.Lock()
@ -1007,7 +1143,7 @@ func (r *layerStore) Unmount(id string, force bool) (bool, error) {
}
func (r *layerStore) ParentOwners(id string) (uids, gids []int, err error) {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return nil, nil, fmt.Errorf("no mount information for layers at %q: %w", r.mountspath(), ErrStoreIsReadOnly)
}
r.mountsLockfile.RLock()
@ -1082,7 +1218,7 @@ func (r *layerStore) removeName(layer *Layer, name string) {
}
func (r *layerStore) updateNames(id string, names []string, op updateNameOperation) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to change layer name assignments at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
layer, ok := r.lookup(id)
@ -1130,7 +1266,7 @@ func (r *layerStore) SetBigData(id, key string, data io.Reader) error {
if key == "" {
return fmt.Errorf("can't set empty name for layer big data item: %w", ErrInvalidBigDataName)
}
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to save data items associated with layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
layer, ok := r.lookup(id)
@ -1189,7 +1325,7 @@ func (r *layerStore) Metadata(id string) (string, error) {
}
func (r *layerStore) SetMetadata(id, metadata string) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to modify layer metadata at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
if layer, ok := r.lookup(id); ok {
@ -1215,7 +1351,7 @@ func layerHasIncompleteFlag(layer *Layer) bool {
}
func (r *layerStore) deleteInternal(id string) error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to delete layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
layer, ok := r.lookup(id)
@ -1346,7 +1482,7 @@ func (r *layerStore) Get(id string) (*Layer, error) {
}
func (r *layerStore) Wipe() error {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return fmt.Errorf("not allowed to delete layers at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
ids := make([]string, 0, len(r.byid))
@ -1611,7 +1747,7 @@ func (r *layerStore) ApplyDiff(to string, diff io.Reader) (size int64, err error
}
func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions, diff io.Reader) (size int64, err error) {
if !r.IsReadWrite() {
if !r.lockfile.IsReadWrite() {
return -1, fmt.Errorf("not allowed to modify layer contents at %q: %w", r.layerspath(), ErrStoreIsReadOnly)
}
@ -1867,77 +2003,6 @@ func (r *layerStore) LayersByUncompressedDigest(d digest.Digest) ([]Layer, error
return r.layersByDigestMap(r.byuncompressedsum, d)
}
func (r *layerStore) Lock() {
r.lockfile.Lock()
}
func (r *layerStore) RLock() {
r.lockfile.RLock()
}
func (r *layerStore) Unlock() {
r.lockfile.Unlock()
}
func (r *layerStore) Touch() error {
return r.lockfile.Touch()
}
func (r *layerStore) Modified() (bool, error) {
var mmodified, tmodified bool
lmodified, err := r.lockfile.Modified()
if err != nil {
return lmodified, err
}
if r.IsReadWrite() {
r.mountsLockfile.RLock()
defer r.mountsLockfile.Unlock()
mmodified, err = r.mountsLockfile.Modified()
if err != nil {
return lmodified, err
}
}
if lmodified || mmodified {
return true, nil
}
// If the layers.json file has been modified manually, then we have to
// reload the storage in any case.
info, err := os.Stat(r.layerspath())
if err != nil && !os.IsNotExist(err) {
return false, fmt.Errorf("stat layers file: %w", err)
}
if info != nil {
tmodified = info.ModTime() != r.layerspathModified
}
return tmodified, nil
}
func (r *layerStore) IsReadWrite() bool {
return r.lockfile.IsReadWrite()
}
func (r *layerStore) TouchedSince(when time.Time) bool {
return r.lockfile.TouchedSince(when)
}
func (r *layerStore) Locked() bool {
return r.lockfile.Locked()
}
func (r *layerStore) ReloadIfChanged() error {
r.loadMut.Lock()
defer r.loadMut.Unlock()
modified, err := r.Modified()
if err == nil && modified {
return r.Load()
}
return err
}
func closeAll(closes ...func() error) (rErr error) {
for _, f := range closes {
if err := f(); err != nil {

View File

@ -527,6 +527,9 @@ func (ta *tarAppender) addTarFile(path, name string) error {
if err := ReadUserXattrToTarHeader(path, hdr); err != nil {
return err
}
if err := ReadFileFlagsToTarHeader(path, hdr); err != nil {
return err
}
if ta.CopyPass {
copyPassHeader(hdr)
}
@ -770,6 +773,15 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
}
// We defer setting flags on directories until the end of
// Unpack or UnpackLayer in case setting them makes the
// directory immutable.
if hdr.Typeflag != tar.TypeDir {
if err := WriteFileFlagsFromTarHeader(path, hdr); err != nil {
return err
}
}
if len(errs) > 0 {
logrus.WithFields(logrus.Fields{
"errors": errs,
@ -1101,6 +1113,9 @@ loop:
if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil {
return err
}
if err := WriteFileFlagsFromTarHeader(path, hdr); err != nil {
return err
}
}
return nil
}

View File

@ -1,3 +1,4 @@
//go:build !windows
// +build !windows
package archive
@ -29,6 +30,7 @@ func statDifferent(oldStat *system.StatT, oldInfo *FileInfo, newStat *system.Sta
if oldStat.Mode() != newStat.Mode() ||
ownerChanged ||
oldStat.Rdev() != newStat.Rdev() ||
oldStat.Flags() != newStat.Flags() ||
// Don't look at size for dirs, its not a good measure of change
(oldStat.Mode()&unix.S_IFDIR != unix.S_IFDIR &&
(!sameFsTimeSpec(oldStat.Mtim(), newStat.Mtim()) || (oldStat.Size() != newStat.Size()))) {

View File

@ -145,6 +145,9 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
return nil
}
if _, exists := unpackedPaths[path]; !exists {
if err := resetImmutable(path, nil); err != nil {
return err
}
err := os.RemoveAll(path)
return err
}
@ -156,6 +159,9 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
} else {
originalBase := base[len(WhiteoutPrefix):]
originalPath := filepath.Join(dir, originalBase)
if err := resetImmutable(originalPath, nil); err != nil {
return 0, err
}
if err := os.RemoveAll(originalPath); err != nil {
return 0, err
}
@ -165,7 +171,15 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
// The only exception is when it is a directory *and* the file from
// the layer is also a directory. Then we want to merge them (i.e.
// just apply the metadata from the layer).
//
// We always reset the immutable flag (if present) to allow metadata
// changes and to allow directory modification. The flag will be
// re-applied based on the contents of hdr either at the end for
// directories or in createTarFile otherwise.
if fi, err := os.Lstat(path); err == nil {
if err := resetImmutable(path, &fi); err != nil {
return 0, err
}
if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
if err := os.RemoveAll(path); err != nil {
return 0, err
@ -215,6 +229,9 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil {
return 0, err
}
if err := WriteFileFlagsFromTarHeader(path, hdr); err != nil {
return 0, err
}
}
return size, nil

View File

@ -0,0 +1,167 @@
//go:build freebsd
// +build freebsd
package archive
import (
"archive/tar"
"fmt"
"math/bits"
"os"
"strings"
"syscall"
"github.com/containers/storage/pkg/system"
)
const (
paxSCHILYFflags = "SCHILY.fflags"
)
var (
flagNameToValue = map[string]uint32{
"sappnd": system.SF_APPEND,
"sappend": system.SF_APPEND,
"arch": system.SF_ARCHIVED,
"archived": system.SF_ARCHIVED,
"schg": system.SF_IMMUTABLE,
"schange": system.SF_IMMUTABLE,
"simmutable": system.SF_IMMUTABLE,
"sunlnk": system.SF_NOUNLINK,
"sunlink": system.SF_NOUNLINK,
"snapshot": system.SF_SNAPSHOT,
"uappnd": system.UF_APPEND,
"uappend": system.UF_APPEND,
"uarch": system.UF_ARCHIVE,
"uarchive": system.UF_ARCHIVE,
"hidden": system.UF_HIDDEN,
"uhidden": system.UF_HIDDEN,
"uchg": system.UF_IMMUTABLE,
"uchange": system.UF_IMMUTABLE,
"uimmutable": system.UF_IMMUTABLE,
"uunlnk": system.UF_NOUNLINK,
"uunlink": system.UF_NOUNLINK,
"offline": system.UF_OFFLINE,
"uoffline": system.UF_OFFLINE,
"opaque": system.UF_OPAQUE,
"rdonly": system.UF_READONLY,
"urdonly": system.UF_READONLY,
"readonly": system.UF_READONLY,
"ureadonly": system.UF_READONLY,
"reparse": system.UF_REPARSE,
"ureparse": system.UF_REPARSE,
"sparse": system.UF_SPARSE,
"usparse": system.UF_SPARSE,
"system": system.UF_SYSTEM,
"usystem": system.UF_SYSTEM,
}
// Only include the short names for the reverse map
flagValueToName = map[uint32]string{
system.SF_APPEND: "sappnd",
system.SF_ARCHIVED: "arch",
system.SF_IMMUTABLE: "schg",
system.SF_NOUNLINK: "sunlnk",
system.SF_SNAPSHOT: "snapshot",
system.UF_APPEND: "uappnd",
system.UF_ARCHIVE: "uarch",
system.UF_HIDDEN: "hidden",
system.UF_IMMUTABLE: "uchg",
system.UF_NOUNLINK: "uunlnk",
system.UF_OFFLINE: "offline",
system.UF_OPAQUE: "opaque",
system.UF_READONLY: "rdonly",
system.UF_REPARSE: "reparse",
system.UF_SPARSE: "sparse",
system.UF_SYSTEM: "system",
}
)
func parseFileFlags(fflags string) (uint32, uint32, error) {
var set, clear uint32 = 0, 0
for _, fflag := range strings.Split(fflags, ",") {
isClear := false
if strings.HasPrefix(fflag, "no") {
isClear = true
fflag = strings.TrimPrefix(fflag, "no")
}
if value, ok := flagNameToValue[fflag]; ok {
if isClear {
clear |= value
} else {
set |= value
}
} else {
return 0, 0, fmt.Errorf("parsing file flags, unrecognised token: %s", fflag)
}
}
return set, clear, nil
}
func formatFileFlags(fflags uint32) (string, error) {
var res = []string{}
for fflags != 0 {
// Extract lowest set bit
fflag := uint32(1) << bits.TrailingZeros32(fflags)
if name, ok := flagValueToName[fflag]; ok {
res = append(res, name)
} else {
return "", fmt.Errorf("formatting file flags, unrecognised flag: %x", fflag)
}
fflags &= ^fflag
}
return strings.Join(res, ","), nil
}
func ReadFileFlagsToTarHeader(path string, hdr *tar.Header) error {
st, err := system.Lstat(path)
if err != nil {
return err
}
fflags, err := formatFileFlags(st.Flags())
if err != nil {
return err
}
if fflags != "" {
if hdr.PAXRecords == nil {
hdr.PAXRecords = map[string]string{}
}
hdr.PAXRecords[paxSCHILYFflags] = fflags
}
return nil
}
func WriteFileFlagsFromTarHeader(path string, hdr *tar.Header) error {
if fflags, ok := hdr.PAXRecords[paxSCHILYFflags]; ok {
var set, clear uint32
set, clear, err := parseFileFlags(fflags)
if err != nil {
return err
}
// Apply the delta to the existing file flags
st, err := system.Lstat(path)
if err != nil {
return err
}
return system.Lchflags(path, (st.Flags() & ^clear)|set)
}
return nil
}
func resetImmutable(path string, fi *os.FileInfo) error {
var flags uint32
if fi != nil {
flags = (*fi).Sys().(*syscall.Stat_t).Flags
} else {
st, err := system.Lstat(path)
if err != nil {
return err
}
flags = st.Flags()
}
if flags&(system.SF_IMMUTABLE|system.UF_IMMUTABLE) != 0 {
flags &= ^(system.SF_IMMUTABLE | system.UF_IMMUTABLE)
return system.Lchflags(path, flags)
}
return nil
}

View File

@ -0,0 +1,21 @@
//go:build !freebsd
// +build !freebsd
package archive
import (
"archive/tar"
"os"
)
func ReadFileFlagsToTarHeader(path string, hdr *tar.Header) error {
return nil
}
func WriteFileFlagsFromTarHeader(path string, hdr *tar.Header) error {
return nil
}
func resetImmutable(path string, fi *os.FileInfo) error {
return nil
}

View File

@ -246,7 +246,7 @@ func (l *lockfile) Modified() (bool, error) {
panic("attempted to check last-writer in lockfile without locking it first")
}
defer l.stateMutex.Unlock()
currentLW := make([]byte, len(l.lw))
currentLW := make([]byte, lastWriterIDSize)
n, err := unix.Pread(int(l.fd), currentLW, 0)
if err != nil {
return true, err

View File

@ -22,9 +22,8 @@ func unmount(target string, flags int) error {
// can be returned if flags are invalid, so this code
// assumes that the flags value is always correct.
return nil
default:
break
}
break
}
return &mountError{

View File

@ -0,0 +1,56 @@
//go:build freebsd
// +build freebsd
package system
import (
"unsafe"
"golang.org/x/sys/unix"
)
// Flag values from <sys/stat.h>
const (
/*
* Definitions of flags stored in file flags word.
*
* Super-user and owner changeable flags.
*/
UF_SETTABLE uint32 = 0x0000ffff /* mask of owner changeable flags */
UF_NODUMP uint32 = 0x00000001 /* do not dump file */
UF_IMMUTABLE uint32 = 0x00000002 /* file may not be changed */
UF_APPEND uint32 = 0x00000004 /* writes to file may only append */
UF_OPAQUE uint32 = 0x00000008 /* directory is opaque wrt. union */
UF_NOUNLINK uint32 = 0x00000010 /* file may not be removed or renamed */
UF_SYSTEM uint32 = 0x00000080 /* Windows system file bit */
UF_SPARSE uint32 = 0x00000100 /* sparse file */
UF_OFFLINE uint32 = 0x00000200 /* file is offline */
UF_REPARSE uint32 = 0x00000400 /* Windows reparse point file bit */
UF_ARCHIVE uint32 = 0x00000800 /* file needs to be archived */
UF_READONLY uint32 = 0x00001000 /* Windows readonly file bit */
/* This is the same as the MacOS X definition of UF_HIDDEN. */
UF_HIDDEN uint32 = 0x00008000 /* file is hidden */
/*
* Super-user changeable flags.
*/
SF_SETTABLE uint32 = 0xffff0000 /* mask of superuser changeable flags */
SF_ARCHIVED uint32 = 0x00010000 /* file is archived */
SF_IMMUTABLE uint32 = 0x00020000 /* file may not be changed */
SF_APPEND uint32 = 0x00040000 /* writes to file may only append */
SF_NOUNLINK uint32 = 0x00100000 /* file may not be removed or renamed */
SF_SNAPSHOT uint32 = 0x00200000 /* snapshot inode */
)
func Lchflags(path string, flags uint32) error {
p, err := unix.BytePtrFromString(path)
if err != nil {
return err
}
_, _, e1 := unix.Syscall(unix.SYS_LCHFLAGS, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
return e1
}
return nil
}

View File

@ -1,8 +1,10 @@
package system
import (
"errors"
"fmt"
"os"
"syscall"
"time"
"github.com/containers/storage/pkg/mount"
@ -34,14 +36,24 @@ func EnsureRemoveAll(dir string) error {
}
for {
if err := resetFileFlags(dir); err != nil {
return fmt.Errorf("resetting file flags: %w", err)
}
err := os.RemoveAll(dir)
if err == nil {
return nil
}
// If the RemoveAll fails with a permission error, we
// may have immutable files so try to remove the
// immutable flag and redo the RemoveAll.
if errors.Is(err, syscall.EPERM) {
if err = resetFileFlags(dir); err != nil {
return fmt.Errorf("resetting file flags: %w", err)
}
err = os.RemoveAll(dir)
if err == nil {
return nil
}
}
pe, ok := err.(*os.PathError)
if !ok {
return err

View File

@ -3,28 +3,13 @@ package system
import (
"io/fs"
"path/filepath"
"unsafe"
"golang.org/x/sys/unix"
)
func lchflags(path string, flags int) (err error) {
p, err := unix.BytePtrFromString(path)
if err != nil {
return err
}
_, _, e1 := unix.Syscall(unix.SYS_LCHFLAGS, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
return e1
}
return nil
}
// Reset file flags in a directory tree. This allows EnsureRemoveAll
// to delete trees which have the immutable flag set.
func resetFileFlags(dir string) error {
return filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
if err := lchflags(path, 0); err != nil {
if err := Lchflags(path, 0); err != nil {
return err
}
return nil

View File

@ -0,0 +1,12 @@
//go:build !freebsd
// +build !freebsd
package system
type platformStatT struct {
}
// Flags return file flags if supported or zero otherwise
func (s StatT) Flags() uint32 {
return 0
}

View File

@ -2,12 +2,23 @@ package system
import "syscall"
type platformStatT struct {
flags uint32
}
// Flags return file flags if supported or zero otherwise
func (s StatT) Flags() uint32 {
return s.flags
}
// fromStatT converts a syscall.Stat_t type to a system.Stat_t type
func fromStatT(s *syscall.Stat_t) (*StatT, error) {
return &StatT{size: s.Size,
st := &StatT{size: s.Size,
mode: uint32(s.Mode),
uid: s.Uid,
gid: s.Gid,
rdev: uint64(s.Rdev),
mtim: s.Mtimespec}, nil
mtim: s.Mtimespec}
st.flags = s.Flags
return st, nil
}

View File

@ -1,3 +1,4 @@
//go:build !windows
// +build !windows
package system
@ -17,6 +18,7 @@ type StatT struct {
rdev uint64
size int64
mtim syscall.Timespec
platformStatT
}
// Mode returns file's permission mode.

View File

@ -50,36 +50,6 @@ var (
storesLock sync.Mutex
)
// roFileBasedStore wraps up the methods of the various types of file-based
// data stores that we implement which are needed for both read-only and
// read-write files.
type roFileBasedStore interface {
Locker
// Load reloads the contents of the store from disk. It should be called
// with the lock held.
Load() error
// ReloadIfChanged reloads the contents of the store from disk if it is changed.
ReloadIfChanged() error
}
// rwFileBasedStore wraps up the methods of various types of file-based data
// stores that we implement using read-write files.
type rwFileBasedStore interface {
// Save saves the contents of the store to disk. It should be called with
// the lock held, and Touch() should be called afterward before releasing the
// lock.
Save() error
}
// fileBasedStore wraps up the common methods of various types of file-based
// data stores that we implement.
type fileBasedStore interface {
roFileBasedStore
rwFileBasedStore
}
// roMetadataStore wraps a method for reading metadata associated with an ID.
type roMetadataStore interface {
// Metadata reads metadata associated with an item with the specified ID.
@ -694,10 +664,8 @@ func GetStore(options types.StoreOptions) (Store, error) {
if err := os.MkdirAll(options.GraphRoot, 0700); err != nil {
return nil, err
}
for _, subdir := range []string{"mounts", "tmp", options.GraphDriverName} {
if err := os.MkdirAll(filepath.Join(options.GraphRoot, subdir), 0700); err != nil {
return nil, err
}
if err := os.MkdirAll(filepath.Join(options.GraphRoot, options.GraphDriverName), 0700); err != nil {
return nil, err
}
graphLock, err := GetLockfile(filepath.Join(options.GraphRoot, "storage.lock"))
@ -991,11 +959,10 @@ func (s *store) readAllLayerStores(fn func(store roLayerStore) (bool, error)) (b
}
for _, s := range layerStores {
store := s
store.RLock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startReading(); err != nil {
return true, err
}
defer store.stopReading()
if done, err := fn(store); done {
return true, err
}
@ -1012,11 +979,10 @@ func (s *store) writeToLayerStore(fn func(store rwLayerStore) error) error {
return err
}
store.Lock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startWriting(); err != nil {
return err
}
defer store.stopWriting()
return fn(store)
}
@ -1079,11 +1045,10 @@ func (s *store) readAllImageStores(fn func(store roImageStore) (bool, error)) (b
}
for _, s := range ImageStores {
store := s
store.RLock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startReading(); err != nil {
return true, err
}
defer store.stopReading()
if done, err := fn(store); done {
return true, err
}
@ -1100,11 +1065,10 @@ func (s *store) writeToImageStore(fn func(store rwImageStore) error) error {
return err
}
store.Lock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startWriting(); err != nil {
return err
}
defer store.stopWriting()
return fn(store)
}
@ -1126,11 +1090,10 @@ func (s *store) writeToContainerStore(fn func(store rwContainerStore) error) err
return err
}
store.Lock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startWriting(); err != nil {
return err
}
defer store.stopWriting()
return fn(store)
}
@ -1151,21 +1114,18 @@ func (s *store) writeToAllStores(fn func(rlstore rwLayerStore, ristore rwImageSt
return err
}
rlstore.Lock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startWriting(); err != nil {
return err
}
ristore.Lock()
defer ristore.Unlock()
if err := ristore.ReloadIfChanged(); err != nil {
defer rlstore.stopWriting()
if err := ristore.startWriting(); err != nil {
return err
}
rcstore.Lock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
defer ristore.stopWriting()
if err := rcstore.startWriting(); err != nil {
return err
}
defer rcstore.stopWriting()
return fn(rlstore, ristore, rcstore)
}
@ -1197,16 +1157,14 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w
if err != nil {
return nil, -1, err
}
rlstore.Lock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startWriting(); err != nil {
return nil, -1, err
}
rcstore.Lock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
defer rlstore.stopWriting()
if err := rcstore.startWriting(); err != nil {
return nil, -1, err
}
defer rcstore.stopWriting()
if options == nil {
options = &LayerOptions{}
}
@ -1223,11 +1181,10 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w
for _, l := range append([]roLayerStore{rlstore}, rlstores...) {
lstore := l
if lstore != rlstore {
lstore.RLock()
defer lstore.Unlock()
if err := lstore.ReloadIfChanged(); err != nil {
if err := lstore.startReading(); err != nil {
return nil, -1, err
}
defer lstore.stopReading()
}
if l, err := lstore.Get(parent); err == nil && l != nil {
ilayer = l
@ -1293,12 +1250,10 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, o
var ilayer *Layer
for _, s := range layerStores {
store := s
store.RLock()
defer store.Unlock()
err := store.ReloadIfChanged()
if err != nil {
if err := store.startReading(); err != nil {
return nil, err
}
defer store.stopReading()
ilayer, err = store.Get(layer)
if err == nil {
break
@ -1481,34 +1436,36 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
if err != nil {
return nil, err
}
rlstore.Lock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startWriting(); err != nil {
return nil, err
}
defer rlstore.stopWriting()
for _, s := range lstores {
store := s
store.RLock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startReading(); err != nil {
return nil, err
}
defer store.stopReading()
}
for _, s := range append([]roImageStore{istore}, istores...) {
store := s
if store == istore {
store.Lock()
} else {
store.RLock()
}
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
return nil, err
}
cimage, err = store.Get(image)
if err == nil {
imageHomeStore = store
break
if err := istore.startWriting(); err != nil {
return nil, err
}
defer istore.stopWriting()
cimage, err = istore.Get(image)
if err == nil {
imageHomeStore = istore
} else {
for _, s := range istores {
store := s
if err := store.startReading(); err != nil {
return nil, err
}
defer store.stopReading()
cimage, err = store.Get(image)
if err == nil {
imageHomeStore = store
break
}
}
}
if cimage == nil {
@ -1546,11 +1503,10 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
}
}
} else {
rlstore.Lock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startWriting(); err != nil {
return nil, err
}
defer rlstore.stopWriting()
if !options.HostUIDMapping && len(options.UIDMap) == 0 {
uidMap = s.uidMap
}
@ -1671,11 +1627,10 @@ func (s *store) Metadata(id string) (string, error) {
if err != nil {
return "", err
}
cstore.RLock()
defer cstore.Unlock()
if err := cstore.ReloadIfChanged(); err != nil {
if err := cstore.startReading(); err != nil {
return "", err
}
defer cstore.stopReading()
if cstore.Exists(id) {
return cstore.Metadata(id)
}
@ -1818,11 +1773,10 @@ func (s *store) ImageSize(id string) (int64, error) {
}
for _, s := range layerStores {
store := s
store.RLock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startReading(); err != nil {
return -1, err
}
defer store.stopReading()
}
imageStores, err := s.allImageStores()
@ -1834,11 +1788,10 @@ func (s *store) ImageSize(id string) (int64, error) {
var image *Image
for _, s := range imageStores {
store := s
store.RLock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startReading(); err != nil {
return -1, err
}
defer store.stopReading()
if image, err = store.Get(id); err == nil {
imageStore = store
break
@ -1918,11 +1871,10 @@ func (s *store) ContainerSize(id string) (int64, error) {
}
for _, s := range layerStores {
store := s
store.RLock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startReading(); err != nil {
return -1, err
}
defer store.stopReading()
}
// Get the location of the container directory and container run directory.
@ -1940,11 +1892,10 @@ func (s *store) ContainerSize(id string) (int64, error) {
if err != nil {
return -1, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return -1, err
}
defer rcstore.stopReading()
// Read the container record.
container, err := rcstore.Get(id)
@ -2002,11 +1953,10 @@ func (s *store) ListContainerBigData(id string) ([]string, error) {
return nil, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return nil, err
}
defer rcstore.stopReading()
return rcstore.BigDataNames(id)
}
@ -2016,11 +1966,10 @@ func (s *store) ContainerBigDataSize(id, key string) (int64, error) {
if err != nil {
return -1, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return -1, err
}
defer rcstore.stopReading()
return rcstore.BigDataSize(id, key)
}
@ -2029,11 +1978,10 @@ func (s *store) ContainerBigDataDigest(id, key string) (digest.Digest, error) {
if err != nil {
return "", err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return "", err
}
defer rcstore.stopReading()
return rcstore.BigDataDigest(id, key)
}
@ -2042,11 +1990,10 @@ func (s *store) ContainerBigData(id, key string) ([]byte, error) {
if err != nil {
return nil, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return nil, err
}
defer rcstore.stopReading()
return rcstore.BigData(id, key)
}
@ -2083,16 +2030,11 @@ func (s *store) Exists(id string) bool {
if err != nil {
return false
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return false
}
if rcstore.Exists(id) {
return true
}
return false
defer rcstore.stopReading()
return rcstore.Exists(id)
}
func dedupeNames(names []string) []string {
@ -2138,11 +2080,10 @@ func (s *store) updateNames(id string, names []string, op updateNameOperation) e
if err != nil {
return err
}
ristore.Lock()
defer ristore.Unlock()
if err := ristore.ReloadIfChanged(); err != nil {
if err := ristore.startWriting(); err != nil {
return err
}
defer ristore.stopWriting()
if ristore.Exists(id) {
return ristore.updateNames(id, deduped, op)
}
@ -2154,20 +2095,16 @@ func (s *store) updateNames(id string, names []string, op updateNameOperation) e
}
for _, s := range ristores {
store := s
store.RLock()
defer store.Unlock()
if err := store.ReloadIfChanged(); err != nil {
if err := store.startReading(); err != nil {
return err
}
defer store.stopReading()
if i, err := store.Get(id); err == nil {
if len(deduped) > 1 {
// Do not want to create image name in R/W storage
deduped = deduped[1:]
}
_, err := ristore.Create(id, deduped, i.TopLayer, i.Metadata, i.Created, i.Digest)
if err == nil {
return ristore.Save()
}
return err
}
}
@ -2213,11 +2150,10 @@ func (s *store) Names(id string) ([]string, error) {
if err != nil {
return nil, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return nil, err
}
defer rcstore.stopReading()
if c, err := rcstore.Get(id); c != nil && err == nil {
return c.Names, nil
}
@ -2251,11 +2187,10 @@ func (s *store) Lookup(name string) (string, error) {
if err != nil {
return "", err
}
cstore.RLock()
defer cstore.Unlock()
if err := cstore.ReloadIfChanged(); err != nil {
if err := cstore.startReading(); err != nil {
return "", err
}
defer cstore.stopReading()
if c, err := cstore.Get(name); c != nil && err == nil {
return c.ID, nil
}
@ -2566,11 +2501,10 @@ func (s *store) mount(id string, options drivers.MountOpts) (string, error) {
s.graphLock.Lock()
defer s.graphLock.Unlock()
rlstore.Lock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startWriting(); err != nil {
return "", err
}
defer rlstore.stopWriting()
modified, err := s.graphLock.Modified()
if err != nil {
@ -2646,11 +2580,10 @@ func (s *store) Mounted(id string) (int, error) {
if err != nil {
return 0, err
}
rlstore.RLock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startReading(); err != nil {
return 0, err
}
defer rlstore.stopReading()
return rlstore.Mounted(id)
}
@ -2738,9 +2671,7 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro
for _, s := range layerStores {
store := s
store.RLock()
if err := store.ReloadIfChanged(); err != nil {
store.Unlock()
if err := store.startReading(); err != nil {
return nil, err
}
if store.Exists(to) {
@ -2748,15 +2679,15 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro
if rc != nil && err == nil {
wrapped := ioutils.NewReadCloserWrapper(rc, func() error {
err := rc.Close()
store.Unlock()
store.stopReading()
return err
})
return wrapped, nil
}
store.Unlock()
store.stopReading()
return rc, err
}
store.Unlock()
store.stopReading()
}
return nil, ErrLayerUnknown
}
@ -2870,11 +2801,10 @@ func (s *store) LayerParentOwners(id string) ([]int, []int, error) {
if err != nil {
return nil, nil, err
}
rlstore.RLock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startReading(); err != nil {
return nil, nil, err
}
defer rlstore.stopReading()
if rlstore.Exists(id) {
return rlstore.ParentOwners(id)
}
@ -2890,16 +2820,14 @@ func (s *store) ContainerParentOwners(id string) ([]int, []int, error) {
if err != nil {
return nil, nil, err
}
rlstore.RLock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startReading(); err != nil {
return nil, nil, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
defer rlstore.stopReading()
if err := rcstore.startReading(); err != nil {
return nil, nil, err
}
defer rcstore.stopReading()
container, err := rcstore.Get(id)
if err != nil {
return nil, nil, err
@ -2946,11 +2874,10 @@ func (s *store) Containers() ([]Container, error) {
return nil, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return nil, err
}
defer rcstore.stopReading()
return rcstore.Containers()
}
@ -3014,11 +2941,10 @@ func (al *additionalLayer) PutAs(id, parent string, names []string) (*Layer, err
if err != nil {
return nil, err
}
rlstore.Lock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startWriting(); err != nil {
return nil, err
}
defer rlstore.stopWriting()
rlstores, err := al.s.getROLayerStores()
if err != nil {
return nil, err
@ -3028,11 +2954,10 @@ func (al *additionalLayer) PutAs(id, parent string, names []string) (*Layer, err
if parent != "" {
for _, lstore := range append([]roLayerStore{rlstore}, rlstores...) {
if lstore != rlstore {
lstore.RLock()
defer lstore.Unlock()
if err := lstore.ReloadIfChanged(); err != nil {
if err := lstore.startReading(); err != nil {
return nil, err
}
defer lstore.stopReading()
}
parentLayer, err = lstore.Get(parent)
if err == nil {
@ -3111,11 +3036,10 @@ func (s *store) Container(id string) (*Container, error) {
if err != nil {
return nil, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return nil, err
}
defer rcstore.stopReading()
return rcstore.Get(id)
}
@ -3125,11 +3049,10 @@ func (s *store) ContainerLayerID(id string) (string, error) {
if err != nil {
return "", err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return "", err
}
defer rcstore.stopReading()
container, err := rcstore.Get(id)
if err != nil {
return "", err
@ -3146,11 +3069,10 @@ func (s *store) ContainerByLayer(id string) (*Container, error) {
if err != nil {
return nil, err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return nil, err
}
defer rcstore.stopReading()
containerList, err := rcstore.Containers()
if err != nil {
return nil, err
@ -3169,11 +3091,10 @@ func (s *store) ContainerDirectory(id string) (string, error) {
if err != nil {
return "", err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return "", err
}
defer rcstore.stopReading()
id, err = rcstore.Lookup(id)
if err != nil {
@ -3194,11 +3115,10 @@ func (s *store) ContainerRunDirectory(id string) (string, error) {
return "", err
}
rcstore.RLock()
defer rcstore.Unlock()
if err := rcstore.ReloadIfChanged(); err != nil {
if err := rcstore.startReading(); err != nil {
return "", err
}
defer rcstore.stopReading()
id, err = rcstore.Lookup(id)
if err != nil {
@ -3264,11 +3184,10 @@ func (s *store) Shutdown(force bool) ([]string, error) {
s.graphLock.Lock()
defer s.graphLock.Unlock()
rlstore.Lock()
defer rlstore.Unlock()
if err := rlstore.ReloadIfChanged(); err != nil {
if err := rlstore.startWriting(); err != nil {
return nil, err
}
defer rlstore.stopWriting()
layers, err := rlstore.Layers()
if err != nil {

View File

@ -35,6 +35,9 @@ const (
var (
defaultStoreOptionsOnce sync.Once
loadDefaultStoreOptionsErr error
once sync.Once
storeOptions StoreOptions
storeError error
)
func loadDefaultStoreOptions() {
@ -167,8 +170,8 @@ func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf str
return storageOpts, nil
}
// DefaultStoreOptions returns the default storage ops for containers
func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
// loadStoreOptions returns the default storage ops for containers
func loadStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
storageConf, err := DefaultConfigFile(rootless && rootlessUID != 0)
if err != nil {
return defaultStoreOptions, err
@ -176,6 +179,21 @@ func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
return defaultStoreOptionsIsolated(rootless, rootlessUID, storageConf)
}
// UpdateOptions should be called iff container engine recieved a SIGHUP,
// otherwise use DefaultStoreOptions
func UpdateStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
storeOptions, storeError = loadStoreOptions(rootless, rootlessUID)
return storeOptions, storeError
}
// DefaultStoreOptions returns the default storage ops for containers
func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
once.Do(func() {
storeOptions, storeError = loadStoreOptions(rootless, rootlessUID)
})
return storeOptions, storeError
}
// StoreOptions is used for passing initialization options to GetStore(), for
// initializing a Store object and the underlying storage that it controls.
type StoreOptions struct {

View File

@ -151,7 +151,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils
github.com/containers/ocicrypt/utils/keyprovider
# github.com/containers/storage v1.43.1-0.20221017123904-a4d4fe98e37d
# github.com/containers/storage v1.43.1-0.20221024131621-fae5bbf607fc
## explicit; go 1.17
github.com/containers/storage
github.com/containers/storage/drivers