Browse code

Merge pull request #10195 from vbatts/vbatts-dm_udev_sync

device-mapper udev sync

unclejack authored on 2015/01/20 07:06:29
Showing 4 changed files
... ...
@@ -105,14 +105,15 @@ type DiskUsage struct {
105 105
 }
106 106
 
107 107
 type Status struct {
108
-	PoolName         string
109
-	DataFile         string // actual block device for data
110
-	DataLoopback     string // loopback file, if used
111
-	MetadataFile     string // actual block device for metadata
112
-	MetadataLoopback string // loopback file, if used
113
-	Data             DiskUsage
114
-	Metadata         DiskUsage
115
-	SectorSize       uint64
108
+	PoolName          string
109
+	DataFile          string // actual block device for data
110
+	DataLoopback      string // loopback file, if used
111
+	MetadataFile      string // actual block device for metadata
112
+	MetadataLoopback  string // loopback file, if used
113
+	Data              DiskUsage
114
+	Metadata          DiskUsage
115
+	SectorSize        uint64
116
+	UdevSyncSupported bool
116 117
 }
117 118
 
118 119
 type DevStatus struct {
... ...
@@ -947,6 +948,12 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
947 947
 		return graphdriver.ErrNotSupported
948 948
 	}
949 949
 
950
+	// https://github.com/docker/docker/issues/4036
951
+	if supported := devicemapper.UdevSetSyncSupport(true); !supported {
952
+		log.Warnf("WARNING: Udev sync is not supported. This will lead to unexpected behavior, data loss and errors")
953
+	}
954
+	log.Debugf("devicemapper: udev sync support: %v", devicemapper.UdevSyncSupported())
955
+
950 956
 	if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
951 957
 		return err
952 958
 	}
... ...
@@ -1572,6 +1579,7 @@ func (devices *DeviceSet) Status() *Status {
1572 1572
 	status.DataLoopback = devices.dataLoopFile
1573 1573
 	status.MetadataFile = devices.MetadataDevicePath()
1574 1574
 	status.MetadataLoopback = devices.metadataLoopFile
1575
+	status.UdevSyncSupported = devicemapper.UdevSyncSupported()
1575 1576
 
1576 1577
 	totalSizeInSectors, _, dataUsed, dataTotal, metadataUsed, metadataTotal, err := devices.poolStatus()
1577 1578
 	if err == nil {
... ...
@@ -74,6 +74,7 @@ func (d *Driver) Status() [][2]string {
74 74
 		{"Data Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Data.Total)))},
75 75
 		{"Metadata Space Used", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Used)))},
76 76
 		{"Metadata Space Total", fmt.Sprintf("%s", units.HumanSize(float64(s.Metadata.Total)))},
77
+		{"Udev Sync Supported", fmt.Sprintf("%v", s.UdevSyncSupported)},
77 78
 	}
78 79
 	if len(s.DataLoopback) > 0 {
79 80
 		status = append(status, [2]string{"Data loop file", s.DataLoopback})
... ...
@@ -319,6 +319,26 @@ func GetLibraryVersion() (string, error) {
319 319
 	return version, nil
320 320
 }
321 321
 
322
+// UdevSyncSupported returns whether device-mapper is able to sync with udev
323
+//
324
+// This is essential otherwise race conditions can arise where both udev and
325
+// device-mapper attempt to create and destroy devices.
326
+func UdevSyncSupported() bool {
327
+	return DmUdevGetSyncSupport() != 0
328
+}
329
+
330
+// UdevSetSyncSupport allows setting whether the udev sync should be enabled.
331
+// The return bool indicates the state of whether the sync is enabled.
332
+func UdevSetSyncSupport(enable bool) bool {
333
+	if enable {
334
+		DmUdevSetSyncSupport(1)
335
+	} else {
336
+		DmUdevSetSyncSupport(0)
337
+	}
338
+
339
+	return UdevSyncSupported()
340
+}
341
+
322 342
 // Useful helper for cleanup
323 343
 func RemoveDevice(name string) error {
324 344
 	log.Debugf("[devmapper] RemoveDevice START")
... ...
@@ -107,6 +107,8 @@ var (
107 107
 	DmTaskSetRo            = dmTaskSetRoFct
108 108
 	DmTaskSetSector        = dmTaskSetSectorFct
109 109
 	DmUdevWait             = dmUdevWaitFct
110
+	DmUdevSetSyncSupport   = dmUdevSetSyncSupportFct
111
+	DmUdevGetSyncSupport   = dmUdevGetSyncSupportFct
110 112
 	LogWithErrnoInit       = logWithErrnoInitFct
111 113
 )
112 114
 
... ...
@@ -231,6 +233,14 @@ func dmGetNextTargetFct(task *CDmTask, next uintptr, start, length *uint64, targ
231 231
 	return uintptr(nextp)
232 232
 }
233 233
 
234
+func dmUdevSetSyncSupportFct(syncWithUdev int) {
235
+	(C.dm_udev_set_sync_support(C.int(syncWithUdev)))
236
+}
237
+
238
+func dmUdevGetSyncSupportFct() int {
239
+	return int(C.dm_udev_get_sync_support())
240
+}
241
+
234 242
 func dmUdevWaitFct(cookie uint) int {
235 243
 	return int(C.dm_udev_wait(C.uint32_t(cookie)))
236 244
 }