Browse code

Use fine-grained locks for plugin loading.

This helps ensure that only one thing is trying to intialize a plugin at
once while also keeping the global lock free during initialization.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2016/01/21 02:12:51
Showing 1 changed files
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"fmt"
7 7
 	"sync"
8 8
 
9
+	"github.com/docker/docker/pkg/locker"
9 10
 	"github.com/docker/docker/pkg/plugins"
10 11
 	"github.com/docker/docker/volume"
11 12
 )
... ...
@@ -13,7 +14,7 @@ import (
13 13
 // currently created by hand. generation tool would generate this like:
14 14
 // $ extpoint-gen Driver > volume/extpoint.go
15 15
 
16
-var drivers = &driverExtpoint{extensions: make(map[string]volume.Driver)}
16
+var drivers = &driverExtpoint{extensions: make(map[string]volume.Driver), driverLock: &locker.Locker{}}
17 17
 
18 18
 const extName = "VolumeDriver"
19 19
 
... ...
@@ -49,16 +50,19 @@ type volumeDriver interface {
49 49
 type driverExtpoint struct {
50 50
 	extensions map[string]volume.Driver
51 51
 	sync.Mutex
52
+	driverLock *locker.Locker
52 53
 }
53 54
 
54 55
 // Register associates the given driver to the given name, checking if
55 56
 // the name is already associated
56 57
 func Register(extension volume.Driver, name string) bool {
57
-	drivers.Lock()
58
-	defer drivers.Unlock()
59 58
 	if name == "" {
60 59
 		return false
61 60
 	}
61
+
62
+	drivers.Lock()
63
+	defer drivers.Unlock()
64
+
62 65
 	_, exists := drivers.extensions[name]
63 66
 	if exists {
64 67
 		return false
... ...
@@ -71,6 +75,7 @@ func Register(extension volume.Driver, name string) bool {
71 71
 func Unregister(name string) bool {
72 72
 	drivers.Lock()
73 73
 	defer drivers.Unlock()
74
+
74 75
 	_, exists := drivers.extensions[name]
75 76
 	if !exists {
76 77
 		return false
... ...
@@ -83,12 +88,16 @@ func Unregister(name string) bool {
83 83
 // driver with the given name has not been registered it checks if
84 84
 // there is a VolumeDriver plugin available with the given name.
85 85
 func Lookup(name string) (volume.Driver, error) {
86
+	drivers.driverLock.Lock(name)
87
+	defer drivers.driverLock.Unlock(name)
88
+
86 89
 	drivers.Lock()
87 90
 	ext, ok := drivers.extensions[name]
88 91
 	drivers.Unlock()
89 92
 	if ok {
90 93
 		return ext, nil
91 94
 	}
95
+
92 96
 	pl, err := plugins.Get(name, extName)
93 97
 	if err != nil {
94 98
 		return nil, fmt.Errorf("Error looking up volume plugin %s: %v", name, err)
... ...
@@ -118,9 +127,11 @@ func GetDriver(name string) (volume.Driver, error) {
118 118
 // If no driver is registered, empty string list will be returned.
119 119
 func GetDriverList() []string {
120 120
 	var driverList []string
121
+	drivers.Lock()
121 122
 	for driverName := range drivers.extensions {
122 123
 		driverList = append(driverList, driverName)
123 124
 	}
125
+	drivers.Unlock()
124 126
 	return driverList
125 127
 }
126 128
 
... ...
@@ -144,6 +155,7 @@ func GetAllDrivers() ([]volume.Driver, error) {
144 144
 		if ok {
145 145
 			continue
146 146
 		}
147
+
147 148
 		ext = NewVolumeDriver(p.Name, p.Client)
148 149
 		drivers.extensions[p.Name] = ext
149 150
 		ds = append(ds, ext)