Vendor in latest containers/storage and containers/image

Update container/image to address a commit error when copying layers and metadata.
This change may require users to recreate containers.

container/storage added some new lock protection to prevent possible deadlock and
data corruption.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1381
Approved by: mheon
This commit is contained in:
Daniel J Walsh
2018-08-30 17:27:54 -04:00
committed by Atomic Bot
parent 89a580b374
commit 82a6b373a5
15 changed files with 174 additions and 23 deletions

View File

@@ -192,6 +192,9 @@ func (r *containerStore) Load() error {
}
func (r *containerStore) Save() error {
if !r.Locked() {
return errors.New("container store is not locked")
}
rpath := r.containerspath()
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil {
return err
@@ -560,3 +563,7 @@ func (r *containerStore) IsReadWrite() bool {
func (r *containerStore) TouchedSince(when time.Time) bool {
return r.lockfile.TouchedSince(when)
}
func (r *containerStore) Locked() bool {
return r.lockfile.Locked()
}

View File

@@ -219,6 +219,9 @@ func (r *imageStore) Save() error {
if !r.IsReadWrite() {
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify the image store at %q", r.imagespath())
}
if !r.Locked() {
return errors.New("image store is not locked")
}
rpath := r.imagespath()
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil {
return err
@@ -701,3 +704,7 @@ func (r *imageStore) IsReadWrite() bool {
func (r *imageStore) TouchedSince(when time.Time) bool {
return r.lockfile.TouchedSince(when)
}
func (r *imageStore) Locked() bool {
return r.lockfile.Locked()
}

View File

@@ -371,6 +371,9 @@ func (r *layerStore) Save() error {
if !r.IsReadWrite() {
return errors.Wrapf(ErrStoreIsReadOnly, "not allowed to modify the layer store at %q", r.layerspath())
}
if !r.Locked() {
return errors.New("layer store is not locked")
}
rpath := r.layerspath()
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil {
return err
@@ -1181,3 +1184,7 @@ func (r *layerStore) IsReadWrite() bool {
func (r *layerStore) TouchedSince(when time.Time) bool {
return r.lockfile.TouchedSince(when)
}
func (r *layerStore) Locked() bool {
return r.lockfile.Locked()
}

View File

@@ -28,6 +28,9 @@ type Locker interface {
// IsReadWrite() checks if the lock file is read-write
IsReadWrite() bool
// Locked() checks if lock is locked
Locked() bool
}
var (

View File

@@ -25,9 +25,9 @@ func getLockFile(path string, ro bool) (Locker, error) {
}
unix.CloseOnExec(fd)
if ro {
return &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_RDLCK}, nil
return &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_RDLCK, locked: false}, nil
}
return &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_WRLCK}, nil
return &lockfile{file: path, fd: uintptr(fd), lw: stringid.GenerateRandomID(), locktype: unix.F_WRLCK, locked: false}, nil
}
type lockfile struct {
@@ -36,6 +36,7 @@ type lockfile struct {
fd uintptr
lw string
locktype int16
locked bool
}
// Lock locks the lock file
@@ -48,6 +49,7 @@ func (l *lockfile) Lock() {
Pid: int32(os.Getpid()),
}
l.mu.Lock()
l.locked = true
for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil {
time.Sleep(10 * time.Millisecond)
}
@@ -65,9 +67,15 @@ func (l *lockfile) Unlock() {
for unix.FcntlFlock(l.fd, unix.F_SETLKW, &lk) != nil {
time.Sleep(10 * time.Millisecond)
}
l.locked = false
l.mu.Unlock()
}
// Check if lock is locked
func (l *lockfile) Locked() bool {
return l.locked
}
// Touch updates the lock file with the UID of the user
func (l *lockfile) Touch() error {
l.lw = stringid.GenerateRandomID()

View File

@@ -9,18 +9,29 @@ import (
)
func getLockFile(path string, ro bool) (Locker, error) {
return &lockfile{}, nil
return &lockfile{locked: false}, nil
}
type lockfile struct {
mu sync.Mutex
file string
mu sync.Mutex
file string
locked bool
}
func (l *lockfile) Lock() {
l.mu.Lock()
l.locked = true
}
func (l *lockfile) Unlock() {
l.locked = false
l.mu.Unlock()
}
func (l *lockfile) Locked() bool {
return l.locked
}
func (l *lockfile) Modified() (bool, error) {
return false, nil
}

View File

@@ -0,0 +1,97 @@
// +build ignore
// Simple tool to create an archive stream from an old and new directory
//
// By default it will stream the comparison of two temporary directories with junk files
package main
import (
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"github.com/containers/storage/pkg/archive"
"github.com/sirupsen/logrus"
)
var (
flDebug = flag.Bool("D", false, "debugging output")
flNewDir = flag.String("newdir", "", "")
flOldDir = flag.String("olddir", "", "")
log = logrus.New()
)
func main() {
flag.Usage = func() {
fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)")
fmt.Printf("%s [OPTIONS]\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
log.Out = os.Stderr
if (len(os.Getenv("DEBUG")) > 0) || *flDebug {
logrus.SetLevel(logrus.DebugLevel)
}
var newDir, oldDir string
if len(*flNewDir) == 0 {
var err error
newDir, err = ioutil.TempDir("", "storage-test-newDir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(newDir)
if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil {
log.Fatal(err)
}
} else {
newDir = *flNewDir
}
if len(*flOldDir) == 0 {
oldDir, err := ioutil.TempDir("", "storage-test-oldDir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(oldDir)
} else {
oldDir = *flOldDir
}
changes, err := archive.ChangesDirs(newDir, oldDir)
if err != nil {
log.Fatal(err)
}
a, err := archive.ExportChanges(newDir, changes)
if err != nil {
log.Fatal(err)
}
defer a.Close()
i, err := io.Copy(os.Stdout, a)
if err != nil && err != io.EOF {
log.Fatal(err)
}
fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i)
}
func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
fileData := []byte("fooo")
for n := 0; n < numberOfFiles; n++ {
fileName := fmt.Sprintf("file-%d", n)
if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
return 0, err
}
if makeLinks {
if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
return 0, err
}
}
}
totalSize := numberOfFiles * len(fileData)
return totalSize, nil
}