devmapper: udev sync is a requirement
| ... | ... |
@@ -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 |