Browse Source

Add more locking to storage drivers

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Tonis Tiigi 8 years ago
parent
commit
fc1cf1911b

+ 9 - 0
daemon/graphdriver/aufs/aufs.go

@@ -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 {

+ 10 - 1
daemon/graphdriver/devmapper/driver.go

@@ -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

+ 9 - 0
daemon/graphdriver/overlay/overlay.go

@@ -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

+ 9 - 0
daemon/graphdriver/overlay2/overlay.go

@@ -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 {