Ver código fonte

devmapper: Add blkdiscard option and disable it on raw devices

The blkdiscard hack we do on container/image delete is pretty slow, but
required to restore space to the "host" root filesystem. However, it
is pretty useless on raw devices, and you may not need it in development
either.

In a simple test of the devicemapper backend on loopback the time to
delete 20 container went from 11 seconds to 0.4 seconds with
--storage-opt blkdiscard=false.

Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)
Alexander Larsson 11 anos atrás
pai
commit
0434a2ce64

+ 16 - 0
daemon/graphdriver/devmapper/README.md

@@ -125,3 +125,19 @@ Here is the list of supported options:
     Example use:
 
     ``docker -d --storage-opt dm.datadev=/dev/sdb1 --storage-opt dm.metadatadev=/dev/sdc1``
+
+ *  `dm.blkdiscard`
+
+    Enables or disables the use of blkdiscard when removing
+    devicemapper devices. This is enabled by default (only) if using
+    loopback devices and is required to res-parsify the loopback file
+    on image/container removal.
+
+    Disabling this on loopback can lead to *much* faster container
+    removal times, but will make the space used in /var/lib/docker
+    directory not be returned to the system for other use when
+    containers are removed.
+
+    Example use:
+
+    ``docker -d --storage-opt dm.blkdiscard=false``

+ 22 - 6
daemon/graphdriver/devmapper/deviceset.go

@@ -77,6 +77,7 @@ type DeviceSet struct {
 	mkfsArgs             []string
 	dataDevice           string
 	metadataDevice       string
+	doBlkDiscard         bool
 }
 
 type DiskUsage struct {
@@ -713,12 +714,14 @@ func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
 }
 
 func (devices *DeviceSet) deleteDevice(info *DevInfo) error {
-	// This is a workaround for the kernel not discarding block so
-	// on the thin pool when we remove a thinp device, so we do it
-	// manually
-	if err := devices.activateDeviceIfNeeded(info); err == nil {
-		if err := BlockDeviceDiscard(info.DevName()); err != nil {
-			utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
+	if devices.doBlkDiscard {
+		// This is a workaround for the kernel not discarding block so
+		// on the thin pool when we remove a thinp device, so we do it
+		// manually
+		if err := devices.activateDeviceIfNeeded(info); err == nil {
+			if err := BlockDeviceDiscard(info.DevName()); err != nil {
+				utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
+			}
 		}
 	}
 
@@ -1174,8 +1177,10 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
 		metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
 		baseFsSize:           DefaultBaseFsSize,
 		filesystem:           "ext4",
+		doBlkDiscard:         true,
 	}
 
+	foundBlkDiscard := false
 	for _, option := range options {
 		key, val, err := utils.ParseKeyValueOpt(option)
 		if err != nil {
@@ -1214,11 +1219,22 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
 			devices.metadataDevice = val
 		case "dm.datadev":
 			devices.dataDevice = val
+		case "dm.blkdiscard":
+			foundBlkDiscard = true
+			devices.doBlkDiscard, err = strconv.ParseBool(val)
+			if err != nil {
+				return nil, err
+			}
 		default:
 			return nil, fmt.Errorf("Unknown option %s\n", key)
 		}
 	}
 
+	// By default, don't do blk discard hack on raw devices, its rarely useful and is expensive
+	if !foundBlkDiscard && devices.dataDevice != "" {
+		devices.doBlkDiscard = false
+	}
+
 	if err := devices.initDevmapper(doInit); err != nil {
 		return nil, err
 	}