diff --git a/storage/containers.go b/storage/containers.go index 00369f611f..7cc0038154 100644 --- a/storage/containers.go +++ b/storage/containers.go @@ -72,17 +72,12 @@ type rwContainerStore interface { containerBigDataStore flaggableStore - // Acquire a writer lock. - // The default unix implementation panics if: - // - opening the lockfile failed - // - tried to lock a read-only lock-file - Lock() + // startWriting makes sure the store is fresh, and locks it for writing. + // If this succeeds, the caller MUST call stopWriting(). + startWriting() error - // Unlock the lock. - // The default unix implementation panics if: - // - unlocking an unlocked lock - // - if the lock counter is corrupted - Unlock() + // 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(). @@ -209,6 +204,30 @@ func (c *Container) MountOpts() []string { } } +// 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 { + r.lockfile.Lock() + succeeded := false + defer func() { + if !succeeded { + r.lockfile.Unlock() + } + }() + + if err := r.ReloadIfChanged(); err != nil { + return err + } + + succeeded = true + return nil +} + +// 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 { diff --git a/storage/store.go b/storage/store.go index ddea1ef1b4..fc91399068 100644 --- a/storage/store.go +++ b/storage/store.go @@ -1119,11 +1119,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) } @@ -1154,11 +1153,10 @@ func (s *store) writeToAllStores(fn func(rlstore rwLayerStore, ristore rwImageSt if err := ristore.ReloadIfChanged(); err != nil { return err } - rcstore.Lock() - defer rcstore.Unlock() - if err := rcstore.ReloadIfChanged(); err != nil { + if err := rcstore.startWriting(); err != nil { return err } + defer rcstore.stopWriting() return fn(rlstore, ristore, rcstore) } @@ -1195,11 +1193,10 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w if err := rlstore.ReloadIfChanged(); err != nil { return nil, -1, err } - rcstore.Lock() - defer rcstore.Unlock() - if err := rcstore.ReloadIfChanged(); err != nil { + if err := rcstore.startWriting(); err != nil { return nil, -1, err } + defer rcstore.stopWriting() if options == nil { options = &LayerOptions{} }