Browse code

devmapper: Fail init with ErrNotSupported if simple devmapper call fails

If we can't even get the current device mapper driver version, then
we cleanly fail the devmapper driver as not supported and fall back
on the next one.

Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)

Alexander Larsson authored on 2014/03/28 01:45:02
Showing 3 changed files
... ...
@@ -17,6 +17,7 @@ import (
17 17
 	"syscall"
18 18
 	"time"
19 19
 
20
+	"github.com/dotcloud/docker/daemon/graphdriver"
20 21
 	"github.com/dotcloud/docker/pkg/label"
21 22
 	"github.com/dotcloud/docker/utils"
22 23
 )
... ...
@@ -506,6 +507,12 @@ func (devices *DeviceSet) ResizePool(size int64) error {
506 506
 func (devices *DeviceSet) initDevmapper(doInit bool) error {
507 507
 	logInit(devices)
508 508
 
509
+	_, err := getDriverVersion()
510
+	if err != nil {
511
+		// Can't even get driver version, assume not supported
512
+		return graphdriver.ErrNotSupported
513
+	}
514
+
509 515
 	if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
510 516
 		return err
511 517
 	}
... ...
@@ -52,6 +52,7 @@ var (
52 52
 	ErrTaskAddTarget          = errors.New("dm_task_add_target failed")
53 53
 	ErrTaskSetSector          = errors.New("dm_task_set_sector failed")
54 54
 	ErrTaskGetInfo            = errors.New("dm_task_get_info failed")
55
+	ErrTaskGetDriverVersion   = errors.New("dm_task_get_driver_version failed")
55 56
 	ErrTaskSetCookie          = errors.New("dm_task_set_cookie failed")
56 57
 	ErrNilCookie              = errors.New("cookie ptr can't be nil")
57 58
 	ErrAttachLoopbackDevice   = errors.New("loopback mounting failed")
... ...
@@ -178,6 +179,14 @@ func (t *Task) GetInfo() (*Info, error) {
178 178
 	return info, nil
179 179
 }
180 180
 
181
+func (t *Task) GetDriverVersion() (string, error) {
182
+	res := DmTaskGetDriverVersion(t.unmanaged)
183
+	if res == "" {
184
+		return "", ErrTaskGetDriverVersion
185
+	}
186
+	return res, nil
187
+}
188
+
181 189
 func (t *Task) GetNextTarget(next uintptr) (nextPtr uintptr, start uint64,
182 190
 	length uint64, targetType string, params string) {
183 191
 
... ...
@@ -394,6 +403,17 @@ func getInfo(name string) (*Info, error) {
394 394
 	return task.GetInfo()
395 395
 }
396 396
 
397
+func getDriverVersion() (string, error) {
398
+	task := TaskCreate(DeviceVersion)
399
+	if task == nil {
400
+		return "", fmt.Errorf("Can't create DeviceVersion task")
401
+	}
402
+	if err := task.Run(); err != nil {
403
+		return "", err
404
+	}
405
+	return task.GetDriverVersion()
406
+}
407
+
397 408
 func getStatus(name string) (uint64, uint64, string, string, error) {
398 409
 	task, err := createTask(DeviceStatus, name)
399 410
 	if task == nil {
... ...
@@ -85,23 +85,24 @@ const (
85 85
 )
86 86
 
87 87
 var (
88
-	DmGetLibraryVersion = dmGetLibraryVersionFct
89
-	DmGetNextTarget     = dmGetNextTargetFct
90
-	DmLogInitVerbose    = dmLogInitVerboseFct
91
-	DmSetDevDir         = dmSetDevDirFct
92
-	DmTaskAddTarget     = dmTaskAddTargetFct
93
-	DmTaskCreate        = dmTaskCreateFct
94
-	DmTaskDestroy       = dmTaskDestroyFct
95
-	DmTaskGetInfo       = dmTaskGetInfoFct
96
-	DmTaskRun           = dmTaskRunFct
97
-	DmTaskSetAddNode    = dmTaskSetAddNodeFct
98
-	DmTaskSetCookie     = dmTaskSetCookieFct
99
-	DmTaskSetMessage    = dmTaskSetMessageFct
100
-	DmTaskSetName       = dmTaskSetNameFct
101
-	DmTaskSetRo         = dmTaskSetRoFct
102
-	DmTaskSetSector     = dmTaskSetSectorFct
103
-	DmUdevWait          = dmUdevWaitFct
104
-	LogWithErrnoInit    = logWithErrnoInitFct
88
+	DmGetLibraryVersion    = dmGetLibraryVersionFct
89
+	DmGetNextTarget        = dmGetNextTargetFct
90
+	DmLogInitVerbose       = dmLogInitVerboseFct
91
+	DmSetDevDir            = dmSetDevDirFct
92
+	DmTaskAddTarget        = dmTaskAddTargetFct
93
+	DmTaskCreate           = dmTaskCreateFct
94
+	DmTaskDestroy          = dmTaskDestroyFct
95
+	DmTaskGetInfo          = dmTaskGetInfoFct
96
+	DmTaskGetDriverVersion = dmTaskGetDriverVersionFct
97
+	DmTaskRun              = dmTaskRunFct
98
+	DmTaskSetAddNode       = dmTaskSetAddNodeFct
99
+	DmTaskSetCookie        = dmTaskSetCookieFct
100
+	DmTaskSetMessage       = dmTaskSetMessageFct
101
+	DmTaskSetName          = dmTaskSetNameFct
102
+	DmTaskSetRo            = dmTaskSetRoFct
103
+	DmTaskSetSector        = dmTaskSetSectorFct
104
+	DmUdevWait             = dmUdevWaitFct
105
+	LogWithErrnoInit       = logWithErrnoInitFct
105 106
 )
106 107
 
107 108
 func free(p *C.char) {
... ...
@@ -184,6 +185,16 @@ func dmTaskGetInfoFct(task *CDmTask, info *Info) int {
184 184
 	return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo))
185 185
 }
186 186
 
187
+func dmTaskGetDriverVersionFct(task *CDmTask) string {
188
+	buffer := C.malloc(128)
189
+	defer C.free(buffer)
190
+	res := C.dm_task_get_driver_version((*C.struct_dm_task)(task), (*C.char)(buffer), 128)
191
+	if res == 0 {
192
+		return ""
193
+	}
194
+	return C.GoString((*C.char)(buffer))
195
+}
196
+
187 197
 func dmGetNextTargetFct(task *CDmTask, next uintptr, start, length *uint64, target, params *string) uintptr {
188 198
 	var (
189 199
 		Cstart, Clength      C.uint64_t