Browse code

Make sure we call every graph init with the same root path.

Remove O(n^2) check for several prior configured drivers.

Signed-off-by: David Calavera <david.calavera@gmail.com>

David Calavera authored on 2016/03/10 08:23:31
Showing 1 changed files
... ...
@@ -146,46 +146,53 @@ func getBuiltinDriver(name, home string, options []string, uidMaps, gidMaps []id
146 146
 }
147 147
 
148 148
 // New creates the driver and initializes it at the specified root.
149
-func New(root string, name string, options []string, uidMaps, gidMaps []idtools.IDMap) (driver Driver, err error) {
149
+func New(root string, name string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) {
150 150
 	if name != "" {
151 151
 		logrus.Debugf("[graphdriver] trying provided driver %q", name) // so the logs show specified driver
152 152
 		return GetDriver(name, root, options, uidMaps, gidMaps)
153 153
 	}
154 154
 
155 155
 	// Guess for prior driver
156
-	priorDrivers := scanPriorDrivers(root)
156
+	driversMap := scanPriorDrivers(root)
157 157
 	for _, name := range priority {
158 158
 		if name == "vfs" {
159 159
 			// don't use vfs even if there is state present.
160 160
 			continue
161 161
 		}
162
-		for _, prior := range priorDrivers {
162
+		if _, prior := driversMap[name]; prior {
163 163
 			// of the state found from prior drivers, check in order of our priority
164 164
 			// which we would prefer
165
-			if prior == name {
166
-				driver, err = getBuiltinDriver(name, root, options, uidMaps, gidMaps)
167
-				if err != nil {
168
-					// unlike below, we will return error here, because there is prior
169
-					// state, and now it is no longer supported/prereq/compatible, so
170
-					// something changed and needs attention. Otherwise the daemon's
171
-					// images would just "disappear".
172
-					logrus.Errorf("[graphdriver] prior storage driver %q failed: %s", name, err)
173
-					return nil, err
174
-				}
175
-				if err := checkPriorDriver(name, root); err != nil {
176
-					return nil, err
165
+			driver, err := getBuiltinDriver(name, root, options, uidMaps, gidMaps)
166
+			if err != nil {
167
+				// unlike below, we will return error here, because there is prior
168
+				// state, and now it is no longer supported/prereq/compatible, so
169
+				// something changed and needs attention. Otherwise the daemon's
170
+				// images would just "disappear".
171
+				logrus.Errorf("[graphdriver] prior storage driver %q failed: %s", name, err)
172
+				return nil, err
173
+			}
174
+
175
+			// abort starting when there are other prior configured drivers
176
+			// to ensure the user explicitly selects the driver to load
177
+			if len(driversMap)-1 > 0 {
178
+				var driversSlice []string
179
+				for name := range driversMap {
180
+					driversSlice = append(driversSlice, name)
177 181
 				}
178
-				logrus.Infof("[graphdriver] using prior storage driver %q", name)
179
-				return driver, nil
182
+
183
+				return nil, fmt.Errorf("%q contains several valid graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s <DRIVER>)", root, strings.Join(driversSlice, ", "))
180 184
 			}
185
+
186
+			logrus.Infof("[graphdriver] using prior storage driver %q", name)
187
+			return driver, nil
181 188
 		}
182 189
 	}
183 190
 
184 191
 	// Check for priority drivers first
185 192
 	for _, name := range priority {
186
-		driver, err = getBuiltinDriver(name, root, options, uidMaps, gidMaps)
193
+		driver, err := getBuiltinDriver(name, root, options, uidMaps, gidMaps)
187 194
 		if err != nil {
188
-			if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS {
195
+			if isDriverNotSupported(err) {
189 196
 				continue
190 197
 			}
191 198
 			return nil, err
... ...
@@ -194,9 +201,10 @@ func New(root string, name string, options []string, uidMaps, gidMaps []idtools.
194 194
 	}
195 195
 
196 196
 	// Check all registered drivers if no priority driver is found
197
-	for _, initFunc := range drivers {
198
-		if driver, err = initFunc(root, options, uidMaps, gidMaps); err != nil {
199
-			if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS {
197
+	for name, initFunc := range drivers {
198
+		driver, err := initFunc(filepath.Join(root, name), options, uidMaps, gidMaps)
199
+		if err != nil {
200
+			if isDriverNotSupported(err) {
200 201
 				continue
201 202
 			}
202 203
 			return nil, err
... ...
@@ -206,31 +214,21 @@ func New(root string, name string, options []string, uidMaps, gidMaps []idtools.
206 206
 	return nil, fmt.Errorf("No supported storage backend found")
207 207
 }
208 208
 
209
+// isDriverNotSupported returns true if the error initializing
210
+// the graph driver is a non-supported error.
211
+func isDriverNotSupported(err error) bool {
212
+	return err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS
213
+}
214
+
209 215
 // scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers
210
-func scanPriorDrivers(root string) []string {
211
-	priorDrivers := []string{}
216
+func scanPriorDrivers(root string) map[string]bool {
217
+	driversMap := make(map[string]bool)
218
+
212 219
 	for driver := range drivers {
213 220
 		p := filepath.Join(root, driver)
214 221
 		if _, err := os.Stat(p); err == nil && driver != "vfs" {
215
-			priorDrivers = append(priorDrivers, driver)
222
+			driversMap[driver] = true
216 223
 		}
217 224
 	}
218
-	return priorDrivers
219
-}
220
-
221
-func checkPriorDriver(name, root string) error {
222
-	priorDrivers := []string{}
223
-	for _, prior := range scanPriorDrivers(root) {
224
-		if prior != name && prior != "vfs" {
225
-			if _, err := os.Stat(filepath.Join(root, prior)); err == nil {
226
-				priorDrivers = append(priorDrivers, prior)
227
-			}
228
-		}
229
-	}
230
-
231
-	if len(priorDrivers) > 0 {
232
-
233
-		return fmt.Errorf("%q contains other graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s <DRIVER>)", root, strings.Join(priorDrivers, ","))
234
-	}
235
-	return nil
225
+	return driversMap
236 226
 }