浏览代码

Merge pull request #11412 from vbatts/vbatts-dm_sync_is_required

devmapper: udev sync is a requirement
Tibor Vass 10 年之前
父节点
当前提交
23c12dabbd

+ 37 - 1
daemon/graphdriver/devmapper/README.md

@@ -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:
 
@@ -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.
+

+ 36 - 26
daemon/graphdriver/devmapper/deviceset.go

@@ -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
 	// We retry device removal so many a times that even error messages
@@ -87,20 +88,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 {
@@ -970,9 +972,11 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
 
 	// https://github.com/docker/docker/issues/4036
 	if supported := devicemapper.UdevSetSyncSupport(true); !supported {
-		logrus.Warnf("Udev sync is not supported. This will lead to unexpected behavior, data loss and errors")
+		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
+		}
 	}
-	logrus.Debugf("devicemapper: udev sync support: %v", devicemapper.UdevSyncSupported())
 
 	if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil && !os.IsExist(err) {
 		return err
@@ -1596,15 +1600,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
@@ -1661,6 +1666,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)
 		}

+ 1 - 0
daemon/graphdriver/devmapper/devmapper_test.go

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

+ 35 - 0
docs/sources/reference/commandline/cli.md

@@ -376,6 +376,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