Browse code

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 authored on 2014/04/01 22:41:25
Showing 2 changed files
... ...
@@ -125,3 +125,19 @@ Here is the list of supported options:
125 125
     Example use:
126 126
 
127 127
     ``docker -d --storage-opt dm.datadev=/dev/sdb1 --storage-opt dm.metadatadev=/dev/sdc1``
128
+
129
+ *  `dm.blkdiscard`
130
+
131
+    Enables or disables the use of blkdiscard when removing
132
+    devicemapper devices. This is enabled by default (only) if using
133
+    loopback devices and is required to res-parsify the loopback file
134
+    on image/container removal.
135
+
136
+    Disabling this on loopback can lead to *much* faster container
137
+    removal times, but will make the space used in /var/lib/docker
138
+    directory not be returned to the system for other use when
139
+    containers are removed.
140
+
141
+    Example use:
142
+
143
+    ``docker -d --storage-opt dm.blkdiscard=false``
... ...
@@ -77,6 +77,7 @@ type DeviceSet struct {
77 77
 	mkfsArgs             []string
78 78
 	dataDevice           string
79 79
 	metadataDevice       string
80
+	doBlkDiscard         bool
80 81
 }
81 82
 
82 83
 type DiskUsage struct {
... ...
@@ -713,12 +714,14 @@ func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
713 713
 }
714 714
 
715 715
 func (devices *DeviceSet) deleteDevice(info *DevInfo) error {
716
-	// This is a workaround for the kernel not discarding block so
717
-	// on the thin pool when we remove a thinp device, so we do it
718
-	// manually
719
-	if err := devices.activateDeviceIfNeeded(info); err == nil {
720
-		if err := BlockDeviceDiscard(info.DevName()); err != nil {
721
-			utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
716
+	if devices.doBlkDiscard {
717
+		// This is a workaround for the kernel not discarding block so
718
+		// on the thin pool when we remove a thinp device, so we do it
719
+		// manually
720
+		if err := devices.activateDeviceIfNeeded(info); err == nil {
721
+			if err := BlockDeviceDiscard(info.DevName()); err != nil {
722
+				utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
723
+			}
722 724
 		}
723 725
 	}
724 726
 
... ...
@@ -1174,8 +1177,10 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
1174 1174
 		metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
1175 1175
 		baseFsSize:           DefaultBaseFsSize,
1176 1176
 		filesystem:           "ext4",
1177
+		doBlkDiscard:         true,
1177 1178
 	}
1178 1179
 
1180
+	foundBlkDiscard := false
1179 1181
 	for _, option := range options {
1180 1182
 		key, val, err := utils.ParseKeyValueOpt(option)
1181 1183
 		if err != nil {
... ...
@@ -1214,11 +1219,22 @@ func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error
1214 1214
 			devices.metadataDevice = val
1215 1215
 		case "dm.datadev":
1216 1216
 			devices.dataDevice = val
1217
+		case "dm.blkdiscard":
1218
+			foundBlkDiscard = true
1219
+			devices.doBlkDiscard, err = strconv.ParseBool(val)
1220
+			if err != nil {
1221
+				return nil, err
1222
+			}
1217 1223
 		default:
1218 1224
 			return nil, fmt.Errorf("Unknown option %s\n", key)
1219 1225
 		}
1220 1226
 	}
1221 1227
 
1228
+	// By default, don't do blk discard hack on raw devices, its rarely useful and is expensive
1229
+	if !foundBlkDiscard && devices.dataDevice != "" {
1230
+		devices.doBlkDiscard = false
1231
+	}
1232
+
1222 1233
 	if err := devices.initDevmapper(doInit); err != nil {
1223 1234
 		return nil, err
1224 1235
 	}