Skip to content

Commit

Permalink
devmapper: storage-opt override for udev sync
Browse files Browse the repository at this point in the history
This provides an override for forcing the daemon to still attempt
running the devicemapper driver even when udev sync is not supported.

Intended to be a very clear impairment for those choosing to use it. If
udev sync is false, there will still be an error in the daemon logs,
even when the override is in place. The docs have an explicit WARNING.

Including link to the docs for users that encounter this daemon error
during an upgrade.

Signed-off-by: Vincent Batts <[email protected]>
  • Loading branch information
vbatts committed Apr 10, 2015
1 parent ca628c6 commit 0e21782
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 27 deletions.
38 changes: 37 additions & 1 deletion daemon/graphdriver/devmapper/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ Here is the list of supported options:
can be achieved by zeroing the first 4k to indicate empty
metadata, like this:

``dd if=/dev/zero of=$metadata_dev bs=4096 count=1```
``dd if=/dev/zero of=$metadata_dev bs=4096 count=1``

Example use:

Expand Down Expand Up @@ -216,3 +216,39 @@ Here is the list of supported options:
Example use:

``docker -d --storage-opt dm.blkdiscard=false``

* `dm.override_udev_sync_check`

Overrides the `udev` synchronization checks between `devicemapper` and `udev`.
`udev` is the device manager for the Linux kernel.

To view the `udev` sync support of a Docker daemon that is using the
`devicemapper` driver, run:

$ docker info
[...]
Udev Sync Supported: true
[...]

When `udev` sync support is `true`, then `devicemapper` and udev can
coordinate the activation and deactivation of devices for containers.

When `udev` sync support is `false`, a race condition occurs between
the`devicemapper` and `udev` during create and cleanup. The race condition
results in errors and failures. (For information on these failures, see
[docker#4036](https://github.com/docker/docker/issues/4036))

To allow the `docker` daemon to start, regardless of `udev` sync not being
supported, set `dm.override_udev_sync_check` to true:

$ docker -d --storage-opt dm.override_udev_sync_check=true

When this value is `true`, the `devicemapper` continues and simply warns
you the errors are happening.

> **Note**: The ideal is to pursue a `docker` daemon and environment that
> does support synchronizing with `udev`. For further discussion on this
> topic, see [docker#4036](https://github.com/docker/docker/issues/4036).
> Otherwise, set this flag for migrating existing Docker daemons to a
> daemon with a supported environment.

62 changes: 36 additions & 26 deletions daemon/graphdriver/devmapper/deviceset.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ var (
DefaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024
DefaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024
DefaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024
DefaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors
DefaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors
DefaultUdevSyncOverride bool = false
MaxDeviceId int = 0xffffff // 24 bit, pool limit
DeviceIdMapSz int = (MaxDeviceId + 1) / 8
)
Expand Down Expand Up @@ -83,20 +84,21 @@ type DeviceSet struct {
deviceIdMap []byte

// Options
dataLoopbackSize int64
metaDataLoopbackSize int64
baseFsSize uint64
filesystem string
mountOptions string
mkfsArgs []string
dataDevice string // block or loop dev
dataLoopFile string // loopback file, if used
metadataDevice string // block or loop dev
metadataLoopFile string // loopback file, if used
doBlkDiscard bool
thinpBlockSize uint32
thinPoolDevice string
Transaction `json:"-"`
dataLoopbackSize int64
metaDataLoopbackSize int64
baseFsSize uint64
filesystem string
mountOptions string
mkfsArgs []string
dataDevice string // block or loop dev
dataLoopFile string // loopback file, if used
metadataDevice string // block or loop dev
metadataLoopFile string // loopback file, if used
doBlkDiscard bool
thinpBlockSize uint32
thinPoolDevice string
Transaction `json:"-"`
overrideUdevSyncCheck bool
}

type DiskUsage struct {
Expand Down Expand Up @@ -963,8 +965,10 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {

// https://github.com/docker/docker/issues/4036
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
logrus.Errorf("Udev sync is not supported. This will lead to unexpected behavior, data loss and errors")
return graphdriver.ErrNotSupported
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")
if !devices.overrideUdevSyncCheck {
return graphdriver.ErrNotSupported
}
}

if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
Expand Down Expand Up @@ -1656,15 +1660,16 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
devicemapper.SetDevDir("/dev")

devices := &DeviceSet{
root: root,
MetaData: MetaData{Devices: make(map[string]*DevInfo)},
dataLoopbackSize: DefaultDataLoopbackSize,
metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
baseFsSize: DefaultBaseFsSize,
filesystem: "ext4",
doBlkDiscard: true,
thinpBlockSize: DefaultThinpBlockSize,
deviceIdMap: make([]byte, DeviceIdMapSz),
root: root,
MetaData: MetaData{Devices: make(map[string]*DevInfo)},
dataLoopbackSize: DefaultDataLoopbackSize,
metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
baseFsSize: DefaultBaseFsSize,
overrideUdevSyncCheck: DefaultUdevSyncOverride,
filesystem: "ext4",
doBlkDiscard: true,
thinpBlockSize: DefaultThinpBlockSize,
deviceIdMap: make([]byte, DeviceIdMapSz),
}

foundBlkDiscard := false
Expand Down Expand Up @@ -1721,6 +1726,11 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
}
// convert to 512b sectors
devices.thinpBlockSize = uint32(size) >> 9
case "dm.override_udev_sync_check":
devices.overrideUdevSyncCheck, err = strconv.ParseBool(val)
if err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("Unknown option %s\n", key)
}
Expand Down
1 change: 1 addition & 0 deletions daemon/graphdriver/devmapper/devmapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func init() {
DefaultDataLoopbackSize = 300 * 1024 * 1024
DefaultMetaDataLoopbackSize = 200 * 1024 * 1024
DefaultBaseFsSize = 300 * 1024 * 1024
DefaultUdevSyncOverride = true
if err := graphtest.InitLoopbacks(); err != nil {
panic(err)
}
Expand Down
35 changes: 35 additions & 0 deletions docs/sources/reference/commandline/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,41 @@ Currently supported options are:

$ docker -d --storage-opt dm.blkdiscard=false

* `dm.override_udev_sync_check`

Overrides the `udev` synchronization checks between `devicemapper` and `udev`.
`udev` is the device manager for the Linux kernel.

To view the `udev` sync support of a Docker daemon that is using the
`devicemapper` driver, run:

$ docker info
[...]
Udev Sync Supported: true
[...]

When `udev` sync support is `true`, then `devicemapper` and udev can
coordinate the activation and deactivation of devices for containers.

When `udev` sync support is `false`, a race condition occurs between
the`devicemapper` and `udev` during create and cleanup. The race condition
results in errors and failures. (For information on these failures, see
[docker#4036](https://github.com/docker/docker/issues/4036))

To allow the `docker` daemon to start, regardless of `udev` sync not being
supported, set `dm.override_udev_sync_check` to true:

$ docker -d --storage-opt dm.override_udev_sync_check=true

When this value is `true`, the `devicemapper` continues and simply warns
you the errors are happening.

> **Note**: The ideal is to pursue a `docker` daemon and environment that
> does support synchronizing with `udev`. For further discussion on this
> topic, see [docker#4036](https://github.com/docker/docker/issues/4036).
> Otherwise, set this flag for migrating existing Docker daemons to a
> daemon with a supported environment.

### Docker exec-driver option

The Docker daemon uses a specifically built `libcontainer` execution driver as its
Expand Down

0 comments on commit 0e21782

Please sign in to comment.