[docker-io/epel7] discard freespace on image delete (BZ 1055645)

Lokesh Mandvekar lsm5 at fedoraproject.org
Mon Jan 20 23:28:20 UTC 2014


commit 104c7311e86b5bba7e396b75a7e3fbdbcdf3f9e0
Author: Lokesh Mandvekar <lsm5 at redhat.com>
Date:   Mon Jan 20 17:54:33 2014 -0500

    discard freespace on image delete (BZ 1055645)
    
    Signed-off-by: Lokesh Mandvekar <lsm5 at redhat.com>

 devicemapper-discard-freespace.patch |  137 ++++++++++++++++++++++++++++++++++
 docker-io.spec                       |   14 +++-
 2 files changed, 148 insertions(+), 3 deletions(-)
---
diff --git a/devicemapper-discard-freespace.patch b/devicemapper-discard-freespace.patch
new file mode 100644
index 0000000..355d971
--- /dev/null
+++ b/devicemapper-discard-freespace.patch
@@ -0,0 +1,137 @@
+From 93e120e7d67313086d8bdecbcb57ea68958f91e4 Mon Sep 17 00:00:00 2001
+From: Alexander Larsson <alexl at redhat.com>
+Date: Tue, 17 Dec 2013 09:12:44 +0100
+Subject: [PATCH] Discard all data on devicemapper devices when deleting them
+
+This works around the fact that deleting a device in a thin pool
+doesn't discard the free space. Unfortunately even this is not perfect,
+as it seems discards are respected only for blocks that has never been
+shared in the thin device code. However, this has been fixed in the
+upstream kernel device-mapper tree:
+
+http://git.kernel.org/cgit/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=for-next&id=0ab1c92ff748b745c1ed7cde31bb37ad2c5f901a
+
+When this hits the kernel I belive this will fully return space
+for removed images/containers to the host FS. For now it only
+helps partially (which is better than nothing).
+
+Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl at redhat.com> (github: alexlarsson)
+---
+ graphdriver/devmapper/deviceset.go         |  9 +++++++++
+ graphdriver/devmapper/devmapper.go         | 24 ++++++++++++++++++++++++
+ graphdriver/devmapper/devmapper_wrapper.go |  1 +
+ graphdriver/devmapper/driver_test.go       |  4 ++++
+ graphdriver/devmapper/ioctl.go             | 11 +++++++++++
+ 5 files changed, 49 insertions(+)
+
+diff --git a/graphdriver/devmapper/deviceset.go b/graphdriver/devmapper/deviceset.go
+index 7308c0e..6e3caf6 100644
+--- a/graphdriver/devmapper/deviceset.go
++++ b/graphdriver/devmapper/deviceset.go
+@@ -568,6 +568,15 @@ func (devices *DeviceSet) removeDevice(hash string) error {
+ 		return fmt.Errorf("hash %s doesn't exists", hash)
+ 	}
+ 
++	// 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(hash); err == nil {
++		if err := BlockDeviceDiscard(info.DevName()); err != nil {
++			utils.Debugf("Error discarding block on device: %s (ignoring)\n", err)
++		}
++	}
++
+ 	devinfo, _ := getInfo(info.Name())
+ 	if devinfo != nil && devinfo.Exists != 0 {
+ 		if err := removeDevice(info.Name()); err != nil {
+diff --git a/graphdriver/devmapper/devmapper.go b/graphdriver/devmapper/devmapper.go
+index dfbdf38..d3eba78 100644
+--- a/graphdriver/devmapper/devmapper.go
++++ b/graphdriver/devmapper/devmapper.go
+@@ -7,6 +7,7 @@ import (
+ 	"fmt"
+ 	"github.com/dotcloud/docker/utils"
+ 	"runtime"
++	"syscall"
+ )
+ 
+ type DevmapperLogger interface {
+@@ -288,6 +289,29 @@ func GetBlockDeviceSize(file *osFile) (uint64, error) {
+ 	return uint64(size), nil
+ }
+ 
++func BlockDeviceDiscard(path string) error {
++	file, err := osOpenFile(path, osORdWr, 0)
++	if err != nil {
++		return err
++	}
++	defer file.Close()
++
++	size, err := GetBlockDeviceSize(file)
++	if err != nil {
++		return err
++	}
++
++	if err := ioctlBlkDiscard(file.Fd(), 0, size); err != nil {
++		return err
++	}
++
++	// Without this sometimes the remove of the device that happens after
++	// discard fails with EBUSY.
++	syscall.Sync()
++
++	return nil
++}
++
+ // This is the programmatic example of "dmsetup create"
+ func createPool(poolName string, dataFile, metadataFile *osFile) error {
+ 	task, err := createTask(DeviceCreate, poolName)
+diff --git a/graphdriver/devmapper/devmapper_wrapper.go b/graphdriver/devmapper/devmapper_wrapper.go
+index 80d430e..7e6dd5e 100644
+--- a/graphdriver/devmapper/devmapper_wrapper.go
++++ b/graphdriver/devmapper/devmapper_wrapper.go
+@@ -66,6 +66,7 @@ type (
+ // IOCTL consts
+ const (
+ 	BlkGetSize64 = C.BLKGETSIZE64
++	BlkDiscard   = C.BLKDISCARD
+ 
+ 	LoopSetFd       = C.LOOP_SET_FD
+ 	LoopCtlGetFree  = C.LOOP_CTL_GET_FREE
+diff --git a/graphdriver/devmapper/driver_test.go b/graphdriver/devmapper/driver_test.go
+index b6d997b..9a2e409 100644
+--- a/graphdriver/devmapper/driver_test.go
++++ b/graphdriver/devmapper/driver_test.go
+@@ -641,6 +641,10 @@ func TestDriverRemove(t *testing.T) {
+ 			"DmTaskSetMessage",
+ 			"DmTaskCreate",
+ 			"DmTaskGetInfo",
++			"DmTaskSetCookie",
++			"DmTaskSetTarget",
++			"DmTaskSetAddNode",
++			"DmUdevWait",
+ 			"Mounted",
+ 			"sysUnmount",
+ 		)
+diff --git a/graphdriver/devmapper/ioctl.go b/graphdriver/devmapper/ioctl.go
+index 448d2d5..f9bf34f 100644
+--- a/graphdriver/devmapper/ioctl.go
++++ b/graphdriver/devmapper/ioctl.go
+@@ -58,3 +58,14 @@ func ioctlBlkGetSize64(fd uintptr) (int64, error) {
+ 	}
+ 	return size, nil
+ }
++
++func ioctlBlkDiscard(fd uintptr, offset, length uint64) error {
++	var r [2]uint64
++	r[0] = offset
++	r[1] = length
++
++	if _, _, err := sysSyscall(sysSysIoctl, fd, BlkDiscard, uintptr(unsafe.Pointer(&r[0]))); err != 0 {
++		return err
++	}
++	return nil
++}
+-- 
+1.8.5.1
+
diff --git a/docker-io.spec b/docker-io.spec
index b94c3a8..9e95ea0 100644
--- a/docker-io.spec
+++ b/docker-io.spec
@@ -14,11 +14,12 @@
 
 Name:           docker-io
 Version:        0.7.6
-Release:        1%{?dist}
+Release:        2%{?dist}
 Summary:        Automates deployment of containerized applications
 License:        ASL 2.0
 
 Patch0:         docker-0.7-el6-docs.patch
+Patch1:         devicemapper-discard-freespace.patch
 URL:            http://www.docker.io
 # only x86_64 for now: https://github.com/dotcloud/docker/issues/136
 ExclusiveArch:  x86_64
@@ -55,7 +56,7 @@ Requires:       tar
 Requires:       xz
 # https://bugzilla.redhat.com/show_bug.cgi?id=1035436
 # this won't be needed for rhel7+
-%if 0%{?rhel} >= 6
+%if 0%{?rhel} >= 6 && 0%{?rhel} < 7
 Requires:       bridge-utils
 %endif
 # https://bugzilla.redhat.com/show_bug.cgi?id=1034919
@@ -77,8 +78,11 @@ servers, OpenStack clusters, public instances, or combinations of the above.
 %setup -q -n docker-%{version}
 rm -rf vendor
 %if 0%{?rhel} >= 6
-%patch0 -p1 -b docker-0.7-el6-docs.patch
+%patch0 -p1 -b docker-0.7-el6-docs
 %endif
+# discard free space after deleting image
+# https://bugzilla.redhat.com/show_bug.cgi?id=1055645
+%patch1 -p1 -b devicemapper-discard-freespace
 
 %build
 mkdir _build
@@ -169,6 +173,10 @@ fi
 %{_sysconfdir}/udev/rules.d/80-docker.rules
 
 %changelog
+* Mon Jan 20 2014 Lokesh Mandvekar <lsm5 at redhat.com> - 0.7.6-2
+- bridge-utils only for rhel < 7
+- discard freespace when image is removed
+
 * Thu Jan 16 2014 Lokesh Mandvekar <lsm5 at redhat.com> - 0.7.6-1
 - upstream version bump v0.7.6
 - built with golang >= 1.2


More information about the scm-commits mailing list