Signed-off-by: Chun Chen <ramichen@tencent.com>
| ... | ... |
@@ -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 |
+} |
| ... | ... |
@@ -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) {
|