mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
devmapper: Provide a new parameter dm.deferred_device_removal
Provide a new command line knob dm.deferred_device_removal which will enable deferred device deactivation if driver and library support it. This patch also checks for library support and driver version. Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
This commit is contained in:
parent
6964ab94be
commit
15c158b207
2 changed files with 83 additions and 2 deletions
|
@ -252,3 +252,23 @@ Here is the list of supported options:
|
||||||
> Otherwise, set this flag for migrating existing Docker daemons to a
|
> Otherwise, set this flag for migrating existing Docker daemons to a
|
||||||
> daemon with a supported environment.
|
> daemon with a supported environment.
|
||||||
|
|
||||||
|
* `dm.use_deferred_removal`
|
||||||
|
|
||||||
|
Enables use of deferred device removal if libdm and kernel driver
|
||||||
|
support the mechanism.
|
||||||
|
|
||||||
|
Deferred device removal means that if device is busy when devices is
|
||||||
|
being removed/deactivated, then a deferred removal is scheduled on
|
||||||
|
device. And devices automatically goes away when last user of device
|
||||||
|
exits.
|
||||||
|
|
||||||
|
For example, when contianer exits, its associated thin device is
|
||||||
|
removed. If that devices has leaked into some other mount namespace
|
||||||
|
can can't be removed now, container exit will still be successful
|
||||||
|
and this option will just schedule device for deferred removal and
|
||||||
|
will not wait in a loop trying to remove a busy device.
|
||||||
|
|
||||||
|
Example use:
|
||||||
|
|
||||||
|
``docker -d --storage-opt dm.use_deferred_device_removal=true``
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,9 @@ var (
|
||||||
// We retry device removal so many a times that even error messages
|
// We retry device removal so many a times that even error messages
|
||||||
// will fill up console during normal operation. So only log Fatal
|
// will fill up console during normal operation. So only log Fatal
|
||||||
// messages by default.
|
// messages by default.
|
||||||
DMLogLevel int = devicemapper.LogLevelFatal
|
DMLogLevel int = devicemapper.LogLevelFatal
|
||||||
|
DriverDeferredRemovalSupport bool = false
|
||||||
|
EnableDeferredRemoval bool = false
|
||||||
)
|
)
|
||||||
|
|
||||||
const deviceSetMetaFile string = "deviceset-metadata"
|
const deviceSetMetaFile string = "deviceset-metadata"
|
||||||
|
@ -103,6 +105,7 @@ type DeviceSet struct {
|
||||||
thinPoolDevice string
|
thinPoolDevice string
|
||||||
Transaction `json:"-"`
|
Transaction `json:"-"`
|
||||||
overrideUdevSyncCheck bool
|
overrideUdevSyncCheck bool
|
||||||
|
deferredRemove bool // use deferred removal
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiskUsage struct {
|
type DiskUsage struct {
|
||||||
|
@ -960,16 +963,67 @@ func (devices *DeviceSet) closeTransaction() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func determineDriverCapabilities(version string) error {
|
||||||
|
/*
|
||||||
|
* Driver version 4.27.0 and greater support deferred activation
|
||||||
|
* feature.
|
||||||
|
*/
|
||||||
|
|
||||||
|
logrus.Debugf("devicemapper: driver version is %s", version)
|
||||||
|
|
||||||
|
versionSplit := strings.Split(version, ".")
|
||||||
|
major, err := strconv.Atoi(versionSplit[0])
|
||||||
|
if err != nil {
|
||||||
|
return graphdriver.ErrNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
if major > 4 {
|
||||||
|
DriverDeferredRemovalSupport = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if major < 4 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
minor, err := strconv.Atoi(versionSplit[1])
|
||||||
|
if err != nil {
|
||||||
|
return graphdriver.ErrNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If major is 4 and minor is 27, then there is no need to
|
||||||
|
* check for patch level as it can not be less than 0.
|
||||||
|
*/
|
||||||
|
if minor >= 27 {
|
||||||
|
DriverDeferredRemovalSupport = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||||
// give ourselves to libdm as a log handler
|
// give ourselves to libdm as a log handler
|
||||||
devicemapper.LogInit(devices)
|
devicemapper.LogInit(devices)
|
||||||
|
|
||||||
_, err := devicemapper.GetDriverVersion()
|
version, err := devicemapper.GetDriverVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Can't even get driver version, assume not supported
|
// Can't even get driver version, assume not supported
|
||||||
return graphdriver.ErrNotSupported
|
return graphdriver.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := determineDriverCapabilities(version); err != nil {
|
||||||
|
return graphdriver.ErrNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
// If user asked for deferred removal and both library and driver
|
||||||
|
// supports deferred removal use it.
|
||||||
|
if EnableDeferredRemoval && DriverDeferredRemovalSupport && devicemapper.LibraryDeferredRemovalSupport == true {
|
||||||
|
logrus.Debugf("devmapper: Deferred removal support enabled.")
|
||||||
|
devices.deferredRemove = true
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/docker/docker/issues/4036
|
// https://github.com/docker/docker/issues/4036
|
||||||
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
if supported := devicemapper.UdevSetSyncSupport(true); !supported {
|
||||||
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")
|
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")
|
||||||
|
@ -1671,6 +1725,13 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "dm.use_deferred_removal":
|
||||||
|
EnableDeferredRemoval, err = strconv.ParseBool(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unknown option %s\n", key)
|
return nil, fmt.Errorf("Unknown option %s\n", key)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue