Merge pull request #18506 from nalind/so-much-diffsize

libpod/Container.rootFsSize(): use recorded image sizes
This commit is contained in:
OpenShift Merge Robot
2023-05-10 06:08:12 -04:00
committed by GitHub
5 changed files with 37 additions and 63 deletions

View File

@ -55,10 +55,11 @@ const (
preCheckpointDir = "pre-checkpoint"
)
// rootFsSize gets the size of the container's root filesystem
// A container FS is split into two parts. The first is the top layer, a
// mutable layer, and the rest is the RootFS: the set of immutable layers
// that make up the image on which the container is based.
// rootFsSize gets the size of the container, which can be divided notionally
// into two parts. The first is the part of its size that can be directly
// attributed to its base image, if it has one. The second is the set of
// changes that the container has had made relative to that base image. Both
// parts include some ancillary data, and we count that, too.
func (c *Container) rootFsSize() (int64, error) {
if c.config.Rootfs != "" {
return 0, nil
@ -72,58 +73,33 @@ func (c *Container) rootFsSize() (int64, error) {
return 0, err
}
// Ignore the size of the top layer. The top layer is a mutable RW layer
// and is not considered a part of the rootfs
rwLayer, err := c.runtime.store.Layer(container.LayerID)
if err != nil {
return 0, err
}
layer, err := c.runtime.store.Layer(rwLayer.Parent)
if err != nil {
return 0, err
}
size := int64(0)
for layer.Parent != "" {
layerSize, err := c.runtime.store.DiffSize(layer.Parent, layer.ID)
if err != nil {
return size, fmt.Errorf("getting diffsize of layer %q and its parent %q: %w", layer.ID, layer.Parent, err)
}
size += layerSize
layer, err = c.runtime.store.Layer(layer.Parent)
if container.ImageID != "" {
size, err = c.runtime.store.ImageSize(container.ImageID)
if err != nil {
return 0, err
}
}
// Get the size of the last layer. Has to be outside of the loop
// because the parent of the last layer is "", and lstore.Get("")
// will return an error.
layerSize, err := c.runtime.store.DiffSize(layer.Parent, layer.ID)
layerSize, err := c.runtime.store.ContainerSize(c.ID())
return size + layerSize, err
}
// rwSize gets the size of the mutable top layer of the container.
// rwSize gets the combined size of the writeable layer and any ancillary data
// for a given container.
func (c *Container) rwSize() (int64, error) {
if c.config.Rootfs != "" {
size, err := util.SizeOfPath(c.config.Rootfs)
return int64(size), err
}
container, err := c.runtime.store.Container(c.ID())
layerSize, err := c.runtime.store.ContainerSize(c.ID())
if err != nil {
return 0, err
}
// The top layer of a container is
// the only readable/writeable layer, all others are immutable.
rwLayer, err := c.runtime.store.Layer(container.LayerID)
if err != nil {
return 0, err
}
// Get the size of the top layer by calculating the size of the diff
// between the layer and its parent.
return c.runtime.store.DiffSize(rwLayer.Parent, rwLayer.ID)
return layerSize, nil
}
// bundlePath returns the path to the container's root filesystem - where the OCI spec will be

View File

@ -6,7 +6,7 @@ import (
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/libpod/lock"
"github.com/containers/podman/v4/libpod/plugin"
"github.com/containers/podman/v4/pkg/util"
"github.com/containers/storage/pkg/directory"
)
// Volume is a libpod named volume.
@ -109,7 +109,8 @@ func (v *Volume) Name() string {
// Returns the size on disk of volume
func (v *Volume) Size() (uint64, error) {
return util.SizeOfPath(v.config.MountPoint)
size, err := directory.Size(v.config.MountPoint)
return uint64(size), err
}
// Driver retrieves the volume's driver.

View File

@ -18,6 +18,7 @@ import (
"github.com/containers/podman/v4/pkg/util"
"github.com/containers/podman/v4/utils"
"github.com/containers/storage"
"github.com/containers/storage/pkg/directory"
"github.com/containers/storage/pkg/unshare"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
@ -280,7 +281,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
dfImages = append(dfImages, &report)
}
// Get Containers and iterate them
// Get containers and iterate over them
cons, err := ic.Libpod.GetAllContainers()
if err != nil {
return nil, err
@ -322,7 +323,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
dfContainers = append(dfContainers, &report)
}
// Get volumes and iterate them
// Get volumes and iterate over them
vols, err := ic.Libpod.GetAllVolumes()
if err != nil {
return nil, err
@ -330,7 +331,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
dfVolumes := make([]*entities.SystemDfVolumeReport, 0, len(vols))
for _, v := range vols {
var reclaimableSize uint64
var reclaimableSize int64
mountPoint, err := v.MountPoint()
if err != nil {
return nil, err
@ -341,7 +342,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
// TODO: fix this.
continue
}
volSize, err := util.SizeOfPath(mountPoint)
volSize, err := directory.Size(mountPoint)
if err != nil {
return nil, err
}
@ -355,8 +356,8 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
report := entities.SystemDfVolumeReport{
VolumeName: v.Name(),
Links: len(inUse),
Size: int64(volSize),
ReclaimableSize: int64(reclaimableSize),
Size: volSize,
ReclaimableSize: reclaimableSize,
}
dfVolumes = append(dfVolumes, &report)
}

View File

@ -3,7 +3,6 @@ package util
import (
"errors"
"fmt"
"io/fs"
"math"
"os"
"os/user"
@ -26,6 +25,7 @@ import (
"github.com/containers/podman/v4/pkg/namespaces"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/signal"
"github.com/containers/storage/pkg/directory"
"github.com/containers/storage/pkg/idtools"
stypes "github.com/containers/storage/types"
securejoin "github.com/cyphar/filepath-securejoin"
@ -618,19 +618,10 @@ func LookupUser(name string) (*user.User, error) {
// SizeOfPath determines the file usage of a given path. it was called volumeSize in v1
// and now is made to be generic and take a path instead of a libpod volume
// Deprecated: use github.com/containers/storage/pkg/directory.Size() instead.
func SizeOfPath(path string) (uint64, error) {
var size uint64
err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
if err == nil && !d.IsDir() {
info, err := d.Info()
if err != nil {
return err
}
size += uint64(info.Size())
}
return err
})
return size, err
size, err := directory.Size(path)
return uint64(size), err
}
// EncryptConfig translates encryptionKeys into a EncriptionsConfig structure

View File

@ -55,18 +55,23 @@ function teardown() {
Type | Images | Containers | Local Volumes
Total | 1 | 2 | 0
Active | 1 | 1 | 0
RawSize | ~12...... | 0 | 0
RawReclaimable | 0 | 0 | 0
RawSize | ~12...... | !0 | 0
RawReclaimable | 0 | !0 | 0
Reclaimable | ~\(0%\) | ~\(50%\) | ~\(0%\)
TotalCount | 1 | 2 | 0
Size | ~12.*MB | 0B | 0B
Size | ~12.*MB | !0B | 0B
'
while read -a fields; do
for i in 0 1 2;do
expect="${fields[$((i+1))]}"
actual=$(jq -r ".[$i].${fields[0]}" <<<"$results")
# Do exact-match check, unless the expect term starts with ~
# Do exact-match check, unless the expect term starts with ~ or !
op='='
if [[ "$expect" =~ ^\! ]]; then
op='!='
expect=${expect##\!}
fi
if [[ "$expect" =~ ^~ ]]; then
op='=~'
expect=${expect##\~}