From 9f8a6e47d8a0a8e1fd7dd48b95ea8ee5720af9d3 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Fri, 13 Sep 2013 15:58:14 +0200 Subject: [PATCH] Add trivial copy-based CoW backend This creates a container by copying the corresponding files from the layers into the containers. This is not gonna be very useful on a developer setup, as there is no copy-on-write or general diskspace sharing. It also makes container instantiation slower. However, it may be useful in deployment where we don't always have a lot of containers running (long-running daemons) and where we don't do a lot of docker commits. Upstream-commit: 43a7d3d0e9e2fafcdc90cb84855e1bb3869d2729 Component: engine --- components/engine/container.go | 6 ++- components/engine/image.go | 68 ++++++++++++++++++++++++++++++++-- components/engine/runtime.go | 2 + 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/components/engine/container.go b/components/engine/container.go index 35060e873e..e9fb4890b7 100644 --- a/components/engine/container.go +++ b/components/engine/container.go @@ -1209,7 +1209,11 @@ func (container *Container) GetImage() (*Image, error) { } func (container *Container) Mounted() (bool, error) { - return Mounted(container.RootfsPath()) + image, err := container.GetImage() + if err != nil { + return false, err + } + return image.Mounted(container.runtime, container.RootfsPath(), container.rwPath()) } func (container *Container) Unmount() error { diff --git a/components/engine/image.go b/components/engine/image.go index 61ca83b208..2c16aeb6d4 100644 --- a/components/engine/image.go +++ b/components/engine/image.go @@ -442,16 +442,38 @@ func (image *Image) ensureImageDevice(devices DeviceSet) error { return nil } +func (image *Image) Mounted(runtime *Runtime, root, rw string) (bool, error) { + method := runtime.GetMountMethod() + if method == MountMethodFilesystem { + if _, err := os.Stat(rw); err != nil { + if os.IsNotExist(err) { + err = nil + } + return false, err + } + mountedPath := path.Join(rw, ".fs-mounted") + if _, err := os.Stat(mountedPath); err != nil { + if os.IsNotExist(err) { + err = nil + } + return false, err + } + return true, nil + } else { + return Mounted(root) + } +} + func (image *Image) Mount(runtime *Runtime, root, rw string, id string) error { - if mounted, err := Mounted(root); err != nil { - return err - } else if mounted { + if mounted, _ := image.Mounted(runtime, root, rw); mounted { return fmt.Errorf("%s is already mounted", root) } + // Create the target directories if they don't exist if err := os.Mkdir(root, 0755); err != nil && !os.IsExist(err) { return err } + switch runtime.GetMountMethod() { case MountMethodNone: return fmt.Errorf("No supported Mount implementation") @@ -502,6 +524,29 @@ func (image *Image) Mount(runtime *Runtime, root, rw string, id string) error { } } + case MountMethodFilesystem: + if err := os.Mkdir(rw, 0755); err != nil && !os.IsExist(err) { + return err + } + + layers, err := image.layers() + if err != nil { + return err + } + + for i := len(layers)-1; i >= 0; i-- { + layer := layers[i] + if err = image.applyLayer(layer, root); err != nil { + return err + } + } + + mountedPath := path.Join(rw, ".fs-mounted") + fo, err := os.Create(mountedPath) + if err != nil { + return err + } + fo.Close() } return nil } @@ -527,7 +572,11 @@ func (image *Image) Unmount(runtime *Runtime, root string, id string) error { } return devices.DeactivateDevice(id) + + case MountMethodFilesystem: + return nil } + return nil } @@ -563,6 +612,17 @@ func (image *Image) Changes(runtime *Runtime, root, rw, id string) ([]Change, er return nil, err } return changes, nil + + case MountMethodFilesystem: + layers, err := image.layers() + if err != nil { + return nil, err + } + changes, err := ChangesLayers(root, layers) + if err != nil { + return nil, err + } + return changes, nil } return nil, fmt.Errorf("No supported Changes implementation") @@ -573,7 +633,7 @@ func (image *Image) ExportChanges(runtime *Runtime, root, rw, id string) (Archiv case MountMethodAUFS: return Tar(rw, Uncompressed) - case MountMethodDeviceMapper: + case MountMethodFilesystem, MountMethodDeviceMapper: changes, err := image.Changes(runtime, root, rw, id) if err != nil { return nil, err diff --git a/components/engine/runtime.go b/components/engine/runtime.go index 3bbed75295..28263ad7cb 100644 --- a/components/engine/runtime.go +++ b/components/engine/runtime.go @@ -23,6 +23,7 @@ const ( MountMethodNone MountMethod = iota MountMethodAUFS MountMethodDeviceMapper + MountMethodFilesystem ) type Capabilities struct { @@ -124,6 +125,7 @@ func (runtime *Runtime) GetMountMethod() MountMethod { runtime.mountMethod = MountMethodDeviceMapper } } + runtime.mountMethod = MountMethodFilesystem } return runtime.mountMethod