瀏覽代碼

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 11 年之前
父節點
當前提交
948e54ac45

+ 7 - 0
daemon/graphdriver/devmapper/deviceset.go

@@ -17,6 +17,7 @@ import (
 	"syscall"
 	"syscall"
 	"time"
 	"time"
 
 
+	"github.com/dotcloud/docker/daemon/graphdriver"
 	"github.com/dotcloud/docker/pkg/label"
 	"github.com/dotcloud/docker/pkg/label"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 )
 )
@@ -506,6 +507,12 @@ func (devices *DeviceSet) ResizePool(size int64) error {
 func (devices *DeviceSet) initDevmapper(doInit bool) error {
 func (devices *DeviceSet) initDevmapper(doInit bool) error {
 	logInit(devices)
 	logInit(devices)
 
 
+	_, err := getDriverVersion()
+	if err != nil {
+		// Can't even get driver version, assume not supported
+		return graphdriver.ErrNotSupported
+	}
+
 	if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
 	if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
 		return err
 		return err
 	}
 	}

+ 20 - 0
daemon/graphdriver/devmapper/devmapper.go

@@ -52,6 +52,7 @@ var (
 	ErrTaskAddTarget          = errors.New("dm_task_add_target failed")
 	ErrTaskAddTarget          = errors.New("dm_task_add_target failed")
 	ErrTaskSetSector          = errors.New("dm_task_set_sector failed")
 	ErrTaskSetSector          = errors.New("dm_task_set_sector failed")
 	ErrTaskGetInfo            = errors.New("dm_task_get_info failed")
 	ErrTaskGetInfo            = errors.New("dm_task_get_info failed")
+	ErrTaskGetDriverVersion   = errors.New("dm_task_get_driver_version failed")
 	ErrTaskSetCookie          = errors.New("dm_task_set_cookie failed")
 	ErrTaskSetCookie          = errors.New("dm_task_set_cookie failed")
 	ErrNilCookie              = errors.New("cookie ptr can't be nil")
 	ErrNilCookie              = errors.New("cookie ptr can't be nil")
 	ErrAttachLoopbackDevice   = errors.New("loopback mounting failed")
 	ErrAttachLoopbackDevice   = errors.New("loopback mounting failed")
@@ -178,6 +179,14 @@ func (t *Task) GetInfo() (*Info, error) {
 	return info, nil
 	return info, nil
 }
 }
 
 
+func (t *Task) GetDriverVersion() (string, error) {
+	res := DmTaskGetDriverVersion(t.unmanaged)
+	if res == "" {
+		return "", ErrTaskGetDriverVersion
+	}
+	return res, nil
+}
+
 func (t *Task) GetNextTarget(next uintptr) (nextPtr uintptr, start uint64,
 func (t *Task) GetNextTarget(next uintptr) (nextPtr uintptr, start uint64,
 	length uint64, targetType string, params string) {
 	length uint64, targetType string, params string) {
 
 
@@ -394,6 +403,17 @@ func getInfo(name string) (*Info, error) {
 	return task.GetInfo()
 	return task.GetInfo()
 }
 }
 
 
+func getDriverVersion() (string, error) {
+	task := TaskCreate(DeviceVersion)
+	if task == nil {
+		return "", fmt.Errorf("Can't create DeviceVersion task")
+	}
+	if err := task.Run(); err != nil {
+		return "", err
+	}
+	return task.GetDriverVersion()
+}
+
 func getStatus(name string) (uint64, uint64, string, string, error) {
 func getStatus(name string) (uint64, uint64, string, string, error) {
 	task, err := createTask(DeviceStatus, name)
 	task, err := createTask(DeviceStatus, name)
 	if task == nil {
 	if task == nil {

+ 28 - 17
daemon/graphdriver/devmapper/devmapper_wrapper.go

@@ -85,23 +85,24 @@ const (
 )
 )
 
 
 var (
 var (
-	DmGetLibraryVersion = dmGetLibraryVersionFct
-	DmGetNextTarget     = dmGetNextTargetFct
-	DmLogInitVerbose    = dmLogInitVerboseFct
-	DmSetDevDir         = dmSetDevDirFct
-	DmTaskAddTarget     = dmTaskAddTargetFct
-	DmTaskCreate        = dmTaskCreateFct
-	DmTaskDestroy       = dmTaskDestroyFct
-	DmTaskGetInfo       = dmTaskGetInfoFct
-	DmTaskRun           = dmTaskRunFct
-	DmTaskSetAddNode    = dmTaskSetAddNodeFct
-	DmTaskSetCookie     = dmTaskSetCookieFct
-	DmTaskSetMessage    = dmTaskSetMessageFct
-	DmTaskSetName       = dmTaskSetNameFct
-	DmTaskSetRo         = dmTaskSetRoFct
-	DmTaskSetSector     = dmTaskSetSectorFct
-	DmUdevWait          = dmUdevWaitFct
-	LogWithErrnoInit    = logWithErrnoInitFct
+	DmGetLibraryVersion    = dmGetLibraryVersionFct
+	DmGetNextTarget        = dmGetNextTargetFct
+	DmLogInitVerbose       = dmLogInitVerboseFct
+	DmSetDevDir            = dmSetDevDirFct
+	DmTaskAddTarget        = dmTaskAddTargetFct
+	DmTaskCreate           = dmTaskCreateFct
+	DmTaskDestroy          = dmTaskDestroyFct
+	DmTaskGetInfo          = dmTaskGetInfoFct
+	DmTaskGetDriverVersion = dmTaskGetDriverVersionFct
+	DmTaskRun              = dmTaskRunFct
+	DmTaskSetAddNode       = dmTaskSetAddNodeFct
+	DmTaskSetCookie        = dmTaskSetCookieFct
+	DmTaskSetMessage       = dmTaskSetMessageFct
+	DmTaskSetName          = dmTaskSetNameFct
+	DmTaskSetRo            = dmTaskSetRoFct
+	DmTaskSetSector        = dmTaskSetSectorFct
+	DmUdevWait             = dmUdevWaitFct
+	LogWithErrnoInit       = logWithErrnoInitFct
 )
 )
 
 
 func free(p *C.char) {
 func free(p *C.char) {
@@ -184,6 +185,16 @@ func dmTaskGetInfoFct(task *CDmTask, info *Info) int {
 	return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo))
 	return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo))
 }
 }
 
 
+func dmTaskGetDriverVersionFct(task *CDmTask) string {
+	buffer := C.malloc(128)
+	defer C.free(buffer)
+	res := C.dm_task_get_driver_version((*C.struct_dm_task)(task), (*C.char)(buffer), 128)
+	if res == 0 {
+		return ""
+	}
+	return C.GoString((*C.char)(buffer))
+}
+
 func dmGetNextTargetFct(task *CDmTask, next uintptr, start, length *uint64, target, params *string) uintptr {
 func dmGetNextTargetFct(task *CDmTask, next uintptr, start, length *uint64, target, params *string) uintptr {
 	var (
 	var (
 		Cstart, Clength      C.uint64_t
 		Cstart, Clength      C.uint64_t