Fixes #29654: take reference to RWLayer while committing/exporting

Take an extra reference to rwlayer while the container is being
committed or exported to avoid the removal of that layer.

Also add some checks before commit/export.

Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
This commit is contained in:
Yuanhong Peng
2017-05-20 10:38:45 +08:00
parent 777d4a1bf4
commit 8c32659979
3 changed files with 77 additions and 10 deletions

View File

@@ -2,6 +2,7 @@ package daemon
import (
"encoding/json"
"fmt"
"io"
"runtime"
"strings"
@@ -133,6 +134,16 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
return "", errors.Errorf("%+v does not support commit of a running container", runtime.GOOS)
}
if container.IsDead() {
err := fmt.Errorf("You cannot commit container %s which is Dead", container.ID)
return "", stateConflictError{err}
}
if container.IsRemovalInProgress() {
err := fmt.Errorf("You cannot commit container %s which is being removed", container.ID)
return "", stateConflictError{err}
}
if c.Pause && !container.IsPaused() {
daemon.containerPause(container)
defer daemon.containerUnpause(container)
@@ -234,19 +245,36 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
return id.String(), nil
}
func (daemon *Daemon) exportContainerRw(container *container.Container) (io.ReadCloser, error) {
if err := daemon.Mount(container); err != nil {
func (daemon *Daemon) exportContainerRw(container *container.Container) (arch io.ReadCloser, err error) {
rwlayer, err := daemon.stores[container.Platform].layerStore.GetRWLayer(container.ID)
if err != nil {
return nil, err
}
defer func() {
if err != nil {
daemon.stores[container.Platform].layerStore.ReleaseRWLayer(rwlayer)
}
}()
// TODO: this mount call is not necessary as we assume that TarStream() should
// mount the layer if needed. But the Diff() function for windows requests that
// the layer should be mounted when calling it. So we reserve this mount call
// until windows driver can implement Diff() interface correctly.
_, err = rwlayer.Mount(container.GetMountLabel())
if err != nil {
return nil, err
}
archive, err := container.RWLayer.TarStream()
archive, err := rwlayer.TarStream()
if err != nil {
daemon.Unmount(container) // logging is already handled in the `Unmount` function
rwlayer.Unmount()
return nil, err
}
return ioutils.NewReadCloserWrapper(archive, func() error {
archive.Close()
return container.RWLayer.Unmount()
err = rwlayer.Unmount()
daemon.stores[container.Platform].layerStore.ReleaseRWLayer(rwlayer)
return err
}),
nil
}