Don’t hold container lock for size calculation

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi 2017-02-18 18:11:48 -08:00
parent cf5fe9ed0b
commit bd33a99acf
6 changed files with 39 additions and 33 deletions

View File

@ -12,7 +12,7 @@ func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]s
}
// getSize returns real size & virtual size
func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
func (daemon *Daemon) getSize(containerID string) (int64, int64) {
// TODO Windows
return 0, 0
}

View File

@ -4,32 +4,32 @@ package daemon
import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/container"
)
// getSize returns the real size & virtual size of the container.
func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
func (daemon *Daemon) getSize(containerID string) (int64, int64) {
var (
sizeRw, sizeRootfs int64
err error
)
if err := daemon.Mount(container); err != nil {
logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
rwlayer, err := daemon.layerStore.GetRWLayer(containerID)
if err != nil {
logrus.Errorf("Failed to compute size of container rootfs %v: %v", containerID, err)
return sizeRw, sizeRootfs
}
defer daemon.Unmount(container)
defer daemon.layerStore.ReleaseRWLayer(rwlayer)
sizeRw, err = container.RWLayer.Size()
sizeRw, err = rwlayer.Size()
if err != nil {
logrus.Errorf("Driver %s couldn't return diff size of container %s: %s",
daemon.GraphDriverName(), container.ID, err)
daemon.GraphDriverName(), containerID, err)
// FIXME: GetSize should return an error. Not changing it now in case
// there is a side-effect.
sizeRw = -1
}
if parent := container.RWLayer.Parent(); parent != nil {
if parent := rwlayer.Parent(); parent != nil {
sizeRootfs, err = parent.Size()
if err != nil {
sizeRootfs = -1

View File

@ -36,10 +36,10 @@ func (daemon *Daemon) ContainerInspectCurrent(name string, size bool) (*types.Co
}
container.Lock()
defer container.Unlock()
base, err := daemon.getInspectData(container, size)
base, err := daemon.getInspectData(container)
if err != nil {
container.Unlock()
return nil, err
}
@ -73,6 +73,14 @@ func (daemon *Daemon) ContainerInspectCurrent(name string, size bool) (*types.Co
}
networkSettings.NetworkSettingsBase.Ports = ports
container.Unlock()
if size {
sizeRw, sizeRootFs := daemon.getSize(base.ID)
base.SizeRw = &sizeRw
base.SizeRootFs = &sizeRootFs
}
return &types.ContainerJSON{
ContainerJSONBase: base,
Mounts: mountPoints,
@ -91,7 +99,7 @@ func (daemon *Daemon) containerInspect120(name string) (*v1p20.ContainerJSON, er
container.Lock()
defer container.Unlock()
base, err := daemon.getInspectData(container, false)
base, err := daemon.getInspectData(container)
if err != nil {
return nil, err
}
@ -114,7 +122,7 @@ func (daemon *Daemon) containerInspect120(name string) (*v1p20.ContainerJSON, er
}, nil
}
func (daemon *Daemon) getInspectData(container *container.Container, size bool) (*types.ContainerJSONBase, error) {
func (daemon *Daemon) getInspectData(container *container.Container) (*types.ContainerJSONBase, error) {
// make a copy to play with
hostConfig := *container.HostConfig
@ -168,16 +176,6 @@ func (daemon *Daemon) getInspectData(container *container.Container, size bool)
HostConfig: &hostConfig,
}
var (
sizeRw int64
sizeRootFs int64
)
if size {
sizeRw, sizeRootFs = daemon.getSize(container)
contJSONBase.SizeRw = &sizeRw
contJSONBase.SizeRootFs = &sizeRootFs
}
// Now set any platform-specific fields
contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)

View File

@ -30,7 +30,7 @@ func (daemon *Daemon) containerInspectPre120(name string) (*v1p19.ContainerJSON,
container.Lock()
defer container.Unlock()
base, err := daemon.getInspectData(container, false)
base, err := daemon.getInspectData(container)
if err != nil {
return nil, err
}

View File

@ -208,19 +208,32 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
// reducePsContainer is the basic representation for a container as expected by the ps command.
func (daemon *Daemon) reducePsContainer(container *container.Container, ctx *listContext, reducer containerReducer) (*types.Container, error) {
container.Lock()
defer container.Unlock()
// filter containers to return
action := includeContainerInList(container, ctx)
switch action {
case excludeContainer:
container.Unlock()
return nil, nil
case stopIteration:
container.Unlock()
return nil, errStopIteration
}
// transform internal container struct into api structs
return reducer(container, ctx)
newC, err := reducer(container, ctx)
container.Unlock()
if err != nil {
return nil, err
}
// release lock because size calculation is slow
if ctx.Size {
sizeRw, sizeRootFs := daemon.getSize(newC.ID)
newC.SizeRw = sizeRw
newC.SizeRootFs = sizeRootFs
}
return newC, nil
}
// foldFilter generates the container filter based on the user's filtering options.
@ -642,11 +655,6 @@ func (daemon *Daemon) transformContainer(container *container.Container, ctx *li
}
}
if ctx.Size {
sizeRw, sizeRootFs := daemon.getSize(container)
newC.SizeRw = sizeRw
newC.SizeRootFs = sizeRootFs
}
newC.Labels = container.Config.Labels
newC.Mounts = addMountPoints(container)

View File

@ -16,7 +16,7 @@ import (
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
"github.com/docker/libnetwork"
"github.com/opencontainers/go-digest"
digest "github.com/opencontainers/go-digest"
)
// ContainersPrune removes unused containers
@ -34,7 +34,7 @@ func (daemon *Daemon) ContainersPrune(pruneFilters filters.Args) (*types.Contain
if !until.IsZero() && c.Created.After(until) {
continue
}
cSize, _ := daemon.getSize(c)
cSize, _ := daemon.getSize(c.ID)
// TODO: sets RmLink to true?
err := daemon.ContainerRm(c.ID, &types.ContainerRmConfig{})
if err != nil {