浏览代码

Merge pull request #10195 from vbatts/vbatts-dm_udev_sync

device-mapper udev sync
unclejack 10 年之前
父节点
当前提交
2d61a62378

+ 16 - 8
daemon/graphdriver/devmapper/deviceset.go

@@ -105,14 +105,15 @@ type DiskUsage struct {
 }
 }
 
 
 type Status struct {
 type Status struct {
-	PoolName         string
-	DataFile         string // actual block device for data
-	DataLoopback     string // loopback file, if used
-	MetadataFile     string // actual block device for metadata
-	MetadataLoopback string // loopback file, if used
-	Data             DiskUsage
-	Metadata         DiskUsage
-	SectorSize       uint64
+	PoolName          string
+	DataFile          string // actual block device for data
+	DataLoopback      string // loopback file, if used
+	MetadataFile      string // actual block device for metadata
+	MetadataLoopback  string // loopback file, if used
+	Data              DiskUsage
+	Metadata          DiskUsage
+	SectorSize        uint64
+	UdevSyncSupported bool
 }
 }
 
 
 type DevStatus struct {
 type DevStatus struct {
@@ -947,6 +948,12 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
 		return graphdriver.ErrNotSupported
 		return graphdriver.ErrNotSupported
 	}
 	}
 
 
+	// https://github.com/docker/docker/issues/4036
+	if supported := devicemapper.UdevSetSyncSupport(true); !supported {
+		log.Warnf("WARNING: Udev sync is not supported. This will lead to unexpected behavior, data loss and errors")
+	}
+	log.Debugf("devicemapper: udev sync support: %v", devicemapper.UdevSyncSupported())
+
 	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
 	}
 	}
@@ -1572,6 +1579,7 @@ func (devices *DeviceSet) Status() *Status {
 	status.DataLoopback = devices.dataLoopFile
 	status.DataLoopback = devices.dataLoopFile
 	status.MetadataFile = devices.MetadataDevicePath()
 	status.MetadataFile = devices.MetadataDevicePath()
 	status.MetadataLoopback = devices.metadataLoopFile
 	status.MetadataLoopback = devices.metadataLoopFile
+	status.UdevSyncSupported = devicemapper.UdevSyncSupported()
 
 
 	totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus()
 	totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus()
 	if err == nil {
 	if err == nil {

+ 1 - 0
daemon/graphdriver/devmapper/driver.go

@@ -74,6 +74,7 @@ func (d *Driver) Status() [][2]string {
 		{"Data Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Total)))},
 		{"Data Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Total)))},
 		{"Metadata Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Used)))},
 		{"Metadata Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Used)))},
 		{"Metadata Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Total)))},
 		{"Metadata Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Total)))},
+		{"Udev Sync Supported", fmt.Sprintf("%v", s.UdevSyncSupported)},
 	}
 	}
 	if len(s.DataLoopback) > 0 {
 	if len(s.DataLoopback) > 0 {
 		status = append(status, [2]string{"Data loop file", s.DataLoopback})
 		status = append(status, [2]string{"Data loop file", s.DataLoopback})

+ 20 - 0
pkg/devicemapper/devmapper.go

@@ -319,6 +319,26 @@ func GetLibraryVersion() (string, error) {
 	return version, nil
 	return version, nil
 }
 }
 
 
+// UdevSyncSupported returns whether device-mapper is able to sync with udev
+//
+// This is essential otherwise race conditions can arise where both udev and
+// device-mapper attempt to create and destroy devices.
+func UdevSyncSupported() bool {
+	return DmUdevGetSyncSupport() != 0
+}
+
+// UdevSetSyncSupport allows setting whether the udev sync should be enabled.
+// The return bool indicates the state of whether the sync is enabled.
+func UdevSetSyncSupport(enable bool) bool {
+	if enable {
+		DmUdevSetSyncSupport(1)
+	} else {
+		DmUdevSetSyncSupport(0)
+	}
+
+	return UdevSyncSupported()
+}
+
 // Useful helper for cleanup
 // Useful helper for cleanup
 func RemoveDevice(name string) error {
 func RemoveDevice(name string) error {
 	log.Debugf("[devmapper] RemoveDevice START")
 	log.Debugf("[devmapper] RemoveDevice START")

+ 10 - 0
pkg/devicemapper/devmapper_wrapper.go

@@ -107,6 +107,8 @@ var (
 	DmTaskSetRo            = dmTaskSetRoFct
 	DmTaskSetRo            = dmTaskSetRoFct
 	DmTaskSetSector        = dmTaskSetSectorFct
 	DmTaskSetSector        = dmTaskSetSectorFct
 	DmUdevWait             = dmUdevWaitFct
 	DmUdevWait             = dmUdevWaitFct
+	DmUdevSetSyncSupport   = dmUdevSetSyncSupportFct
+	DmUdevGetSyncSupport   = dmUdevGetSyncSupportFct
 	LogWithErrnoInit       = logWithErrnoInitFct
 	LogWithErrnoInit       = logWithErrnoInitFct
 )
 )
 
 
@@ -231,6 +233,14 @@ func dmGetNextTargetFct(task *CDmTask, next uintptr, start, length *uint64, targ
 	return uintptr(nextp)
 	return uintptr(nextp)
 }
 }
 
 
+func dmUdevSetSyncSupportFct(syncWithUdev int) {
+	(C.dm_udev_set_sync_support(C.int(syncWithUdev)))
+}
+
+func dmUdevGetSyncSupportFct() int {
+	return int(C.dm_udev_get_sync_support())
+}
+
 func dmUdevWaitFct(cookie uint) int {
 func dmUdevWaitFct(cookie uint) int {
 	return int(C.dm_udev_wait(C.uint32_t(cookie)))
 	return int(C.dm_udev_wait(C.uint32_t(cookie)))
 }
 }