Remove O(n^2) check for several prior configured drivers.
Signed-off-by: David Calavera <david.calavera@gmail.com>
| ... | ... |
@@ -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 |
} |