Browse code

Merge pull request #11412 from vbatts/vbatts-dm_sync_is_required

devmapper: udev sync is a requirement

Tibor Vass authored on 2015/04/11 05:52:38
Showing 4 changed files
... ...
@@ -186,7 +186,7 @@ Here is the list of supported options:
186 186
     can be achieved by zeroing the first 4k to indicate empty
187 187
     metadata, like this:
188 188
 
189
-    ``dd if=/dev/zero of=$metadata_dev bs=4096 count=1```
189
+    ``dd if=/dev/zero of=$metadata_dev bs=4096 count=1``
190 190
 
191 191
     Example use:
192 192
 
... ...
@@ -216,3 +216,39 @@ Here is the list of supported options:
216 216
     Example use:
217 217
 
218 218
     ``docker -d --storage-opt dm.blkdiscard=false``
219
+
220
+ *  `dm.override_udev_sync_check`
221
+
222
+    Overrides the `udev` synchronization checks between `devicemapper` and `udev`.
223
+    `udev` is the device manager for the Linux kernel.
224
+
225
+    To view the `udev` sync support of a Docker daemon that is using the
226
+    `devicemapper` driver, run:
227
+
228
+        $ docker info
229
+	[...]
230
+	 Udev Sync Supported: true
231
+	[...]
232
+
233
+    When `udev` sync support is `true`, then `devicemapper` and udev can
234
+    coordinate the activation and deactivation of devices for containers.
235
+
236
+    When `udev` sync support is `false`, a race condition occurs between
237
+    the`devicemapper` and `udev` during create and cleanup. The race condition
238
+    results in errors and failures. (For information on these failures, see
239
+    [docker#4036](https://github.com/docker/docker/issues/4036))
240
+
241
+    To allow the `docker` daemon to start, regardless of `udev` sync not being
242
+    supported, set `dm.override_udev_sync_check` to true:
243
+
244
+        $ docker -d --storage-opt dm.override_udev_sync_check=true
245
+
246
+    When this value is `true`, the  `devicemapper` continues and simply warns
247
+    you the errors are happening.
248
+
249
+    > **Note**: The ideal is to pursue a `docker` daemon and environment that
250
+    > does support synchronizing with `udev`. For further discussion on this
251
+    > topic, see [docker#4036](https://github.com/docker/docker/issues/4036).
252
+    > Otherwise, set this flag for migrating existing Docker daemons to a
253
+    > daemon with a supported environment.
254
+
... ...
@@ -30,7 +30,8 @@ var (
30 30
 	DefaultDataLoopbackSize     int64  = 100 * 1024 * 1024 * 1024
31 31
 	DefaultMetaDataLoopbackSize int64  = 2 * 1024 * 1024 * 1024
32 32
 	DefaultBaseFsSize           uint64 = 10 * 1024 * 1024 * 1024
33
-	DefaultThinpBlockSize       uint32 = 128      // 64K = 128 512b sectors
33
+	DefaultThinpBlockSize       uint32 = 128 // 64K = 128 512b sectors
34
+	DefaultUdevSyncOverride     bool   = false
34 35
 	MaxDeviceId                 int    = 0xffffff // 24 bit, pool limit
35 36
 	DeviceIdMapSz               int    = (MaxDeviceId + 1) / 8
36 37
 	// We retry device removal so many a times that even error messages
... ...
@@ -87,20 +88,21 @@ type DeviceSet struct {
87 87
 	deviceIdMap   []byte
88 88
 
89 89
 	// Options
90
-	dataLoopbackSize     int64
91
-	metaDataLoopbackSize int64
92
-	baseFsSize           uint64
93
-	filesystem           string
94
-	mountOptions         string
95
-	mkfsArgs             []string
96
-	dataDevice           string // block or loop dev
97
-	dataLoopFile         string // loopback file, if used
98
-	metadataDevice       string // block or loop dev
99
-	metadataLoopFile     string // loopback file, if used
100
-	doBlkDiscard         bool
101
-	thinpBlockSize       uint32
102
-	thinPoolDevice       string
103
-	Transaction          `json:"-"`
90
+	dataLoopbackSize      int64
91
+	metaDataLoopbackSize  int64
92
+	baseFsSize            uint64
93
+	filesystem            string
94
+	mountOptions          string
95
+	mkfsArgs              []string
96
+	dataDevice            string // block or loop dev
97
+	dataLoopFile          string // loopback file, if used
98
+	metadataDevice        string // block or loop dev
99
+	metadataLoopFile      string // loopback file, if used
100
+	doBlkDiscard          bool
101
+	thinpBlockSize        uint32
102
+	thinPoolDevice        string
103
+	Transaction           `json:"-"`
104
+	overrideUdevSyncCheck bool
104 105
 }
105 106
 
106 107
 type DiskUsage struct {
... ...
@@ -970,9 +972,11 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
970 970
 
971 971
 	// https://github.com/docker/docker/issues/4036
972 972
 	if supported := devicemapper.UdevSetSyncSupport(true); !supported {
973
-		logrus.Warnf("Udev sync is not supported. This will lead to unexpected behavior, data loss and errors")
973
+		logrus.Errorf("Udev sync is not supported. This will lead to unexpected behavior, data loss and errors. For more information, see https://docs.docker.com/reference/commandline/cli/#daemon-storage-driver-option")
974
+		if !devices.overrideUdevSyncCheck {
975
+			return graphdriver.ErrNotSupported
976
+		}
974 977
 	}
975
-	logrus.Debugf("devicemapper: udev sync support: %v", devicemapper.UdevSyncSupported())
976 978
 
977 979
 	if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
978 980
 		return err
... ...
@@ -1596,15 +1600,16 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
1596 1596
 	devicemapper.SetDevDir("/dev")
1597 1597
 
1598 1598
 	devices := &DeviceSet{
1599
-		root:                 root,
1600
-		MetaData:             MetaData{Devices: make(map[string]*DevInfo)},
1601
-		dataLoopbackSize:     DefaultDataLoopbackSize,
1602
-		metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
1603
-		baseFsSize:           DefaultBaseFsSize,
1604
-		filesystem:           "ext4",
1605
-		doBlkDiscard:         true,
1606
-		thinpBlockSize:       DefaultThinpBlockSize,
1607
-		deviceIdMap:          make([]byte, DeviceIdMapSz),
1599
+		root:                  root,
1600
+		MetaData:              MetaData{Devices: make(map[string]*DevInfo)},
1601
+		dataLoopbackSize:      DefaultDataLoopbackSize,
1602
+		metaDataLoopbackSize:  DefaultMetaDataLoopbackSize,
1603
+		baseFsSize:            DefaultBaseFsSize,
1604
+		overrideUdevSyncCheck: DefaultUdevSyncOverride,
1605
+		filesystem:            "ext4",
1606
+		doBlkDiscard:          true,
1607
+		thinpBlockSize:        DefaultThinpBlockSize,
1608
+		deviceIdMap:           make([]byte, DeviceIdMapSz),
1608 1609
 	}
1609 1610
 
1610 1611
 	foundBlkDiscard := false
... ...
@@ -1661,6 +1666,11 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
1661 1661
 			}
1662 1662
 			// convert to 512b sectors
1663 1663
 			devices.thinpBlockSize = uint32(size) >> 9
1664
+		case "dm.override_udev_sync_check":
1665
+			devices.overrideUdevSyncCheck, err = strconv.ParseBool(val)
1666
+			if err != nil {
1667
+				return nil, err
1668
+			}
1664 1669
 		default:
1665 1670
 			return nil, fmt.Errorf("Unknown option %s\n", key)
1666 1671
 		}
... ...
@@ -13,6 +13,7 @@ func init() {
13 13
 	DefaultDataLoopbackSize = 300 * 1024 * 1024
14 14
 	DefaultMetaDataLoopbackSize = 200 * 1024 * 1024
15 15
 	DefaultBaseFsSize = 300 * 1024 * 1024
16
+	DefaultUdevSyncOverride = true
16 17
 	if err := graphtest.InitLoopbacks(); err != nil {
17 18
 		panic(err)
18 19
 	}
... ...
@@ -376,6 +376,41 @@ Currently supported options are:
376 376
 
377 377
         $ docker -d --storage-opt dm.blkdiscard=false
378 378
 
379
+ *  `dm.override_udev_sync_check`
380
+
381
+    Overrides the `udev` synchronization checks between `devicemapper` and `udev`.
382
+    `udev` is the device manager for the Linux kernel.
383
+
384
+    To view the `udev` sync support of a Docker daemon that is using the
385
+    `devicemapper` driver, run:
386
+
387
+        $ docker info
388
+	[...]
389
+	 Udev Sync Supported: true
390
+	[...]
391
+
392
+    When `udev` sync support is `true`, then `devicemapper` and udev can
393
+    coordinate the activation and deactivation of devices for containers.
394
+
395
+    When `udev` sync support is `false`, a race condition occurs between
396
+    the`devicemapper` and `udev` during create and cleanup. The race condition
397
+    results in errors and failures. (For information on these failures, see
398
+    [docker#4036](https://github.com/docker/docker/issues/4036))
399
+
400
+    To allow the `docker` daemon to start, regardless of `udev` sync not being
401
+    supported, set `dm.override_udev_sync_check` to true:
402
+
403
+        $ docker -d --storage-opt dm.override_udev_sync_check=true
404
+
405
+    When this value is `true`, the  `devicemapper` continues and simply warns
406
+    you the errors are happening.
407
+
408
+    > **Note**: The ideal is to pursue a `docker` daemon and environment that
409
+    > does support synchronizing with `udev`. For further discussion on this
410
+    > topic, see [docker#4036](https://github.com/docker/docker/issues/4036).
411
+    > Otherwise, set this flag for migrating existing Docker daemons to a
412
+    > daemon with a supported environment.
413
+
379 414
 ### Docker exec-driver option
380 415
 
381 416
 The Docker daemon uses a specifically built `libcontainer` execution driver as its