Don't hold lock around volume driver for volume create.

Signed-off-by: Stephen Rust <srust@blockbridge.com>
This commit is contained in:
Stephen Rust 2015-08-28 14:16:18 -04:00
parent b1cb1b1df4
commit 0ef740a5bf
2 changed files with 46 additions and 3 deletions

View file

@ -133,11 +133,12 @@ func getVolumeDriver(name string) (volume.Driver, error) {
// Create tries to find an existing volume with the given name or create a new one from the passed in driver
func (s *volumeStore) Create(name, driverName string, opts map[string]string) (volume.Volume, error) {
s.mu.Lock()
defer s.mu.Unlock()
if vc, exists := s.vols[name]; exists {
return vc.Volume, nil
v := vc.Volume
s.mu.Unlock()
return v, nil
}
s.mu.Unlock()
vd, err := getVolumeDriver(driverName)
if err != nil {
@ -149,7 +150,10 @@ func (s *volumeStore) Create(name, driverName string, opts map[string]string) (v
return nil, err
}
s.mu.Lock()
s.vols[v.Name()] = &volumeCounter{v, 0}
s.mu.Unlock()
return v, nil
}

View file

@ -9,8 +9,10 @@ import (
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/go-check/check"
)
@ -271,3 +273,40 @@ func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriverCheckBindL
c.Assert(s.ec.mounts, check.Equals, 1)
c.Assert(s.ec.unmounts, check.Equals, 1)
}
// Make sure a request to use a down driver doesn't block other requests
func (s *DockerExternalVolumeSuite) TestStartExternalVolumeDriverLookupNotBlocked(c *check.C) {
specPath := "/etc/docker/plugins/down-driver.spec"
err := ioutil.WriteFile("/etc/docker/plugins/down-driver.spec", []byte("tcp://127.0.0.7:9999"), 0644)
c.Assert(err, check.IsNil)
defer os.RemoveAll(specPath)
chCmd1 := make(chan struct{})
chCmd2 := make(chan error)
cmd1 := exec.Command(dockerBinary, "volume", "create", "-d", "down-driver")
cmd2 := exec.Command(dockerBinary, "volume", "create")
c.Assert(cmd1.Start(), check.IsNil)
defer cmd1.Process.Kill()
time.Sleep(100 * time.Millisecond) // ensure API has been called
c.Assert(cmd2.Start(), check.IsNil)
go func() {
cmd1.Wait()
close(chCmd1)
}()
go func() {
chCmd2 <- cmd2.Wait()
}()
select {
case <-chCmd1:
cmd2.Process.Kill()
c.Fatalf("volume create with down driver finished unexpectedly")
case err := <-chCmd2:
c.Assert(err, check.IsNil, check.Commentf("error creating volume"))
case <-time.After(5 * time.Second):
c.Fatal("volume creates are blocked by previous create requests when previous driver is down")
cmd2.Process.Kill()
}
}