diff options
13 files changed, 203 insertions, 89 deletions
diff --git a/vendor.conf b/vendor.conf index 309189c05..9488bb644 100644 --- a/vendor.conf +++ b/vendor.conf @@ -16,7 +16,7 @@ github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d github.com/containernetworking/cni v0.7.0-alpha1 github.com/containernetworking/plugins v0.7.4 github.com/containers/image 93bced01015eb94bec4821df1876314be8197680 -github.com/containers/storage 06b6c2e4cf254f5922a79da058c94ac2a65bb92f +github.com/containers/storage v1.10 github.com/containers/psgo v1.1 github.com/coreos/go-systemd v14 github.com/cri-o/ocicni 2d2983e40c242322a56c22a903785e7f83eb378c diff --git a/vendor/github.com/containers/storage/containers.go b/vendor/github.com/containers/storage/containers.go index beaf41f39..10d628dbe 100644 --- a/vendor/github.com/containers/storage/containers.go +++ b/vendor/github.com/containers/storage/containers.go @@ -568,6 +568,9 @@ func (r *containerStore) Lock() { r.lockfile.Lock() } +func (r *containerStore) RLock() { + r.lockfile.RLock() +} func (r *containerStore) Unlock() { r.lockfile.Unlock() } diff --git a/vendor/github.com/containers/storage/containers_ffjson.go b/vendor/github.com/containers/storage/containers_ffjson.go index 40b912bb3..aef6becfe 100644 --- a/vendor/github.com/containers/storage/containers_ffjson.go +++ b/vendor/github.com/containers/storage/containers_ffjson.go @@ -1,5 +1,5 @@ // Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT. -// source: ./containers.go +// source: containers.go package storage diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index 57d6dd63a..657d9b3ce 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -239,6 +239,8 @@ func parseOptions(options []string) (*overlayOptions, error) { } key = strings.ToLower(key) switch key { + case ".override_kernel_check", "overlay.override_kernel_check", "overlay2.override_kernel_check": + logrus.Warnf("overlay: override_kernel_check option was specified, but is no longer necessary") case ".mountopt", "overlay.mountopt", "overlay2.mountopt": o.mountOptions = val case ".size", "overlay.size", "overlay2.size": diff --git a/vendor/github.com/containers/storage/errors.go b/vendor/github.com/containers/storage/errors.go index 562415c09..63cb9ab74 100644 --- a/vendor/github.com/containers/storage/errors.go +++ b/vendor/github.com/containers/storage/errors.go @@ -43,8 +43,6 @@ var ( ErrSizeUnknown = errors.New("size is not known") // ErrStoreIsReadOnly is returned when the caller makes a call to a read-only store that would require modifying its contents. ErrStoreIsReadOnly = errors.New("called a write method on a read-only store") - // ErrLockReadOnly indicates that the caller only took a read-only lock, and is not allowed to write. - ErrLockReadOnly = errors.New("lock is not a read-write lock") // ErrDuplicateImageNames indicates that the read-only store uses the same name for multiple images. ErrDuplicateImageNames = errors.New("read-only image store assigns the same name to multiple images") // ErrDuplicateLayerNames indicates that the read-only store uses the same name for multiple layers. diff --git a/vendor/github.com/containers/storage/images.go b/vendor/github.com/containers/storage/images.go index fa4a7c43b..93505f5fb 100644 --- a/vendor/github.com/containers/storage/images.go +++ b/vendor/github.com/containers/storage/images.go @@ -756,6 +756,10 @@ func (r *imageStore) Lock() { r.lockfile.Lock() } +func (r *imageStore) RLock() { + r.lockfile.RLock() +} + func (r *imageStore) Unlock() { r.lockfile.Unlock() } diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index cdc3cbba9..d612f0459 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -1222,6 +1222,10 @@ func (r *layerStore) Lock() { r.lockfile.Lock() } +func (r *layerStore) RLock() { + r.lockfile.RLock() +} + func (r *layerStore) Unlock() { r.lockfile.Unlock() } diff --git a/vendor/github.com/containers/storage/layers_ffjson.go b/vendor/github.com/containers/storage/layers_ffjson.go index 09b5d0f33..125b5d8c9 100644 --- a/vendor/github.com/containers/storage/layers_ffjson.go +++ b/vendor/github.com/containers/storage/layers_ffjson.go @@ -1,5 +1,5 @@ // Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT. -// source: ./layers.go +// source: layers.go package storage diff --git a/vendor/github.com/containers/storage/lockfile.go b/vendor/github.com/containers/storage/lockfile.go index 9f6a18144..7f07b9ac5 100644 --- a/vendor/github.com/containers/storage/lockfile.go +++ b/vendor/github.com/containers/storage/lockfile.go @@ -1,7 +1,6 @@ package storage import ( - "fmt" "path/filepath" "sync" "time" @@ -13,7 +12,14 @@ import ( // identifier of the last party that made changes to whatever's being protected // by the lock. type Locker interface { - sync.Locker + // Acquire a writer lock. + Lock() + + // Unlock the lock. + Unlock() + + // Acquire a reader lock. + RLock() // Touch records, for others sharing the lock, that the caller was the // last writer. It should only be called with the lock held. @@ -39,31 +45,22 @@ var ( ) // GetLockfile opens a read-write lock file, creating it if necessary. The -// Locker object it returns will be returned unlocked. +// Locker object may already be locked if the path has already been requested +// by the current process. func GetLockfile(path string) (Locker, error) { - lockfilesLock.Lock() - defer lockfilesLock.Unlock() - if lockfiles == nil { - lockfiles = make(map[string]Locker) - } - cleanPath := filepath.Clean(path) - if locker, ok := lockfiles[cleanPath]; ok { - if !locker.IsReadWrite() { - return nil, errors.Wrapf(ErrLockReadOnly, "lock %q is a read-only lock", cleanPath) - } - return locker, nil - } - locker, err := getLockFile(path, false) // platform dependent locker - if err != nil { - return nil, err - } - lockfiles[filepath.Clean(path)] = locker - return locker, nil + return getLockfile(path, false) } -// GetROLockfile opens a read-only lock file. The Locker object it returns -// will be returned unlocked. +// GetROLockfile opens a read-only lock file, creating it if necessary. The +// Locker object may already be locked if the path has already been requested +// by the current process. func GetROLockfile(path string) (Locker, error) { + return getLockfile(path, true) +} + +// getLockfile is a helper for GetLockfile and GetROLockfile and returns Locker +// based on the path and read-only property. +func getLockfile(path string, ro bool) (Locker, error) { lockfilesLock.Lock() defer lockfilesLock.Unlock() if lockfiles == nil { @@ -71,12 +68,15 @@ func GetROLockfile(path string) (Locker, error) { } cleanPath := filepath.Clean(path) if locker, ok := lockfiles[cleanPath]; ok { - if locker.IsReadWrite() { - return nil, fmt.Errorf("lock %q is a read-write lock", cleanPath) + if ro && locker.IsReadWrite() { + return nil, errors.Errorf("lock %q is not a read-only lock", cleanPath) + } + if !ro && !locker.IsReadWrite() { + return nil, errors.Errorf("lock %q is not a read-write lock", cleanPath) } return locker, nil } - locker, err := getLockFile(path, true) // platform dependent locker + locker, err := getLockFile(path, ro) // platform dependent locker if err != nil { return nil, err } diff --git a/vendor/github.com/containers/storage/lockfile_unix.go b/vendor/github.com/containers/storage/lockfile_unix.go index 31e39c02e..0adbc49a5 100644 --- a/vendor/github.com/containers/storage/lockfile_unix.go +++ b/vendor/github.com/containers/storage/lockfile_unix.go @@ -3,6 +3,7 @@ package storage import ( + "fmt" "os" "sync" "time" @@ -24,38 +25,84 @@ func getLockFile(path string, ro bool) (Locker, error) { return nil, errors.Wrapf(err, "error opening %q", path) } unix.CloseOnExec(fd) + + locktype := unix.F_WRLCK if ro { - return &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_RDLCK, locked: false}, nil + locktype = unix.F_RDLCK } - return &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_WRLCK, locked: false}, nil + return &lockfile{ + stateMutex: &sync.Mutex{}, + writeMutex: &sync.Mutex{}, + file: path, + fd: uintptr(fd), + lw: stringid.GenerateRandomID(), + locktype: int16(locktype), + locked: false, + ro: ro}, nil } type lockfile struct { - mu sync.Mutex - file string - fd uintptr - lw string - locktype int16 - locked bool + // stateMutex is used to synchronize concurrent accesses + stateMutex *sync.Mutex + // writeMutex is used to serialize and avoid recursive writer locks + writeMutex *sync.Mutex + counter int64 + file string + fd uintptr + lw string + locktype int16 + locked bool + ro bool } -// Lock locks the lock file -func (l *lockfile) Lock() { +// lock locks the lockfile via FCTNL(2) based on the specified type and +// command. +func (l *lockfile) lock(l_type int16) { lk := unix.Flock_t{ - Type: l.locktype, + Type: l_type, Whence: int16(os.SEEK_SET), Start: 0, Len: 0, Pid: int32(os.Getpid()), } - l.mu.Lock() + if l_type == unix.F_WRLCK { + // If we try to lock as a writer, lock the writerMutex first to + // avoid multiple writer acquisitions of the same process. + // Note: it's important to lock it prior to the stateMutex to + // avoid a deadlock. + l.writeMutex.Lock() + } + l.stateMutex.Lock() + l.locktype = l_type + if l.counter == 0 { + // Optimization: only use the (expensive) fcntl syscall when + // the counter is 0. If it's greater than that, we're owning + // the lock already and can only be a reader. + for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil { + time.Sleep(10 * time.Millisecond) + } + } l.locked = true - for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil { - time.Sleep(10 * time.Millisecond) + l.counter++ + l.stateMutex.Unlock() +} + +// Lock locks the lockfile as a writer. Note that RLock() will be called if +// the lock is a read-only one. +func (l *lockfile) Lock() { + if l.ro { + l.RLock() + } else { + l.lock(unix.F_WRLCK) } } -// Unlock unlocks the lock file +// LockRead locks the lockfile as a reader. +func (l *lockfile) RLock() { + l.lock(unix.F_RDLCK) +} + +// Unlock unlocks the lockfile. func (l *lockfile) Unlock() { lk := unix.Flock_t{ Type: unix.F_UNLCK, @@ -64,19 +111,40 @@ func (l *lockfile) Unlock() { Len: 0, Pid: int32(os.Getpid()), } - for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil { - time.Sleep(10 * time.Millisecond) + l.stateMutex.Lock() + if l.locked == false { + // Panic when unlocking an unlocked lock. That's a violation + // of the lock semantics and will reveal such. + panic("calling Unlock on unlocked lock") + } + l.counter-- + if l.counter < 0 { + // Panic when the counter is negative. There is no way we can + // recover from a corrupted lock and we need to protect the + // storage from corruption. + panic(fmt.Sprintf("lock %q has been unlocked too often", l.file)) + } + if l.counter == 0 { + // We should only release the lock when the counter is 0 to + // avoid releasing read-locks too early; a given process may + // acquire a read lock multiple times. + l.locked = false + for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil { + time.Sleep(10 * time.Millisecond) + } + } + if l.locktype == unix.F_WRLCK { + l.writeMutex.Unlock() } - l.locked = false - l.mu.Unlock() + l.stateMutex.Unlock() } -// Check if lock is locked +// Locked checks if lockfile is locked. func (l *lockfile) Locked() bool { return l.locked } -// Touch updates the lock file with the UID of the user +// Touch updates the lock file with the UID of the user. func (l *lockfile) Touch() error { l.lw = stringid.GenerateRandomID() id := []byte(l.lw) @@ -98,7 +166,8 @@ func (l *lockfile) Touch() error { return nil } -// Modified indicates if the lock file has been updated since the last time it was loaded +// Modified indicates if the lockfile has been updated since the last time it +// was loaded. func (l *lockfile) Modified() (bool, error) { id := []byte(l.lw) _, err := unix.Seek(int(l.fd), 0, os.SEEK_SET) @@ -117,7 +186,7 @@ func (l *lockfile) Modified() (bool, error) { return l.lw != lw, nil } -// IsRWLock indicates if the lock file is a read-write lock +// IsReadWriteLock indicates if the lock file is a read-write lock. func (l *lockfile) IsReadWrite() bool { - return (l.locktype == unix.F_WRLCK) + return !l.ro } diff --git a/vendor/github.com/containers/storage/lockfile_windows.go b/vendor/github.com/containers/storage/lockfile_windows.go index 77490b851..a3821bfeb 100644 --- a/vendor/github.com/containers/storage/lockfile_windows.go +++ b/vendor/github.com/containers/storage/lockfile_windows.go @@ -23,6 +23,11 @@ func (l *lockfile) Lock() { l.locked = true } +func (l *lockfile) RLock() { + l.mu.Lock() + l.locked = true +} + func (l *lockfile) Unlock() { l.locked = false l.mu.Unlock() diff --git a/vendor/github.com/containers/storage/pkg/archive/archive_ffjson.go b/vendor/github.com/containers/storage/pkg/archive/archive_ffjson.go index 2ba44b85d..9b8103e4d 100644 --- a/vendor/github.com/containers/storage/pkg/archive/archive_ffjson.go +++ b/vendor/github.com/containers/storage/pkg/archive/archive_ffjson.go @@ -1,5 +1,5 @@ // Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT. -// source: ./pkg/archive/archive.go +// source: pkg/archive/archive.go package archive diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index 856c73e51..d53703d6b 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -566,10 +566,10 @@ func GetStore(options StoreOptions) (Store, error) { } if options.GraphRoot == "" { - return nil, ErrIncompleteOptions + return nil, errors.Wrap(ErrIncompleteOptions, "no storage root specified") } if options.RunRoot == "" { - return nil, ErrIncompleteOptions + return nil, errors.Wrap(ErrIncompleteOptions, "no storage runroot specified") } if err := os.MkdirAll(options.RunRoot, 0700); err != nil && !os.IsExist(err) { @@ -870,7 +870,8 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w gidMap := options.GIDMap if parent != "" { var ilayer *Layer - for _, lstore := range append([]ROLayerStore{rlstore}, rlstores...) { + for _, l := range append([]ROLayerStore{rlstore}, rlstores...) { + lstore := l if lstore != rlstore { lstore.Lock() defer lstore.Unlock() @@ -949,7 +950,8 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, o return nil, err } var ilayer *Layer - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1010,7 +1012,8 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, crea } var layer, parentLayer *Layer // Locate the image's top layer and its parent, if it has one. - for _, store := range append([]ROLayerStore{rlstore}, lstores...) { + for _, s := range append([]ROLayerStore{rlstore}, lstores...) { + store := s if store != rlstore { store.Lock() defer store.Unlock() @@ -1143,7 +1146,8 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat } } var cimage *Image - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1315,7 +1319,8 @@ func (s *store) Metadata(id string) (string, error) { if err != nil { return "", err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1336,7 +1341,8 @@ func (s *store) Metadata(id string) (string, error) { if err != nil { return "", err } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1375,7 +1381,8 @@ func (s *store) ListImageBigData(id string) ([]string, error) { if err != nil { return nil, err } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1400,7 +1407,8 @@ func (s *store) ImageBigDataSize(id, key string) (int64, error) { if err != nil { return -1, err } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1426,7 +1434,8 @@ func (s *store) ImageBigDataDigest(id, key string) (digest.Digest, error) { return "", err } stores = append([]ROImageStore{ristore}, stores...) - for _, ristore := range stores { + for _, r := range stores { + ristore := r ristore.Lock() defer ristore.Unlock() if modified, err := ristore.Modified(); modified || err != nil { @@ -1451,8 +1460,9 @@ func (s *store) ImageBigData(id, key string) ([]byte, error) { if err != nil { return nil, err } - for _, store := range append([]ROImageStore{istore}, istores...) { - store.Lock() + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s + store.RLock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { if err = store.Load(); err != nil { @@ -1495,7 +1505,8 @@ func (s *store) ImageSize(id string) (int64, error) { if err != nil { return -1, errors.Wrapf(err, "error loading additional layer stores") } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1516,7 +1527,8 @@ func (s *store) ImageSize(id string) (int64, error) { } // Look for the image's record. - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1603,7 +1615,8 @@ func (s *store) ContainerSize(id string) (int64, error) { if err != nil { return -1, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1772,7 +1785,8 @@ func (s *store) Exists(id string) bool { if err != nil { return false } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1793,7 +1807,8 @@ func (s *store) Exists(id string) bool { if err != nil { return false } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1895,7 +1910,8 @@ func (s *store) Names(id string) ([]string, error) { if err != nil { return nil, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1916,7 +1932,8 @@ func (s *store) Names(id string) ([]string, error) { if err != nil { return nil, err } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1955,7 +1972,8 @@ func (s *store) Lookup(name string) (string, error) { if err != nil { return "", err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -1976,7 +1994,8 @@ func (s *store) Lookup(name string) (string, error) { if err != nil { return "", err } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2486,7 +2505,8 @@ func (s *store) Changes(from, to string) ([]archive.Change, error) { if err != nil { return nil, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2510,7 +2530,8 @@ func (s *store) DiffSize(from, to string) (int64, error) { if err != nil { return -1, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2534,8 +2555,9 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro if err != nil { return nil, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { - store.Lock() + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s + store.RLock() if modified, err := store.Modified(); modified || err != nil { if err = store.Load(); err != nil { return nil, err @@ -2588,7 +2610,8 @@ func (s *store) layersByMappedDigest(m func(ROLayerStore, digest.Digest) ([]Laye if err != nil { return nil, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2634,7 +2657,8 @@ func (s *store) LayerSize(id string) (int64, error) { if err != nil { return -1, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2712,7 +2736,8 @@ func (s *store) Layers() ([]Layer, error) { return nil, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2740,7 +2765,8 @@ func (s *store) Images() ([]Image, error) { if err != nil { return nil, err } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2783,7 +2809,8 @@ func (s *store) Layer(id string) (*Layer, error) { if err != nil { return nil, err } - for _, store := range append([]ROLayerStore{lstore}, lstores...) { + for _, s := range append([]ROLayerStore{lstore}, lstores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2808,7 +2835,8 @@ func (s *store) Image(id string) (*Image, error) { if err != nil { return nil, err } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { @@ -2840,7 +2868,8 @@ func (s *store) ImagesByTopLayer(id string) ([]*Image, error) { if err != nil { return nil, err } - for _, store := range append([]ROImageStore{istore}, istores...) { + for _, s := range append([]ROImageStore{istore}, istores...) { + store := s store.Lock() defer store.Unlock() if modified, err := store.Modified(); modified || err != nil { |