| ... | ... |
@@ -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 |
} |