The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/2890

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 53c312d1f985d94c6ccd0807744f42482730259d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@ubuntu.com>
Date: Wed, 15 Feb 2017 17:38:53 +0100
Subject: [PATCH] storage: lock Container{U,M}ount for zfs, lvm

Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
---
 lxd/storage.go       |  4 +--
 lxd/storage_btrfs.go | 14 +++++-----
 lxd/storage_lvm.go   | 72 +++++++++++++++++++++++++++++++++++++++------------
 lxd/storage_zfs.go   | 73 +++++++++++++++++++++++++++++++++++++++-------------
 4 files changed, 119 insertions(+), 44 deletions(-)

diff --git a/lxd/storage.go b/lxd/storage.go
index f90cc74..9023031 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -22,8 +22,8 @@ import (
        log "gopkg.in/inconshreveable/log15.v2"
 )
 
-var imageCreationInPool = map[string]chan bool{}
-var imageCreationInPoolLock sync.Mutex
+var lxdStorageLockMap = map[string]chan bool{}
+var lxdStorageLock sync.Mutex
 
 /* Some interesting filesystems */
 const (
diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index d847f34..ebcecdb 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -571,23 +571,23 @@ func (s *storageBtrfs) ContainerCreateFromImage(container 
container, fingerprint
        // ${LXD_DIR}/images/<fingerprint>
        imageMntPoint := getImageMountPoint(s.pool.Name, fingerprint)
        imageStoragePoolLockID := fmt.Sprintf("%s/%s", s.pool.Name, fingerprint)
-       imageCreationInPoolLock.Lock()
-       if waitChannel, ok := imageCreationInPool[imageStoragePoolLockID]; ok {
-               imageCreationInPoolLock.Unlock()
+       lxdStorageLock.Lock()
+       if waitChannel, ok := lxdStorageLockMap[imageStoragePoolLockID]; ok {
+               lxdStorageLock.Unlock()
                if _, ok := <-waitChannel; ok {
                        shared.LogWarnf("Value transmitted over image lock 
semaphore?")
                }
        } else {
-               imageCreationInPool[imageStoragePoolLockID] = make(chan bool)
+               lxdStorageLockMap[imageStoragePoolLockID] = make(chan bool)
                var imgerr error
                if !shared.PathExists(imageMntPoint) || 
!s.isBtrfsPoolVolume(imageMntPoint) {
                        imgerr = s.ImageCreate(fingerprint)
                }
-               if waitChannel, ok := 
imageCreationInPool[imageStoragePoolLockID]; ok {
+               if waitChannel, ok := 
lxdStorageLockMap[imageStoragePoolLockID]; ok {
                        close(waitChannel)
-                       delete(imageCreationInPool, imageStoragePoolLockID)
+                       delete(lxdStorageLockMap, imageStoragePoolLockID)
                }
-               imageCreationInPoolLock.Unlock()
+               lxdStorageLock.Unlock()
                if imgerr != nil {
                        return imgerr
                }
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 4afda74..7ae48ce 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -547,23 +547,23 @@ func (s *storageLvm) ContainerCreateFromImage(container 
container, fingerprint s
        imageLvmDevPath := getLvmDevPath(s.pool.Name, 
storagePoolVolumeApiEndpointImages, fingerprint)
 
        imageStoragePoolLockID := fmt.Sprintf("%s/%s", s.pool.Name, fingerprint)
-       imageCreationInPoolLock.Lock()
-       if waitChannel, ok := imageCreationInPool[imageStoragePoolLockID]; ok {
-               imageCreationInPoolLock.Unlock()
+       lxdStorageLock.Lock()
+       if waitChannel, ok := lxdStorageLockMap[imageStoragePoolLockID]; ok {
+               lxdStorageLock.Unlock()
                if _, ok := <-waitChannel; ok {
                        shared.LogWarnf("Value transmitted over image lock 
semaphore?")
                }
        } else {
-               imageCreationInPool[imageStoragePoolLockID] = make(chan bool)
+               lxdStorageLockMap[imageStoragePoolLockID] = make(chan bool)
                var imgerr error
                if !shared.PathExists(imageMntPoint) || 
!shared.PathExists(imageLvmDevPath) {
                        imgerr = s.ImageCreate(fingerprint)
                }
-               if waitChannel, ok := 
imageCreationInPool[imageStoragePoolLockID]; ok {
+               if waitChannel, ok := 
lxdStorageLockMap[imageStoragePoolLockID]; ok {
                        close(waitChannel)
-                       delete(imageCreationInPool, imageStoragePoolLockID)
+                       delete(lxdStorageLockMap, imageStoragePoolLockID)
                }
-               imageCreationInPoolLock.Unlock()
+               lxdStorageLock.Unlock()
                if imgerr != nil {
                        return imgerr
                }
@@ -759,31 +759,69 @@ func (s *storageLvm) ContainerMount(name string, path 
string) (bool, error) {
        mountOptions := s.volume.Config["block.mount_options"]
        containerMntPoint := getContainerMountPoint(s.pool.Name, name)
 
-       if shared.IsMountPoint(containerMntPoint) {
+       containerMountLockID := fmt.Sprintf("mount/%s/%s", s.pool.Name, name)
+       lxdStorageLock.Lock()
+       if waitChannel, ok := lxdStorageLockMap[containerMountLockID]; ok {
+               lxdStorageLock.Unlock()
+               if _, ok := <-waitChannel; ok {
+                       shared.LogWarnf("Value transmitted over image lock 
semaphore?")
+               }
+               // Give the benefit of the doubt and assume that the other
+               // thread actually succeeded in mounting the storage volume.
                return false, nil
        }
 
-       err := tryMount(containerLvmPath, containerMntPoint, lvFsType, 0, 
mountOptions)
-       if err != nil {
-               return false, fmt.Errorf("Error mounting snapshot LV path='%s': 
%s", path, err)
+       lxdStorageLockMap[containerMountLockID] = make(chan bool)
+       var imgerr error
+       ourMount := false
+       if !shared.IsMountPoint(containerMntPoint) {
+               imgerr = tryMount(containerLvmPath, containerMntPoint, 
lvFsType, 0, mountOptions)
+               ourMount = true
+       }
+       if waitChannel, ok := lxdStorageLockMap[containerMountLockID]; ok {
+               close(waitChannel)
+               delete(lxdStorageLockMap, containerMountLockID)
+       }
+       lxdStorageLock.Unlock()
+       if imgerr != nil {
+               return false, imgerr
        }
 
-       return true, nil
+       return ourMount, nil
 }
 
 func (s *storageLvm) ContainerUmount(name string, path string) (bool, error) {
        containerMntPoint := getContainerMountPoint(s.pool.Name, name)
 
-       if !shared.IsMountPoint(containerMntPoint) {
+       containerUmountLockID := fmt.Sprintf("umount/%s/%s", s.pool.Name, name)
+       lxdStorageLock.Lock()
+       if waitChannel, ok := lxdStorageLockMap[containerUmountLockID]; ok {
+               lxdStorageLock.Unlock()
+               if _, ok := <-waitChannel; ok {
+                       shared.LogWarnf("Value transmitted over image lock 
semaphore?")
+               }
+               // Give the benefit of the doubt and assume that the other
+               // thread actually succeeded in unmounting the storage volume.
                return false, nil
        }
 
-       err := tryUnmount(containerMntPoint, 0)
-       if err != nil {
-               return false, fmt.Errorf("failed to unmount container path 
'%s': %s", path, err)
+       lxdStorageLockMap[containerUmountLockID] = make(chan bool)
+       var imgerr error
+       ourUmount := false
+       if shared.IsMountPoint(containerMntPoint) {
+               imgerr = tryUnmount(containerMntPoint, 0)
+               ourUmount = true
+       }
+       if waitChannel, ok := lxdStorageLockMap[containerUmountLockID]; ok {
+               close(waitChannel)
+               delete(lxdStorageLockMap, containerUmountLockID)
+       }
+       lxdStorageLock.Unlock()
+       if imgerr != nil {
+               return false, imgerr
        }
 
-       return true, nil
+       return ourUmount, nil
 }
 
 func (s *storageLvm) ContainerRename(container container, newContainerName 
string) error {
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 0e83884..0ad6eda 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -398,33 +398,70 @@ func (s *storageZfs) ContainerMount(name string, path 
string) (bool, error) {
        fs := fmt.Sprintf("containers/%s", name)
        containerPoolVolumeMntPoint := getContainerMountPoint(s.pool.Name, name)
 
-       // Just in case the container filesystem got unmounted
-       if shared.IsMountPoint(containerPoolVolumeMntPoint) {
+       containerMountLockID := fmt.Sprintf("mount/%s/%s", s.pool.Name, name)
+       lxdStorageLock.Lock()
+       if waitChannel, ok := lxdStorageLockMap[containerMountLockID]; ok {
+               lxdStorageLock.Unlock()
+               if _, ok := <-waitChannel; ok {
+                       shared.LogWarnf("Value transmitted over image lock 
semaphore?")
+               }
+               // Give the benefit of the doubt and assume that the other
+               // thread actually succeeded in mounting the storage volume.
                return false, nil
        }
 
-       err := s.zfsPoolVolumeMount(fs)
-       if err != nil {
-               return false, err
+       lxdStorageLockMap[containerMountLockID] = make(chan bool)
+       var imgerr error
+       ourMount := false
+       if !shared.IsMountPoint(containerPoolVolumeMntPoint) {
+               imgerr = s.zfsPoolVolumeMount(fs)
+               ourMount = true
+       }
+       if waitChannel, ok := lxdStorageLockMap[containerMountLockID]; ok {
+               close(waitChannel)
+               delete(lxdStorageLockMap, containerMountLockID)
+       }
+       lxdStorageLock.Unlock()
+       if imgerr != nil {
+               return false, imgerr
        }
 
-       return true, nil
+       return ourMount, nil
 }
 
 func (s *storageZfs) ContainerUmount(name string, path string) (bool, error) {
        fs := fmt.Sprintf("containers/%s", name)
        containerPoolVolumeMntPoint := getContainerMountPoint(s.pool.Name, name)
 
-       if !shared.IsMountPoint(containerPoolVolumeMntPoint) {
+       containerUmountLockID := fmt.Sprintf("umount/%s/%s", s.pool.Name, name)
+       lxdStorageLock.Lock()
+       if waitChannel, ok := lxdStorageLockMap[containerUmountLockID]; ok {
+               lxdStorageLock.Unlock()
+               if _, ok := <-waitChannel; ok {
+                       shared.LogWarnf("Value transmitted over image lock 
semaphore?")
+               }
+               // Give the benefit of the doubt and assume that the other
+               // thread actually succeeded in unmounting the storage volume.
                return false, nil
        }
 
-       err := s.zfsPoolVolumeUmount(fs)
-       if err != nil {
-               return false, err
+       lxdStorageLockMap[containerUmountLockID] = make(chan bool)
+       var imgerr error
+       ourUmount := false
+       if shared.IsMountPoint(containerPoolVolumeMntPoint) {
+               imgerr = s.zfsPoolVolumeUmount(fs)
+               ourUmount = true
+       }
+       if waitChannel, ok := lxdStorageLockMap[containerUmountLockID]; ok {
+               close(waitChannel)
+               delete(lxdStorageLockMap, containerUmountLockID)
+       }
+       lxdStorageLock.Unlock()
+       if imgerr != nil {
+               return false, imgerr
        }
 
-       return true, nil
+       return ourUmount, nil
 }
 
 // Things we do have to care about
@@ -477,23 +514,23 @@ func (s *storageZfs) ContainerCreateFromImage(container 
container, fingerprint s
        fsImage := fmt.Sprintf("images/%s", fingerprint)
 
        imageStoragePoolLockID := fmt.Sprintf("%s/%s", s.pool.Name, fingerprint)
-       imageCreationInPoolLock.Lock()
-       if waitChannel, ok := imageCreationInPool[imageStoragePoolLockID]; ok {
-               imageCreationInPoolLock.Unlock()
+       lxdStorageLock.Lock()
+       if waitChannel, ok := lxdStorageLockMap[imageStoragePoolLockID]; ok {
+               lxdStorageLock.Unlock()
                if _, ok := <-waitChannel; ok {
                        shared.LogWarnf("Value transmitted over image lock 
semaphore?")
                }
        } else {
-               imageCreationInPool[imageStoragePoolLockID] = make(chan bool)
+               lxdStorageLockMap[imageStoragePoolLockID] = make(chan bool)
                var imgerr error
                if !s.zfsPoolVolumeExists(fsImage) {
                        imgerr = s.ImageCreate(fingerprint)
                }
-               if waitChannel, ok := 
imageCreationInPool[imageStoragePoolLockID]; ok {
+               if waitChannel, ok := 
lxdStorageLockMap[imageStoragePoolLockID]; ok {
                        close(waitChannel)
-                       delete(imageCreationInPool, imageStoragePoolLockID)
+                       delete(lxdStorageLockMap, imageStoragePoolLockID)
                }
-               imageCreationInPoolLock.Unlock()
+               lxdStorageLock.Unlock()
                if imgerr != nil {
                        return imgerr
                }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to