diff --git a/components/engine/daemon/container_operations_windows.go b/components/engine/daemon/container_operations_windows.go index d05f251e05..eece6e1cae 100644 --- a/components/engine/daemon/container_operations_windows.go +++ b/components/engine/daemon/container_operations_windows.go @@ -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 } diff --git a/components/engine/daemon/getsize_unix.go b/components/engine/daemon/getsize_unix.go index 707323a4bf..bd088fd41c 100644 --- a/components/engine/daemon/getsize_unix.go +++ b/components/engine/daemon/getsize_unix.go @@ -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 diff --git a/components/engine/daemon/inspect.go b/components/engine/daemon/inspect.go index 73bc12b2f6..06858223f5 100644 --- a/components/engine/daemon/inspect.go +++ b/components/engine/daemon/inspect.go @@ -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) diff --git a/components/engine/daemon/inspect_unix.go b/components/engine/daemon/inspect_unix.go index 08a82235ad..8342f7cf98 100644 --- a/components/engine/daemon/inspect_unix.go +++ b/components/engine/daemon/inspect_unix.go @@ -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 } diff --git a/components/engine/daemon/list.go b/components/engine/daemon/list.go index 4de5d0ac6f..f104fe05a0 100644 --- a/components/engine/daemon/list.go +++ b/components/engine/daemon/list.go @@ -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) diff --git a/components/engine/daemon/prune.go b/components/engine/daemon/prune.go index 2964983137..1b6ce38027 100644 --- a/components/engine/daemon/prune.go +++ b/components/engine/daemon/prune.go @@ -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 {