Browse code

Try to resize data and metadata loopback file when initiating devicemapper

Signed-off-by: Chun Chen <ramichen@tencent.com>

Chun Chen authored on 2015/09/24 10:21:28
Showing 8 changed files
... ...
@@ -52,7 +52,7 @@ func Init(home string, options []string) (graphdriver.Driver, error) {
52 52
 		home: home,
53 53
 	}
54 54
 
55
-	return graphdriver.NaiveDiffDriver(driver), nil
55
+	return graphdriver.NewNaiveDiffDriver(driver), nil
56 56
 }
57 57
 
58 58
 // Driver contains information about the filesystem mounted.
... ...
@@ -232,7 +232,7 @@ func (devices *DeviceSet) hasImage(name string) bool {
232 232
 
233 233
 // ensureImage creates a sparse file of <size> bytes at the path
234 234
 // <root>/devicemapper/<name>.
235
-// If the file already exists, it does nothing.
235
+// If the file already exists and new size is larger than its current size, it grows to the new size.
236 236
 // Either way it returns the full path.
237 237
 func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
238 238
 	dirname := devices.loopbackDir()
... ...
@@ -242,7 +242,7 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
242 242
 		return "", err
243 243
 	}
244 244
 
245
-	if _, err := os.Stat(filename); err != nil {
245
+	if fi, err := os.Stat(filename); err != nil {
246 246
 		if !os.IsNotExist(err) {
247 247
 			return "", err
248 248
 		}
... ...
@@ -256,6 +256,19 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
256 256
 		if err := file.Truncate(size); err != nil {
257 257
 			return "", err
258 258
 		}
259
+	} else {
260
+		if fi.Size() < size {
261
+			file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600)
262
+			if err != nil {
263
+				return "", err
264
+			}
265
+			defer file.Close()
266
+			if err := file.Truncate(size); err != nil {
267
+				return "", fmt.Errorf("Unable to grow loopback file %s: %v", filename, err)
268
+			}
269
+		} else if fi.Size() > size {
270
+			logrus.Warnf("Can't shrink loopback file %s", filename)
271
+		}
259 272
 	}
260 273
 	return filename, nil
261 274
 }
... ...
@@ -3,8 +3,10 @@
3 3
 package devmapper
4 4
 
5 5
 import (
6
+	"fmt"
6 7
 	"testing"
7 8
 
9
+	"github.com/docker/docker/daemon/graphdriver"
8 10
 	"github.com/docker/docker/daemon/graphdriver/graphtest"
9 11
 )
10 12
 
... ...
@@ -40,3 +42,40 @@ func TestDevmapperCreateSnap(t *testing.T) {
40 40
 func TestDevmapperTeardown(t *testing.T) {
41 41
 	graphtest.PutDriver(t)
42 42
 }
43
+
44
+func TestDevmapperReduceLoopBackSize(t *testing.T) {
45
+	tenMB := int64(10 * 1024 * 1024)
46
+	testChangeLoopBackSize(t, -tenMB, defaultDataLoopbackSize, defaultMetaDataLoopbackSize)
47
+}
48
+
49
+func TestDevmapperIncreaseLoopBackSize(t *testing.T) {
50
+	tenMB := int64(10 * 1024 * 1024)
51
+	testChangeLoopBackSize(t, tenMB, defaultDataLoopbackSize+tenMB, defaultMetaDataLoopbackSize+tenMB)
52
+}
53
+
54
+func testChangeLoopBackSize(t *testing.T, delta, expectDataSize, expectMetaDataSize int64) {
55
+	driver := graphtest.GetDriver(t, "devicemapper").(*graphtest.Driver).Driver.(*graphdriver.NaiveDiffDriver).ProtoDriver.(*Driver)
56
+	defer graphtest.PutDriver(t)
57
+	// make sure data or metadata loopback size are the default size
58
+	if s := driver.DeviceSet.Status(); s.Data.Total != uint64(defaultDataLoopbackSize) || s.Metadata.Total != uint64(defaultMetaDataLoopbackSize) {
59
+		t.Fatalf("data or metadata loop back size is incorrect")
60
+	}
61
+	if err := driver.Cleanup(); err != nil {
62
+		t.Fatal(err)
63
+	}
64
+	//Reload
65
+	d, err := Init(driver.home, []string{
66
+		fmt.Sprintf("dm.loopdatasize=%d", defaultDataLoopbackSize+delta),
67
+		fmt.Sprintf("dm.loopmetadatasize=%d", defaultMetaDataLoopbackSize+delta),
68
+	})
69
+	if err != nil {
70
+		t.Fatalf("error creating devicemapper driver: %v", err)
71
+	}
72
+	driver = d.(*graphdriver.NaiveDiffDriver).ProtoDriver.(*Driver)
73
+	if s := driver.DeviceSet.Status(); s.Data.Total != uint64(expectDataSize) || s.Metadata.Total != uint64(expectMetaDataSize) {
74
+		t.Fatalf("data or metadata loop back size is incorrect")
75
+	}
76
+	if err := driver.Cleanup(); err != nil {
77
+		t.Fatal(err)
78
+	}
79
+}
... ...
@@ -57,7 +57,7 @@ func Init(home string, options []string) (graphdriver.Driver, error) {
57 57
 		home:      home,
58 58
 	}
59 59
 
60
-	return graphdriver.NaiveDiffDriver(d), nil
60
+	return graphdriver.NewNaiveDiffDriver(d), nil
61 61
 }
62 62
 
63 63
 func (d *Driver) String() string {
... ...
@@ -11,29 +11,29 @@ import (
11 11
 	"github.com/docker/docker/pkg/ioutils"
12 12
 )
13 13
 
14
-// naiveDiffDriver takes a ProtoDriver and adds the
14
+// NaiveDiffDriver takes a ProtoDriver and adds the
15 15
 // capability of the Diffing methods which it may or may not
16 16
 // support on its own. See the comment on the exported
17
-// NaiveDiffDriver function below.
17
+// NewNaiveDiffDriver function below.
18 18
 // Notably, the AUFS driver doesn't need to be wrapped like this.
19
-type naiveDiffDriver struct {
19
+type NaiveDiffDriver struct {
20 20
 	ProtoDriver
21 21
 }
22 22
 
23
-// NaiveDiffDriver returns a fully functional driver that wraps the
23
+// NewNaiveDiffDriver returns a fully functional driver that wraps the
24 24
 // given ProtoDriver and adds the capability of the following methods which
25 25
 // it may or may not support on its own:
26 26
 //     Diff(id, parent string) (archive.Archive, error)
27 27
 //     Changes(id, parent string) ([]archive.Change, error)
28 28
 //     ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error)
29 29
 //     DiffSize(id, parent string) (size int64, err error)
30
-func NaiveDiffDriver(driver ProtoDriver) Driver {
31
-	return &naiveDiffDriver{ProtoDriver: driver}
30
+func NewNaiveDiffDriver(driver ProtoDriver) Driver {
31
+	return &NaiveDiffDriver{ProtoDriver: driver}
32 32
 }
33 33
 
34 34
 // Diff produces an archive of the changes between the specified
35 35
 // layer and its parent layer which may be "".
36
-func (gdw *naiveDiffDriver) Diff(id, parent string) (arch archive.Archive, err error) {
36
+func (gdw *NaiveDiffDriver) Diff(id, parent string) (arch archive.Archive, err error) {
37 37
 	driver := gdw.ProtoDriver
38 38
 
39 39
 	layerFs, err := driver.Get(id, "")
... ...
@@ -84,7 +84,7 @@ func (gdw *naiveDiffDriver) Diff(id, parent string) (arch archive.Archive, err e
84 84
 
85 85
 // Changes produces a list of changes between the specified layer
86 86
 // and its parent layer. If parent is "", then all changes will be ADD changes.
87
-func (gdw *naiveDiffDriver) Changes(id, parent string) ([]archive.Change, error) {
87
+func (gdw *NaiveDiffDriver) Changes(id, parent string) ([]archive.Change, error) {
88 88
 	driver := gdw.ProtoDriver
89 89
 
90 90
 	layerFs, err := driver.Get(id, "")
... ...
@@ -109,7 +109,7 @@ func (gdw *naiveDiffDriver) Changes(id, parent string) ([]archive.Change, error)
109 109
 // ApplyDiff extracts the changeset from the given diff into the
110 110
 // layer with the specified id and parent, returning the size of the
111 111
 // new layer in bytes.
112
-func (gdw *naiveDiffDriver) ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error) {
112
+func (gdw *NaiveDiffDriver) ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error) {
113 113
 	driver := gdw.ProtoDriver
114 114
 
115 115
 	// Mount the root filesystem so we can apply the diff/layer.
... ...
@@ -132,7 +132,7 @@ func (gdw *naiveDiffDriver) ApplyDiff(id, parent string, diff archive.Reader) (s
132 132
 // DiffSize calculates the changes between the specified layer
133 133
 // and its parent and returns the size in bytes of the changes
134 134
 // relative to its base filesystem directory.
135
-func (gdw *naiveDiffDriver) DiffSize(id, parent string) (size int64, err error) {
135
+func (gdw *NaiveDiffDriver) DiffSize(id, parent string) (size int64, err error) {
136 136
 	driver := gdw.ProtoDriver
137 137
 
138 138
 	changes, err := gdw.Changes(id, parent)
... ...
@@ -43,7 +43,7 @@ type naiveDiffDriverWithApply struct {
43 43
 // NaiveDiffDriverWithApply returns a NaiveDiff driver with custom ApplyDiff.
44 44
 func NaiveDiffDriverWithApply(driver ApplyDiffProtoDriver) graphdriver.Driver {
45 45
 	return &naiveDiffDriverWithApply{
46
-		Driver:    graphdriver.NaiveDiffDriver(driver),
46
+		Driver:    graphdriver.NewNaiveDiffDriver(driver),
47 47
 		applyDiff: driver,
48 48
 	}
49 49
 }
... ...
@@ -23,7 +23,7 @@ func Init(home string, options []string) (graphdriver.Driver, error) {
23 23
 	d := &Driver{
24 24
 		home: home,
25 25
 	}
26
-	return graphdriver.NaiveDiffDriver(d), nil
26
+	return graphdriver.NewNaiveDiffDriver(d), nil
27 27
 }
28 28
 
29 29
 // Driver holds information about the driver, home directory of the driver.
... ...
@@ -103,7 +103,7 @@ func Init(base string, opt []string) (graphdriver.Driver, error) {
103 103
 		options:          options,
104 104
 		filesystemsCache: filesystemsCache,
105 105
 	}
106
-	return graphdriver.NaiveDiffDriver(d), nil
106
+	return graphdriver.NewNaiveDiffDriver(d), nil
107 107
 }
108 108
 
109 109
 func parseOptions(opt []string) (zfsOptions, error) {