Add more locking to storage drivers
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
parent
b1debf1374
commit
fc1cf1911b
4 changed files with 37 additions and 1 deletions
|
@ -44,6 +44,7 @@ import (
|
||||||
"github.com/docker/docker/pkg/chrootarchive"
|
"github.com/docker/docker/pkg/chrootarchive"
|
||||||
"github.com/docker/docker/pkg/directory"
|
"github.com/docker/docker/pkg/directory"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
"github.com/docker/docker/pkg/locker"
|
||||||
mountpk "github.com/docker/docker/pkg/mount"
|
mountpk "github.com/docker/docker/pkg/mount"
|
||||||
|
|
||||||
"github.com/opencontainers/runc/libcontainer/label"
|
"github.com/opencontainers/runc/libcontainer/label"
|
||||||
|
@ -75,6 +76,7 @@ type Driver struct {
|
||||||
pathCacheLock sync.Mutex
|
pathCacheLock sync.Mutex
|
||||||
pathCache map[string]string
|
pathCache map[string]string
|
||||||
naiveDiff graphdriver.DiffDriver
|
naiveDiff graphdriver.DiffDriver
|
||||||
|
locker *locker.Locker
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init returns a new AUFS driver.
|
// Init returns a new AUFS driver.
|
||||||
|
@ -112,6 +114,7 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||||
gidMaps: gidMaps,
|
gidMaps: gidMaps,
|
||||||
pathCache: make(map[string]string),
|
pathCache: make(map[string]string),
|
||||||
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicAufs)),
|
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicAufs)),
|
||||||
|
locker: locker.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
|
rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
|
||||||
|
@ -304,6 +307,8 @@ func debugEBusy(mountPath string) (out []string, err error) {
|
||||||
|
|
||||||
// Remove will unmount and remove the given id.
|
// Remove will unmount and remove the given id.
|
||||||
func (a *Driver) Remove(id string) error {
|
func (a *Driver) Remove(id string) error {
|
||||||
|
a.locker.Lock(id)
|
||||||
|
defer a.locker.Unlock(id)
|
||||||
a.pathCacheLock.Lock()
|
a.pathCacheLock.Lock()
|
||||||
mountpoint, exists := a.pathCache[id]
|
mountpoint, exists := a.pathCache[id]
|
||||||
a.pathCacheLock.Unlock()
|
a.pathCacheLock.Unlock()
|
||||||
|
@ -377,6 +382,8 @@ func (a *Driver) Remove(id string) error {
|
||||||
// Get returns the rootfs path for the id.
|
// Get returns the rootfs path for the id.
|
||||||
// This will mount the dir at its given path
|
// This will mount the dir at its given path
|
||||||
func (a *Driver) Get(id, mountLabel string) (string, error) {
|
func (a *Driver) Get(id, mountLabel string) (string, error) {
|
||||||
|
a.locker.Lock(id)
|
||||||
|
defer a.locker.Unlock(id)
|
||||||
parents, err := a.getParentLayerPaths(id)
|
parents, err := a.getParentLayerPaths(id)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -412,6 +419,8 @@ func (a *Driver) Get(id, mountLabel string) (string, error) {
|
||||||
|
|
||||||
// Put unmounts and updates list of active mounts.
|
// Put unmounts and updates list of active mounts.
|
||||||
func (a *Driver) Put(id string) error {
|
func (a *Driver) Put(id string) error {
|
||||||
|
a.locker.Lock(id)
|
||||||
|
defer a.locker.Unlock(id)
|
||||||
a.pathCacheLock.Lock()
|
a.pathCacheLock.Lock()
|
||||||
m, exists := a.pathCache[id]
|
m, exists := a.pathCache[id]
|
||||||
if !exists {
|
if !exists {
|
||||||
|
|
|
@ -14,8 +14,9 @@ import (
|
||||||
"github.com/docker/docker/daemon/graphdriver"
|
"github.com/docker/docker/daemon/graphdriver"
|
||||||
"github.com/docker/docker/pkg/devicemapper"
|
"github.com/docker/docker/pkg/devicemapper"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
"github.com/docker/docker/pkg/locker"
|
||||||
"github.com/docker/docker/pkg/mount"
|
"github.com/docker/docker/pkg/mount"
|
||||||
"github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -29,6 +30,7 @@ type Driver struct {
|
||||||
uidMaps []idtools.IDMap
|
uidMaps []idtools.IDMap
|
||||||
gidMaps []idtools.IDMap
|
gidMaps []idtools.IDMap
|
||||||
ctr *graphdriver.RefCounter
|
ctr *graphdriver.RefCounter
|
||||||
|
locker *locker.Locker
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init creates a driver with the given home and the set of options.
|
// Init creates a driver with the given home and the set of options.
|
||||||
|
@ -48,6 +50,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||||
uidMaps: uidMaps,
|
uidMaps: uidMaps,
|
||||||
gidMaps: gidMaps,
|
gidMaps: gidMaps,
|
||||||
ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
|
ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
|
||||||
|
locker: locker.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
|
return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
|
||||||
|
@ -142,6 +145,8 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
|
||||||
|
|
||||||
// Remove removes a device with a given id, unmounts the filesystem.
|
// Remove removes a device with a given id, unmounts the filesystem.
|
||||||
func (d *Driver) Remove(id string) error {
|
func (d *Driver) Remove(id string) error {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
if !d.DeviceSet.HasDevice(id) {
|
if !d.DeviceSet.HasDevice(id) {
|
||||||
// Consider removing a non-existing device a no-op
|
// Consider removing a non-existing device a no-op
|
||||||
// This is useful to be able to progress on container removal
|
// This is useful to be able to progress on container removal
|
||||||
|
@ -164,6 +169,8 @@ func (d *Driver) Remove(id string) error {
|
||||||
|
|
||||||
// Get mounts a device with given id into the root filesystem
|
// Get mounts a device with given id into the root filesystem
|
||||||
func (d *Driver) Get(id, mountLabel string) (string, error) {
|
func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
mp := path.Join(d.home, "mnt", id)
|
mp := path.Join(d.home, "mnt", id)
|
||||||
rootFs := path.Join(mp, "rootfs")
|
rootFs := path.Join(mp, "rootfs")
|
||||||
if count := d.ctr.Increment(mp); count > 1 {
|
if count := d.ctr.Increment(mp); count > 1 {
|
||||||
|
@ -214,6 +221,8 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
|
||||||
|
|
||||||
// Put unmounts a device and removes it.
|
// Put unmounts a device and removes it.
|
||||||
func (d *Driver) Put(id string) error {
|
func (d *Driver) Put(id string) error {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
mp := path.Join(d.home, "mnt", id)
|
mp := path.Join(d.home, "mnt", id)
|
||||||
if count := d.ctr.Decrement(mp); count > 0 {
|
if count := d.ctr.Decrement(mp); count > 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/docker/docker/pkg/fsutils"
|
"github.com/docker/docker/pkg/fsutils"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
"github.com/docker/docker/pkg/locker"
|
||||||
"github.com/docker/docker/pkg/mount"
|
"github.com/docker/docker/pkg/mount"
|
||||||
"github.com/opencontainers/runc/libcontainer/label"
|
"github.com/opencontainers/runc/libcontainer/label"
|
||||||
)
|
)
|
||||||
|
@ -97,6 +98,7 @@ type Driver struct {
|
||||||
gidMaps []idtools.IDMap
|
gidMaps []idtools.IDMap
|
||||||
ctr *graphdriver.RefCounter
|
ctr *graphdriver.RefCounter
|
||||||
supportsDType bool
|
supportsDType bool
|
||||||
|
locker *locker.Locker
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -154,6 +156,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||||
gidMaps: gidMaps,
|
gidMaps: gidMaps,
|
||||||
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
|
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
|
||||||
supportsDType: supportsDType,
|
supportsDType: supportsDType,
|
||||||
|
locker: locker.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return NaiveDiffDriverWithApply(d, uidMaps, gidMaps), nil
|
return NaiveDiffDriverWithApply(d, uidMaps, gidMaps), nil
|
||||||
|
@ -334,6 +337,8 @@ func (d *Driver) dir(id string) string {
|
||||||
|
|
||||||
// Remove cleans the directories that are created for this id.
|
// Remove cleans the directories that are created for this id.
|
||||||
func (d *Driver) Remove(id string) error {
|
func (d *Driver) Remove(id string) error {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
if err := os.RemoveAll(d.dir(id)); err != nil && !os.IsNotExist(err) {
|
if err := os.RemoveAll(d.dir(id)); err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -342,6 +347,8 @@ func (d *Driver) Remove(id string) error {
|
||||||
|
|
||||||
// Get creates and mounts the required file system for the given id and returns the mount path.
|
// Get creates and mounts the required file system for the given id and returns the mount path.
|
||||||
func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
dir := d.dir(id)
|
dir := d.dir(id)
|
||||||
if _, err := os.Stat(dir); err != nil {
|
if _, err := os.Stat(dir); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -389,6 +396,8 @@ func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
||||||
|
|
||||||
// Put unmounts the mount path created for the give id.
|
// Put unmounts the mount path created for the give id.
|
||||||
func (d *Driver) Put(id string) error {
|
func (d *Driver) Put(id string) error {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
// If id has a root, just return
|
// If id has a root, just return
|
||||||
if _, err := os.Stat(path.Join(d.dir(id), "root")); err == nil {
|
if _, err := os.Stat(path.Join(d.dir(id), "root")); err == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/docker/docker/pkg/directory"
|
"github.com/docker/docker/pkg/directory"
|
||||||
"github.com/docker/docker/pkg/fsutils"
|
"github.com/docker/docker/pkg/fsutils"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
"github.com/docker/docker/pkg/locker"
|
||||||
"github.com/docker/docker/pkg/mount"
|
"github.com/docker/docker/pkg/mount"
|
||||||
"github.com/docker/docker/pkg/parsers"
|
"github.com/docker/docker/pkg/parsers"
|
||||||
"github.com/docker/docker/pkg/parsers/kernel"
|
"github.com/docker/docker/pkg/parsers/kernel"
|
||||||
|
@ -98,6 +99,7 @@ type Driver struct {
|
||||||
options overlayOptions
|
options overlayOptions
|
||||||
naiveDiff graphdriver.DiffDriver
|
naiveDiff graphdriver.DiffDriver
|
||||||
supportsDType bool
|
supportsDType bool
|
||||||
|
locker *locker.Locker
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -180,6 +182,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||||
gidMaps: gidMaps,
|
gidMaps: gidMaps,
|
||||||
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
|
ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
|
||||||
supportsDType: supportsDType,
|
supportsDType: supportsDType,
|
||||||
|
locker: locker.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps)
|
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps)
|
||||||
|
@ -451,6 +454,8 @@ func (d *Driver) getLowerDirs(id string) ([]string, error) {
|
||||||
|
|
||||||
// Remove cleans the directories that are created for this id.
|
// Remove cleans the directories that are created for this id.
|
||||||
func (d *Driver) Remove(id string) error {
|
func (d *Driver) Remove(id string) error {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
dir := d.dir(id)
|
dir := d.dir(id)
|
||||||
lid, err := ioutil.ReadFile(path.Join(dir, "link"))
|
lid, err := ioutil.ReadFile(path.Join(dir, "link"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -467,6 +472,8 @@ func (d *Driver) Remove(id string) error {
|
||||||
|
|
||||||
// Get creates and mounts the required file system for the given id and returns the mount path.
|
// Get creates and mounts the required file system for the given id and returns the mount path.
|
||||||
func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
dir := d.dir(id)
|
dir := d.dir(id)
|
||||||
if _, err := os.Stat(dir); err != nil {
|
if _, err := os.Stat(dir); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -553,6 +560,8 @@ func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
||||||
|
|
||||||
// Put unmounts the mount path created for the give id.
|
// Put unmounts the mount path created for the give id.
|
||||||
func (d *Driver) Put(id string) error {
|
func (d *Driver) Put(id string) error {
|
||||||
|
d.locker.Lock(id)
|
||||||
|
defer d.locker.Unlock(id)
|
||||||
dir := d.dir(id)
|
dir := d.dir(id)
|
||||||
_, err := ioutil.ReadFile(path.Join(dir, lowerFile))
|
_, err := ioutil.ReadFile(path.Join(dir, lowerFile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Add table
Reference in a new issue