Add more locking to storage drivers

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi 2017-02-17 15:46:19 -08:00
parent b1debf1374
commit fc1cf1911b
4 changed files with 37 additions and 1 deletions

View file

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

View file

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

View file

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

View file

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